/* * ReactOS Explorer * * Copyright 2009 Andrew Hill * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* Implements the logo band of a cabinet window. Most remarkable feature is the animation. */ #include "precomp.h" /* TODO: Add Exec command handlers Properly implement GetBandInfo Fix SetSite to revoke brand band service when site is cleared */ inline void FillSolidRect(HDC dc, const RECT *bounds) { ::ExtTextOut(dc, 0, 0, ETO_OPAQUE, bounds, NULL, 0, NULL); } inline void FillSolidRect(HDC dc, const RECT *bounds, COLORREF clr) { ::SetBkColor(dc, clr); ::ExtTextOut(dc, 0, 0, ETO_OPAQUE, bounds, NULL, 0, NULL); } //static const int gSmallImageSize = 22; static const int gMediumImageSize = 26; static const int gLargeImageSize = 38; static const int gTrueColorResourceBase = 240; static const int g256ColorResourceBase = 245; CBrandBand::CBrandBand() { fProfferCookie = 0; fCurrentFrame = 0; fMaxFrameCount = 0; fImageBitmap = NULL; fBitmapSize = 0; fAdviseCookie = 0; } CBrandBand::~CBrandBand() { DeleteObject(fImageBitmap); } void CBrandBand::StartAnimation() { fCurrentFrame = 0; SetTimer(5678, 30, NULL); } void CBrandBand::StopAnimation() { KillTimer(5678); fCurrentFrame = 0; Invalidate(FALSE); } void CBrandBand::SelectImage() { int screenDepth; RECT clientRect; int clientWidth; int clientHeight; int clientSize; BITMAP bitmapInfo; int resourceID; screenDepth = SHGetCurColorRes(); GetClientRect(&clientRect); clientWidth = clientRect.right - clientRect.left; clientHeight = clientRect.bottom - clientRect.top; clientSize = min(clientWidth, clientHeight); if (screenDepth > 8) resourceID = gTrueColorResourceBase; else resourceID = g256ColorResourceBase; if (clientSize >= gLargeImageSize) resourceID += 2; else if (clientSize >= gMediumImageSize) resourceID += 1; fImageBitmap = LoadBitmap(_AtlBaseModule.GetResourceInstance(), MAKEINTRESOURCE(resourceID)); GetObjectW(fImageBitmap, sizeof(bitmapInfo), &bitmapInfo); fBitmapSize = bitmapInfo.bmWidth; fMaxFrameCount = bitmapInfo.bmHeight / fBitmapSize; } HRESULT STDMETHODCALLTYPE CBrandBand::GetBandInfo(DWORD dwBandID, DWORD dwViewMode, DESKBANDINFO* pdbi) { if (pdbi->dwMask & DBIM_MINSIZE) { pdbi->ptMinSize.x = 38; pdbi->ptMinSize.y = 22; } if (pdbi->dwMask & DBIM_MAXSIZE) { pdbi->ptMaxSize.x = 38; pdbi->ptMaxSize.y = 38; } if (pdbi->dwMask & DBIM_INTEGRAL) { pdbi->ptIntegral.x = 38; pdbi->ptIntegral.y = 38; } if (pdbi->dwMask & DBIM_ACTUAL) { pdbi->ptActual.x = 38; pdbi->ptActual.y = 38; } if (pdbi->dwMask & DBIM_TITLE) wcscpy(pdbi->wszTitle, L""); if (pdbi->dwMask & DBIM_MODEFLAGS) pdbi->dwModeFlags = DBIMF_UNDELETEABLE; if (pdbi->dwMask & DBIM_BKCOLOR) pdbi->crBkgnd = 0; return S_OK; } HRESULT STDMETHODCALLTYPE CBrandBand::SetSite(IUnknown* pUnkSite) { CComPtr browserService; CComPtr oleWindow; CComPtr serviceProvider; CComPtr profferService; HWND parentWindow; HWND hwnd; HRESULT hResult; fSite.Release(); if (pUnkSite == NULL) { hResult = AtlUnadvise(fSite, DIID_DWebBrowserEvents, fAdviseCookie); // TODO: revoke brand band service return S_OK; } // get window handle of parent hResult = pUnkSite->QueryInterface(IID_PPV_ARG(IDockingWindowSite, &fSite)); if (FAILED_UNEXPECTEDLY(hResult)) return hResult; parentWindow = NULL; hResult = pUnkSite->QueryInterface(IID_PPV_ARG(IOleWindow, &oleWindow)); if (SUCCEEDED(hResult)) hResult = oleWindow->GetWindow(&parentWindow); if (!::IsWindow(parentWindow)) return E_FAIL; // create worker window in parent window hwnd = SHCreateWorkerWindowW(0, parentWindow, 0, WS_VISIBLE | WS_CHILD | WS_CLIPSIBLINGS | WS_CLIPCHILDREN, NULL, 0); if (hwnd == NULL) return E_FAIL; SubclassWindow(hwnd); // take advice to watch events hResult = pUnkSite->QueryInterface(IID_PPV_ARG(IServiceProvider, &serviceProvider)); if (SUCCEEDED(hResult)) { hResult = serviceProvider->QueryService( SID_SBrandBand, IID_PPV_ARG(IProfferService, &profferService)); if (SUCCEEDED(hResult)) hResult = profferService->ProfferService(SID_SBrandBand, static_cast(this), &fProfferCookie); hResult = serviceProvider->QueryService(SID_SShellBrowser, IID_PPV_ARG(IBrowserService, &browserService)); if (SUCCEEDED(hResult)) hResult = AtlAdvise(browserService, static_cast(this), DIID_DWebBrowserEvents, &fAdviseCookie); } // ignore any hResult errors up to here - they are nonfatal hResult = S_OK; SelectImage(); return hResult; } HRESULT STDMETHODCALLTYPE CBrandBand::GetSite(REFIID riid, void **ppvSite) { if (ppvSite == NULL) return E_POINTER; if (fSite.p == NULL) { *ppvSite = NULL; return E_FAIL; } return fSite.p->QueryInterface(riid, ppvSite); } HRESULT STDMETHODCALLTYPE CBrandBand::GetWindow(HWND *lphwnd) { if (lphwnd == NULL) return E_POINTER; *lphwnd = m_hWnd; return S_OK; } HRESULT STDMETHODCALLTYPE CBrandBand::ContextSensitiveHelp(BOOL fEnterMode) { return E_NOTIMPL; } HRESULT STDMETHODCALLTYPE CBrandBand::CloseDW(DWORD dwReserved) { ShowDW(FALSE); if (IsWindow()) DestroyWindow(); m_hWnd = NULL; return S_OK; } HRESULT STDMETHODCALLTYPE CBrandBand::ResizeBorderDW( const RECT* prcBorder, IUnknown* punkToolbarSite, BOOL fReserved) { return E_NOTIMPL; } HRESULT STDMETHODCALLTYPE CBrandBand::ShowDW(BOOL fShow) { if (m_hWnd) { if (fShow) ShowWindow(SW_SHOW); else ShowWindow(SW_HIDE); } return S_OK; } HRESULT STDMETHODCALLTYPE CBrandBand::HasFocusIO() { if (GetFocus() == m_hWnd) return S_OK; return S_FALSE; } HRESULT STDMETHODCALLTYPE CBrandBand::TranslateAcceleratorIO(LPMSG lpMsg) { return E_NOTIMPL; } HRESULT STDMETHODCALLTYPE CBrandBand::UIActivateIO(BOOL fActivate, LPMSG lpMsg) { return E_NOTIMPL; } HRESULT STDMETHODCALLTYPE CBrandBand::GetClassID(CLSID *pClassID) { if (pClassID == NULL) return E_POINTER; *pClassID = CLSID_BrandBand; return S_OK; } HRESULT STDMETHODCALLTYPE CBrandBand::IsDirty() { return S_FALSE; } HRESULT STDMETHODCALLTYPE CBrandBand::Load(IStream *pStm) { return E_NOTIMPL; } HRESULT STDMETHODCALLTYPE CBrandBand::Save(IStream *pStm, BOOL fClearDirty) { return E_NOTIMPL; } HRESULT STDMETHODCALLTYPE CBrandBand::GetSizeMax(ULARGE_INTEGER *pcbSize) { return E_NOTIMPL; } HRESULT STDMETHODCALLTYPE CBrandBand::OnWinEvent( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT *theResult) { return E_NOTIMPL; } HRESULT STDMETHODCALLTYPE CBrandBand::IsWindowOwner(HWND hWnd) { if (hWnd == m_hWnd) return S_OK; return S_FALSE; } HRESULT STDMETHODCALLTYPE CBrandBand::QueryStatus( const GUID *pguidCmdGroup, ULONG cCmds, OLECMD prgCmds[ ], OLECMDTEXT *pCmdText) { return E_NOTIMPL; } HRESULT STDMETHODCALLTYPE CBrandBand::Exec(const GUID *pguidCmdGroup, DWORD nCmdID, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut) { if (IsEqualIID(*pguidCmdGroup, CGID_PrivCITCommands)) { } else if (IsEqualIID(*pguidCmdGroup, CGID_BrandCmdGroup)) { switch (nCmdID) { case BBID_STARTANIMATION: StartAnimation(); return S_OK; case BBID_STOPANIMATION: StopAnimation(); return S_OK; } } return E_FAIL; } HRESULT STDMETHODCALLTYPE CBrandBand::QueryService(REFGUID guidService, REFIID riid, void **ppvObject) { CComPtr serviceProvider; HRESULT hResult; if (IsEqualIID(guidService, SID_SBrandBand)) return this->QueryInterface(riid, ppvObject); hResult = fSite->QueryInterface(IID_PPV_ARG(IServiceProvider, &serviceProvider)); if (FAILED_UNEXPECTEDLY(hResult)) return hResult; return serviceProvider->QueryService(guidService, riid, ppvObject); } HRESULT STDMETHODCALLTYPE CBrandBand::GetTypeInfoCount(UINT *pctinfo) { return E_NOTIMPL; } HRESULT STDMETHODCALLTYPE CBrandBand::GetTypeInfo(UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo) { return E_NOTIMPL; } HRESULT STDMETHODCALLTYPE CBrandBand::GetIDsOfNames(REFIID riid, LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId) { return E_NOTIMPL; } HRESULT STDMETHODCALLTYPE CBrandBand::Invoke(DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr) { if (pDispParams == NULL) return E_INVALIDARG; switch (dispIdMember) { case DISPID_DOWNLOADCOMPLETE: StopAnimation(); break; case DISPID_DOWNLOADBEGIN: StartAnimation(); break; } return E_INVALIDARG; } LRESULT CBrandBand::OnSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled) { Invalidate(FALSE); return 0; } LRESULT CBrandBand::OnEraseBkgnd (UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled) { return 1; } LRESULT CBrandBand::OnPaint(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled) { PAINTSTRUCT paintInfo; HDC dc; POINT destinationPoint; HDC sourceDC; HBITMAP oldBitmap; RECT clientRect; RECT tempRect; dc = BeginPaint(&paintInfo); GetClientRect(&clientRect); destinationPoint.x = (clientRect.right - clientRect.left - fBitmapSize) / 2; destinationPoint.y = (clientRect.bottom - clientRect.top - fBitmapSize) / 2; ::SetBkColor(dc, RGB(255, 255, 255)); tempRect.left = 0; tempRect.top = 0; tempRect.right = clientRect.right; tempRect.bottom = destinationPoint.y; FillSolidRect(dc, &tempRect, RGB(255, 255, 255)); tempRect.left = 0; tempRect.top = destinationPoint.y + fBitmapSize; tempRect.right = clientRect.right; tempRect.bottom = clientRect.bottom; FillSolidRect(dc, &paintInfo.rcPaint, RGB(255, 255, 255)); tempRect.left = 0; tempRect.top = destinationPoint.y; tempRect.right = destinationPoint.x; tempRect.bottom = destinationPoint.y + fBitmapSize; FillSolidRect(dc, &paintInfo.rcPaint, RGB(255, 255, 255)); tempRect.left = destinationPoint.x + fBitmapSize; tempRect.top = destinationPoint.y; tempRect.right = clientRect.right; tempRect.bottom = destinationPoint.y + fBitmapSize; FillSolidRect(dc, &paintInfo.rcPaint, RGB(255, 255, 255)); sourceDC = CreateCompatibleDC(dc); oldBitmap = reinterpret_cast(SelectObject(sourceDC, fImageBitmap)); BitBlt(dc, destinationPoint.x, destinationPoint.y, fBitmapSize, fBitmapSize, sourceDC, 0, fCurrentFrame * fBitmapSize, SRCCOPY); SelectObject(sourceDC, oldBitmap); DeleteDC(sourceDC); EndPaint(&paintInfo); return 0; } LRESULT CBrandBand::OnTimer(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled) { fCurrentFrame++; if (fCurrentFrame >= fMaxFrameCount) fCurrentFrame = 0; Invalidate(FALSE); return 0; }