* Sync to trunk HEAD (r53298).
[reactos.git] / dll / win32 / browseui / brandband.cpp
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 #include "precomp.h"
26
27 /*
28 TODO:
29 Add Exec command handlers
30 Properly implement GetBandInfo
31 Fix SetSite to revoke brand band service when site is cleared
32 */
33
34 inline void FillSolidRect(HDC dc, const RECT *bounds)
35 {
36 ::ExtTextOut(dc, 0, 0, ETO_OPAQUE, bounds, NULL, 0, NULL);
37 }
38
39 inline void FillSolidRect(HDC dc, const RECT *bounds, COLORREF clr)
40 {
41 ::SetBkColor(dc, clr);
42 ::ExtTextOut(dc, 0, 0, ETO_OPAQUE, bounds, NULL, 0, NULL);
43 }
44
45 long GetScreenDepth()
46 {
47 HDC tempDC;
48 long depth;
49
50 tempDC = GetDC(NULL);
51 depth = GetDeviceCaps(tempDC, BITSPIXEL) * GetDeviceCaps(tempDC, PLANES);
52 ReleaseDC(NULL, tempDC);
53 return depth;
54 }
55
56 static const int gSmallImageSize = 22;
57 static const int gMediumImageSize = 26;
58 static const int gLargeImageSize = 38;
59
60 static const int gTrueColorResourceBase = 240;
61 static const int g256ColorResourceBase = 245;
62
63 CBrandBand::CBrandBand()
64 {
65 fProfferCookie = 0;
66 fCurrentFrame = 0;
67 fMaxFrameCount = 0;
68 fImageBitmap = NULL;
69 fAdviseCookie = 0;
70 }
71
72 CBrandBand::~CBrandBand()
73 {
74 DeleteObject(fImageBitmap);
75 }
76
77 void CBrandBand::StartAnimation()
78 {
79 fCurrentFrame = 0;
80 SetTimer(5678, 30, NULL);
81 }
82
83 void CBrandBand::StopAnimation()
84 {
85 KillTimer(5678);
86 fCurrentFrame = 0;
87 Invalidate(FALSE);
88 }
89
90 void CBrandBand::SelectImage()
91 {
92 int screenDepth;
93 RECT clientRect;
94 int clientWidth;
95 int clientHeight;
96 int clientSize;
97 HINSTANCE shell32Instance;
98 BITMAP bitmapInfo;
99 int resourceID;
100
101 screenDepth = GetScreenDepth();
102 GetClientRect(&clientRect);
103 clientWidth = clientRect.right - clientRect.left;
104 clientHeight = clientRect.bottom - clientRect.top;
105 clientSize = min(clientWidth, clientHeight);
106 if (screenDepth > 8)
107 resourceID = gTrueColorResourceBase;
108 else
109 resourceID = g256ColorResourceBase;
110 if (clientSize >= gLargeImageSize)
111 resourceID += 2;
112 else if (clientSize >= gMediumImageSize)
113 resourceID += 1;
114 shell32Instance = GetModuleHandle(L"shell32.dll");
115 fImageBitmap = LoadBitmap(shell32Instance, MAKEINTRESOURCE(resourceID));
116 GetObjectW(fImageBitmap, sizeof(bitmapInfo), &bitmapInfo);
117 fBitmapSize = bitmapInfo.bmWidth;
118 fMaxFrameCount = bitmapInfo.bmHeight / fBitmapSize;
119 }
120
121 HRESULT STDMETHODCALLTYPE CBrandBand::GetBandInfo(DWORD dwBandID, DWORD dwViewMode, DESKBANDINFO* pdbi)
122 {
123 if (pdbi->dwMask & DBIM_MINSIZE)
124 {
125 pdbi->ptMinSize.x = 38;
126 pdbi->ptMinSize.y = 22;
127 }
128 if (pdbi->dwMask & DBIM_MAXSIZE)
129 {
130 pdbi->ptMaxSize.x = 38;
131 pdbi->ptMaxSize.y = 38;
132 }
133 if (pdbi->dwMask & DBIM_INTEGRAL)
134 {
135 pdbi->ptIntegral.x = 38;
136 pdbi->ptIntegral.y = 38;
137 }
138 if (pdbi->dwMask & DBIM_ACTUAL)
139 {
140 pdbi->ptActual.x = 38;
141 pdbi->ptActual.y = 38;
142 }
143 if (pdbi->dwMask & DBIM_TITLE)
144 wcscpy(pdbi->wszTitle, L"");
145 if (pdbi->dwMask & DBIM_MODEFLAGS)
146 pdbi->dwModeFlags = DBIMF_UNDELETEABLE;
147 if (pdbi->dwMask & DBIM_BKCOLOR)
148 pdbi->crBkgnd = 0;
149 return S_OK;
150 }
151
152 HRESULT STDMETHODCALLTYPE CBrandBand::SetSite(IUnknown* pUnkSite)
153 {
154 CComPtr<IBrowserService> browserService;
155 CComPtr<IOleWindow> oleWindow;
156 CComPtr<IServiceProvider> serviceProvider;
157 CComPtr<IProfferService> profferService;
158 HWND parentWindow;
159 HWND hwnd;
160 HRESULT hResult;
161
162 fSite.Release();
163 if (pUnkSite == NULL)
164 {
165 hResult = AtlUnadvise(fSite, DIID_DWebBrowserEvents, fAdviseCookie);
166 // TODO: revoke brand band service
167 return S_OK;
168 }
169 hResult = pUnkSite->QueryInterface(IID_IDockingWindowSite, (void **)&fSite);
170 if (FAILED(hResult))
171 return hResult;
172 parentWindow = NULL;
173 hResult = pUnkSite->QueryInterface(IID_IOleWindow, (void **)&oleWindow);
174 if (SUCCEEDED(hResult))
175 hResult = oleWindow->GetWindow(&parentWindow);
176 if (!::IsWindow(parentWindow))
177 return E_FAIL;
178
179 hwnd = SHCreateWorkerWindowW(0, parentWindow, 0, WS_VISIBLE | WS_CHILD | WS_CLIPSIBLINGS | WS_CLIPCHILDREN, NULL, 0);
180 if (hwnd == NULL)
181 return E_FAIL;
182 SubclassWindow(hwnd);
183 hResult = pUnkSite->QueryInterface(IID_IServiceProvider, (void **)&serviceProvider);
184 if (SUCCEEDED(hResult))
185 {
186 hResult = serviceProvider->QueryService(SID_SBrandBand, IID_IProfferService, (void **)&profferService);
187 if (SUCCEEDED(hResult))
188 hResult = profferService->ProfferService(SID_SBrandBand, (IServiceProvider *)this, &fProfferCookie);
189 hResult = serviceProvider->QueryService(SID_SShellBrowser, IID_IBrowserService, (void **)&browserService);
190 if (SUCCEEDED(hResult))
191 hResult = AtlAdvise(browserService, (IDispatch *)this, DIID_DWebBrowserEvents, &fAdviseCookie);
192 }
193 // ignore any hResult errors up to here - they are nonfatal
194 hResult = S_OK;
195 SelectImage();
196 return hResult;
197 }
198
199 HRESULT STDMETHODCALLTYPE CBrandBand::GetSite(REFIID riid, void **ppvSite)
200 {
201 if (ppvSite == NULL)
202 return E_POINTER;
203 if (fSite.p == NULL)
204 {
205 *ppvSite = NULL;
206 return E_FAIL;
207 }
208 return fSite.p->QueryInterface(riid, ppvSite);
209 }
210
211 HRESULT STDMETHODCALLTYPE CBrandBand::GetWindow(HWND *lphwnd)
212 {
213 if (lphwnd == NULL)
214 return E_POINTER;
215 *lphwnd = m_hWnd;
216 return S_OK;
217 }
218
219 HRESULT STDMETHODCALLTYPE CBrandBand::ContextSensitiveHelp(BOOL fEnterMode)
220 {
221 return E_NOTIMPL;
222 }
223
224 HRESULT STDMETHODCALLTYPE CBrandBand::CloseDW(DWORD dwReserved)
225 {
226 ShowDW(FALSE);
227
228 if (IsWindow())
229 DestroyWindow();
230
231 m_hWnd = NULL;
232
233 return S_OK;
234 }
235
236 HRESULT STDMETHODCALLTYPE CBrandBand::ResizeBorderDW(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(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT *theResult)
299 {
300 return E_NOTIMPL;
301 }
302
303 HRESULT STDMETHODCALLTYPE CBrandBand::IsWindowOwner(HWND hWnd)
304 {
305 if (hWnd == m_hWnd)
306 return S_OK;
307 return S_FALSE;
308 }
309
310 HRESULT STDMETHODCALLTYPE CBrandBand::QueryStatus(const GUID *pguidCmdGroup, ULONG cCmds, OLECMD prgCmds[ ], OLECMDTEXT *pCmdText)
311 {
312 return E_NOTIMPL;
313 }
314
315 HRESULT STDMETHODCALLTYPE CBrandBand::Exec(const GUID *pguidCmdGroup, DWORD nCmdID, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
316 {
317 if (IsEqualIID(*pguidCmdGroup, CGID_PrivCITCommands))
318 {
319 }
320 else if (IsEqualIID(*pguidCmdGroup, CGID_BrandCmdGroup))
321 {
322 switch (nCmdID)
323 {
324 case BBID_STARTANIMATION:
325 StartAnimation();
326 return S_OK;
327 case BBID_STOPANIMATION:
328 StopAnimation();
329 return S_OK;
330 }
331 }
332 return E_FAIL;
333 }
334
335 HRESULT STDMETHODCALLTYPE CBrandBand::QueryService(REFGUID guidService, REFIID riid, void **ppvObject)
336 {
337 CComPtr<IServiceProvider> serviceProvider;
338 HRESULT hResult;
339
340 if (IsEqualIID(guidService, SID_SBrandBand))
341 return this->QueryInterface(riid, ppvObject);
342 hResult = fSite->QueryInterface(IID_IServiceProvider, (void **)&serviceProvider);
343 if (FAILED (hResult))
344 return hResult;
345 return serviceProvider->QueryService(guidService, riid, ppvObject);
346 }
347
348 HRESULT STDMETHODCALLTYPE CBrandBand::GetTypeInfoCount(UINT *pctinfo)
349 {
350 return E_NOTIMPL;
351 }
352
353 HRESULT STDMETHODCALLTYPE CBrandBand::GetTypeInfo(UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo)
354 {
355 return E_NOTIMPL;
356 }
357
358 HRESULT STDMETHODCALLTYPE CBrandBand::GetIDsOfNames(REFIID riid, LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
359 {
360 return E_NOTIMPL;
361 }
362
363 HRESULT STDMETHODCALLTYPE CBrandBand::Invoke(DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
364 {
365 if (pDispParams == NULL)
366 return E_INVALIDARG;
367 switch (dispIdMember)
368 {
369 case DISPID_DOWNLOADCOMPLETE:
370 StopAnimation();
371 break;
372 case DISPID_DOWNLOADBEGIN:
373 StartAnimation();
374 break;
375 }
376 return E_INVALIDARG;
377 }
378
379 LRESULT CBrandBand::OnSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
380 {
381 Invalidate(FALSE);
382 return 0;
383 }
384
385 LRESULT CBrandBand::OnEraseBkgnd (UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
386 {
387 return 1;
388 }
389
390 LRESULT CBrandBand::OnPaint(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
391 {
392 PAINTSTRUCT paintInfo;
393 HDC dc;
394 POINT destinationPoint;
395 HDC sourceDC;
396 HBITMAP oldBitmap;
397 RECT clientRect;
398 RECT tempRect;
399
400 dc = BeginPaint(&paintInfo);
401 GetClientRect(&clientRect);
402
403 destinationPoint.x = (clientRect.right - clientRect.left - fBitmapSize) / 2;
404 destinationPoint.y = (clientRect.bottom - clientRect.top - fBitmapSize) / 2;
405
406 ::SetBkColor(dc, RGB(255, 255, 255));
407
408 tempRect.left = 0;
409 tempRect.top = 0;
410 tempRect.right = clientRect.right;
411 tempRect.bottom = destinationPoint.y;
412 FillSolidRect(dc, &tempRect, RGB(255, 255, 255));
413
414 tempRect.left = 0;
415 tempRect.top = destinationPoint.y + fBitmapSize;
416 tempRect.right = clientRect.right;
417 tempRect.bottom = clientRect.bottom;
418 FillSolidRect(dc, &paintInfo.rcPaint, RGB(255, 255, 255));
419
420 tempRect.left = 0;
421 tempRect.top = destinationPoint.y;
422 tempRect.right = destinationPoint.x;
423 tempRect.bottom = destinationPoint.y + fBitmapSize;
424 FillSolidRect(dc, &paintInfo.rcPaint, RGB(255, 255, 255));
425
426 tempRect.left = destinationPoint.x + fBitmapSize;
427 tempRect.top = destinationPoint.y;
428 tempRect.right = clientRect.right;
429 tempRect.bottom = destinationPoint.y + fBitmapSize;
430 FillSolidRect(dc, &paintInfo.rcPaint, RGB(255, 255, 255));
431
432 sourceDC = CreateCompatibleDC(dc);
433 oldBitmap = (HBITMAP)SelectObject(sourceDC, fImageBitmap);
434
435 BitBlt(dc, destinationPoint.x, destinationPoint.y, fBitmapSize, fBitmapSize, sourceDC, 0, fCurrentFrame * fBitmapSize, SRCCOPY);
436
437 SelectObject(sourceDC, oldBitmap);
438 DeleteDC(sourceDC);
439
440 EndPaint(&paintInfo);
441 return 0;
442 }
443
444 LRESULT CBrandBand::OnTimer(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
445 {
446 fCurrentFrame++;
447 if (fCurrentFrame >= fMaxFrameCount)
448 fCurrentFrame = 0;
449 Invalidate(FALSE);
450 return 0;
451 }
452
453 HRESULT CreateBrandBand(REFIID riid, void **ppv)
454 {
455 CComObject<CBrandBand> *theMenuBar;
456 HRESULT hResult;
457
458 if (ppv == NULL)
459 return E_POINTER;
460 *ppv = NULL;
461 ATLTRY (theMenuBar = new CComObject<CBrandBand>);
462 if (theMenuBar == NULL)
463 return E_OUTOFMEMORY;
464 hResult = theMenuBar->QueryInterface (riid, (void **)ppv);
465 if (FAILED (hResult))
466 {
467 delete theMenuBar;
468 return hResult;
469 }
470 return S_OK;
471 }