1 /* 2 * ReactOS Explorer 3 * 4 * Copyright 2009 Andrew Hill <ash77 at domain reactos.org> 5 * 6 * This library is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU Lesser General Public 8 * License as published by the Free Software Foundation; either 9 * version 2.1 of the License, or (at your option) any later version. 10 * 11 * This library is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 * Lesser General Public License for more details. 15 * 16 * You should have received a copy of the GNU Lesser General Public 17 * License along with this library; if not, write to the Free Software 18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 */ 20 21 /* 22 Implements the logo band of a cabinet window. Most remarkable feature is the 23 animation. 24 */ 25 26 #include "precomp.h" 27 28 /* 29 TODO: 30 Add Exec command handlers 31 Properly implement GetBandInfo 32 Fix SetSite to revoke brand band service when site is cleared 33 */ 34 35 inline void FillSolidRect(HDC dc, const RECT *bounds) 36 { 37 ::ExtTextOut(dc, 0, 0, ETO_OPAQUE, bounds, NULL, 0, NULL); 38 } 39 40 inline void FillSolidRect(HDC dc, const RECT *bounds, COLORREF clr) 41 { 42 ::SetBkColor(dc, clr); 43 ::ExtTextOut(dc, 0, 0, ETO_OPAQUE, bounds, NULL, 0, NULL); 44 } 45 46 //static const int gSmallImageSize = 22; 47 static const int gMediumImageSize = 26; 48 static const int gLargeImageSize = 38; 49 50 static const int gTrueColorResourceBase = 240; 51 static const int g256ColorResourceBase = 245; 52 53 CBrandBand::CBrandBand() 54 { 55 fProfferCookie = 0; 56 fCurrentFrame = 0; 57 fMaxFrameCount = 0; 58 fImageBitmap = NULL; 59 fBitmapSize = 0; 60 fAdviseCookie = 0; 61 } 62 63 CBrandBand::~CBrandBand() 64 { 65 DeleteObject(fImageBitmap); 66 } 67 68 void CBrandBand::StartAnimation() 69 { 70 fCurrentFrame = 0; 71 SetTimer(5678, 30, NULL); 72 } 73 74 void CBrandBand::StopAnimation() 75 { 76 KillTimer(5678); 77 fCurrentFrame = 0; 78 Invalidate(FALSE); 79 } 80 81 void CBrandBand::SelectImage() 82 { 83 int screenDepth; 84 RECT clientRect; 85 int clientWidth; 86 int clientHeight; 87 int clientSize; 88 BITMAP bitmapInfo; 89 int resourceID; 90 91 screenDepth = SHGetCurColorRes(); 92 GetClientRect(&clientRect); 93 clientWidth = clientRect.right - clientRect.left; 94 clientHeight = clientRect.bottom - clientRect.top; 95 clientSize = min(clientWidth, clientHeight); 96 if (screenDepth > 8) 97 resourceID = gTrueColorResourceBase; 98 else 99 resourceID = g256ColorResourceBase; 100 if (clientSize >= gLargeImageSize) 101 resourceID += 2; 102 else if (clientSize >= gMediumImageSize) 103 resourceID += 1; 104 fImageBitmap = LoadBitmap(_AtlBaseModule.GetResourceInstance(), MAKEINTRESOURCE(resourceID)); 105 GetObjectW(fImageBitmap, sizeof(bitmapInfo), &bitmapInfo); 106 fBitmapSize = bitmapInfo.bmWidth; 107 fMaxFrameCount = bitmapInfo.bmHeight / fBitmapSize; 108 } 109 110 HRESULT STDMETHODCALLTYPE CBrandBand::GetBandInfo(DWORD dwBandID, DWORD dwViewMode, DESKBANDINFO* pdbi) 111 { 112 if (pdbi->dwMask & DBIM_MINSIZE) 113 { 114 pdbi->ptMinSize.x = 38; 115 pdbi->ptMinSize.y = 22; 116 } 117 if (pdbi->dwMask & DBIM_MAXSIZE) 118 { 119 pdbi->ptMaxSize.x = 38; 120 pdbi->ptMaxSize.y = 38; 121 } 122 if (pdbi->dwMask & DBIM_INTEGRAL) 123 { 124 pdbi->ptIntegral.x = 38; 125 pdbi->ptIntegral.y = 38; 126 } 127 if (pdbi->dwMask & DBIM_ACTUAL) 128 { 129 pdbi->ptActual.x = 38; 130 pdbi->ptActual.y = 38; 131 } 132 if (pdbi->dwMask & DBIM_TITLE) 133 wcscpy(pdbi->wszTitle, L""); 134 if (pdbi->dwMask & DBIM_MODEFLAGS) 135 pdbi->dwModeFlags = DBIMF_UNDELETEABLE; 136 if (pdbi->dwMask & DBIM_BKCOLOR) 137 pdbi->crBkgnd = 0; 138 return S_OK; 139 } 140 141 HRESULT STDMETHODCALLTYPE CBrandBand::SetSite(IUnknown* pUnkSite) 142 { 143 CComPtr<IBrowserService> browserService; 144 CComPtr<IOleWindow> oleWindow; 145 CComPtr<IServiceProvider> serviceProvider; 146 CComPtr<IProfferService> profferService; 147 HWND parentWindow; 148 HWND hwnd; 149 HRESULT hResult; 150 151 fSite.Release(); 152 if (pUnkSite == NULL) 153 { 154 hResult = AtlUnadvise(fSite, DIID_DWebBrowserEvents, fAdviseCookie); 155 // TODO: revoke brand band service 156 return S_OK; 157 } 158 159 // get window handle of parent 160 hResult = pUnkSite->QueryInterface(IID_PPV_ARG(IDockingWindowSite, &fSite)); 161 if (FAILED_UNEXPECTEDLY(hResult)) 162 return hResult; 163 parentWindow = NULL; 164 hResult = pUnkSite->QueryInterface(IID_PPV_ARG(IOleWindow, &oleWindow)); 165 if (SUCCEEDED(hResult)) 166 hResult = oleWindow->GetWindow(&parentWindow); 167 if (!::IsWindow(parentWindow)) 168 return E_FAIL; 169 170 // create worker window in parent window 171 hwnd = SHCreateWorkerWindowW(0, parentWindow, 0, 172 WS_VISIBLE | WS_CHILD | WS_CLIPSIBLINGS | WS_CLIPCHILDREN, NULL, 0); 173 if (hwnd == NULL) 174 return E_FAIL; 175 SubclassWindow(hwnd); 176 177 // take advice to watch events 178 hResult = pUnkSite->QueryInterface(IID_PPV_ARG(IServiceProvider, &serviceProvider)); 179 if (SUCCEEDED(hResult)) 180 { 181 hResult = serviceProvider->QueryService( 182 SID_SBrandBand, IID_PPV_ARG(IProfferService, &profferService)); 183 if (SUCCEEDED(hResult)) 184 hResult = profferService->ProfferService(SID_SBrandBand, 185 static_cast<IServiceProvider *>(this), &fProfferCookie); 186 hResult = serviceProvider->QueryService(SID_SShellBrowser, 187 IID_PPV_ARG(IBrowserService, &browserService)); 188 if (SUCCEEDED(hResult)) 189 hResult = AtlAdvise(browserService, static_cast<IDispatch *>(this), DIID_DWebBrowserEvents, &fAdviseCookie); 190 } 191 192 // ignore any hResult errors up to here - they are nonfatal 193 hResult = S_OK; 194 SelectImage(); 195 return hResult; 196 } 197 198 HRESULT STDMETHODCALLTYPE CBrandBand::GetSite(REFIID riid, void **ppvSite) 199 { 200 if (ppvSite == NULL) 201 return E_POINTER; 202 if (fSite.p == NULL) 203 { 204 *ppvSite = NULL; 205 return E_FAIL; 206 } 207 return fSite.p->QueryInterface(riid, ppvSite); 208 } 209 210 HRESULT STDMETHODCALLTYPE CBrandBand::GetWindow(HWND *lphwnd) 211 { 212 if (lphwnd == NULL) 213 return E_POINTER; 214 *lphwnd = m_hWnd; 215 return S_OK; 216 } 217 218 HRESULT STDMETHODCALLTYPE CBrandBand::ContextSensitiveHelp(BOOL fEnterMode) 219 { 220 return E_NOTIMPL; 221 } 222 223 HRESULT STDMETHODCALLTYPE CBrandBand::CloseDW(DWORD dwReserved) 224 { 225 ShowDW(FALSE); 226 227 if (IsWindow()) 228 DestroyWindow(); 229 230 m_hWnd = NULL; 231 232 return S_OK; 233 } 234 235 HRESULT STDMETHODCALLTYPE CBrandBand::ResizeBorderDW( 236 const RECT* prcBorder, IUnknown* punkToolbarSite, BOOL fReserved) 237 { 238 return E_NOTIMPL; 239 } 240 241 HRESULT STDMETHODCALLTYPE CBrandBand::ShowDW(BOOL fShow) 242 { 243 if (m_hWnd) 244 { 245 if (fShow) 246 ShowWindow(SW_SHOW); 247 else 248 ShowWindow(SW_HIDE); 249 } 250 return S_OK; 251 } 252 253 HRESULT STDMETHODCALLTYPE CBrandBand::HasFocusIO() 254 { 255 if (GetFocus() == m_hWnd) 256 return S_OK; 257 return S_FALSE; 258 } 259 260 HRESULT STDMETHODCALLTYPE CBrandBand::TranslateAcceleratorIO(LPMSG lpMsg) 261 { 262 return E_NOTIMPL; 263 } 264 265 HRESULT STDMETHODCALLTYPE CBrandBand::UIActivateIO(BOOL fActivate, LPMSG lpMsg) 266 { 267 return E_NOTIMPL; 268 } 269 270 HRESULT STDMETHODCALLTYPE CBrandBand::GetClassID(CLSID *pClassID) 271 { 272 if (pClassID == NULL) 273 return E_POINTER; 274 *pClassID = CLSID_BrandBand; 275 return S_OK; 276 } 277 278 HRESULT STDMETHODCALLTYPE CBrandBand::IsDirty() 279 { 280 return S_FALSE; 281 } 282 283 HRESULT STDMETHODCALLTYPE CBrandBand::Load(IStream *pStm) 284 { 285 return E_NOTIMPL; 286 } 287 288 HRESULT STDMETHODCALLTYPE CBrandBand::Save(IStream *pStm, BOOL fClearDirty) 289 { 290 return E_NOTIMPL; 291 } 292 293 HRESULT STDMETHODCALLTYPE CBrandBand::GetSizeMax(ULARGE_INTEGER *pcbSize) 294 { 295 return E_NOTIMPL; 296 } 297 298 HRESULT STDMETHODCALLTYPE CBrandBand::OnWinEvent( 299 HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT *theResult) 300 { 301 return E_NOTIMPL; 302 } 303 304 HRESULT STDMETHODCALLTYPE CBrandBand::IsWindowOwner(HWND hWnd) 305 { 306 if (hWnd == m_hWnd) 307 return S_OK; 308 return S_FALSE; 309 } 310 311 HRESULT STDMETHODCALLTYPE CBrandBand::QueryStatus( 312 const GUID *pguidCmdGroup, ULONG cCmds, OLECMD prgCmds[ ], OLECMDTEXT *pCmdText) 313 { 314 return E_NOTIMPL; 315 } 316 317 HRESULT STDMETHODCALLTYPE CBrandBand::Exec(const GUID *pguidCmdGroup, 318 DWORD nCmdID, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut) 319 { 320 if (IsEqualIID(*pguidCmdGroup, CGID_PrivCITCommands)) 321 { 322 } 323 else if (IsEqualIID(*pguidCmdGroup, CGID_BrandCmdGroup)) 324 { 325 switch (nCmdID) 326 { 327 case BBID_STARTANIMATION: 328 StartAnimation(); 329 return S_OK; 330 case BBID_STOPANIMATION: 331 StopAnimation(); 332 return S_OK; 333 } 334 } 335 return E_FAIL; 336 } 337 338 HRESULT STDMETHODCALLTYPE CBrandBand::QueryService(REFGUID guidService, REFIID riid, void **ppvObject) 339 { 340 CComPtr<IServiceProvider> serviceProvider; 341 HRESULT hResult; 342 343 if (IsEqualIID(guidService, SID_SBrandBand)) 344 return this->QueryInterface(riid, ppvObject); 345 hResult = fSite->QueryInterface(IID_PPV_ARG(IServiceProvider, &serviceProvider)); 346 if (FAILED_UNEXPECTEDLY(hResult)) 347 return hResult; 348 return serviceProvider->QueryService(guidService, riid, ppvObject); 349 } 350 351 HRESULT STDMETHODCALLTYPE CBrandBand::GetTypeInfoCount(UINT *pctinfo) 352 { 353 return E_NOTIMPL; 354 } 355 356 HRESULT STDMETHODCALLTYPE CBrandBand::GetTypeInfo(UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo) 357 { 358 return E_NOTIMPL; 359 } 360 361 HRESULT STDMETHODCALLTYPE CBrandBand::GetIDsOfNames(REFIID riid, LPOLESTR *rgszNames, UINT cNames, 362 LCID lcid, DISPID *rgDispId) 363 { 364 return E_NOTIMPL; 365 } 366 367 HRESULT STDMETHODCALLTYPE CBrandBand::Invoke(DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags, 368 DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr) 369 { 370 if (pDispParams == NULL) 371 return E_INVALIDARG; 372 switch (dispIdMember) 373 { 374 case DISPID_DOWNLOADCOMPLETE: 375 StopAnimation(); 376 break; 377 case DISPID_DOWNLOADBEGIN: 378 StartAnimation(); 379 break; 380 } 381 return E_INVALIDARG; 382 } 383 384 LRESULT CBrandBand::OnSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled) 385 { 386 Invalidate(FALSE); 387 return 0; 388 } 389 390 LRESULT CBrandBand::OnEraseBkgnd (UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled) 391 { 392 return 1; 393 } 394 395 LRESULT CBrandBand::OnPaint(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled) 396 { 397 PAINTSTRUCT paintInfo; 398 HDC dc; 399 POINT destinationPoint; 400 HDC sourceDC; 401 HBITMAP oldBitmap; 402 RECT clientRect; 403 RECT tempRect; 404 405 dc = BeginPaint(&paintInfo); 406 GetClientRect(&clientRect); 407 408 destinationPoint.x = (clientRect.right - clientRect.left - fBitmapSize) / 2; 409 destinationPoint.y = (clientRect.bottom - clientRect.top - fBitmapSize) / 2; 410 411 ::SetBkColor(dc, RGB(255, 255, 255)); 412 413 tempRect.left = 0; 414 tempRect.top = 0; 415 tempRect.right = clientRect.right; 416 tempRect.bottom = destinationPoint.y; 417 FillSolidRect(dc, &tempRect, RGB(255, 255, 255)); 418 419 tempRect.left = 0; 420 tempRect.top = destinationPoint.y + fBitmapSize; 421 tempRect.right = clientRect.right; 422 tempRect.bottom = clientRect.bottom; 423 FillSolidRect(dc, &paintInfo.rcPaint, RGB(255, 255, 255)); 424 425 tempRect.left = 0; 426 tempRect.top = destinationPoint.y; 427 tempRect.right = destinationPoint.x; 428 tempRect.bottom = destinationPoint.y + fBitmapSize; 429 FillSolidRect(dc, &paintInfo.rcPaint, RGB(255, 255, 255)); 430 431 tempRect.left = destinationPoint.x + fBitmapSize; 432 tempRect.top = destinationPoint.y; 433 tempRect.right = clientRect.right; 434 tempRect.bottom = destinationPoint.y + fBitmapSize; 435 FillSolidRect(dc, &paintInfo.rcPaint, RGB(255, 255, 255)); 436 437 sourceDC = CreateCompatibleDC(dc); 438 oldBitmap = reinterpret_cast<HBITMAP>(SelectObject(sourceDC, fImageBitmap)); 439 440 BitBlt(dc, destinationPoint.x, destinationPoint.y, fBitmapSize, fBitmapSize, sourceDC, 0, fCurrentFrame * fBitmapSize, SRCCOPY); 441 442 SelectObject(sourceDC, oldBitmap); 443 DeleteDC(sourceDC); 444 445 EndPaint(&paintInfo); 446 return 0; 447 } 448 449 LRESULT CBrandBand::OnTimer(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled) 450 { 451 fCurrentFrame++; 452 if (fCurrentFrame >= fMaxFrameCount) 453 fCurrentFrame = 0; 454 Invalidate(FALSE); 455 return 0; 456 } 457