Synchronize up to trunk's revision r57756.
[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 fBitmapSize = 0;
70 fAdviseCookie = 0;
71 }
72
73 CBrandBand::~CBrandBand()
74 {
75 DeleteObject(fImageBitmap);
76 }
77
78 void CBrandBand::StartAnimation()
79 {
80 fCurrentFrame = 0;
81 SetTimer(5678, 30, NULL);
82 }
83
84 void CBrandBand::StopAnimation()
85 {
86 KillTimer(5678);
87 fCurrentFrame = 0;
88 Invalidate(FALSE);
89 }
90
91 void CBrandBand::SelectImage()
92 {
93 int screenDepth;
94 RECT clientRect;
95 int clientWidth;
96 int clientHeight;
97 int clientSize;
98 HINSTANCE shell32Instance;
99 BITMAP bitmapInfo;
100 int resourceID;
101
102 screenDepth = GetScreenDepth();
103 GetClientRect(&clientRect);
104 clientWidth = clientRect.right - clientRect.left;
105 clientHeight = clientRect.bottom - clientRect.top;
106 clientSize = min(clientWidth, clientHeight);
107 if (screenDepth > 8)
108 resourceID = gTrueColorResourceBase;
109 else
110 resourceID = g256ColorResourceBase;
111 if (clientSize >= gLargeImageSize)
112 resourceID += 2;
113 else if (clientSize >= gMediumImageSize)
114 resourceID += 1;
115 shell32Instance = GetModuleHandle(L"shell32.dll");
116 fImageBitmap = LoadBitmap(shell32Instance, MAKEINTRESOURCE(resourceID));
117 GetObjectW(fImageBitmap, sizeof(bitmapInfo), &bitmapInfo);
118 fBitmapSize = bitmapInfo.bmWidth;
119 fMaxFrameCount = bitmapInfo.bmHeight / fBitmapSize;
120 }
121
122 HRESULT STDMETHODCALLTYPE CBrandBand::GetBandInfo(DWORD dwBandID, DWORD dwViewMode, DESKBANDINFO* pdbi)
123 {
124 if (pdbi->dwMask & DBIM_MINSIZE)
125 {
126 pdbi->ptMinSize.x = 38;
127 pdbi->ptMinSize.y = 22;
128 }
129 if (pdbi->dwMask & DBIM_MAXSIZE)
130 {
131 pdbi->ptMaxSize.x = 38;
132 pdbi->ptMaxSize.y = 38;
133 }
134 if (pdbi->dwMask & DBIM_INTEGRAL)
135 {
136 pdbi->ptIntegral.x = 38;
137 pdbi->ptIntegral.y = 38;
138 }
139 if (pdbi->dwMask & DBIM_ACTUAL)
140 {
141 pdbi->ptActual.x = 38;
142 pdbi->ptActual.y = 38;
143 }
144 if (pdbi->dwMask & DBIM_TITLE)
145 wcscpy(pdbi->wszTitle, L"");
146 if (pdbi->dwMask & DBIM_MODEFLAGS)
147 pdbi->dwModeFlags = DBIMF_UNDELETEABLE;
148 if (pdbi->dwMask & DBIM_BKCOLOR)
149 pdbi->crBkgnd = 0;
150 return S_OK;
151 }
152
153 HRESULT STDMETHODCALLTYPE CBrandBand::SetSite(IUnknown* pUnkSite)
154 {
155 CComPtr<IBrowserService> browserService;
156 CComPtr<IOleWindow> oleWindow;
157 CComPtr<IServiceProvider> serviceProvider;
158 CComPtr<IProfferService> profferService;
159 HWND parentWindow;
160 HWND hwnd;
161 HRESULT hResult;
162
163 fSite.Release();
164 if (pUnkSite == NULL)
165 {
166 hResult = AtlUnadvise(fSite, DIID_DWebBrowserEvents, fAdviseCookie);
167 // TODO: revoke brand band service
168 return S_OK;
169 }
170 hResult = pUnkSite->QueryInterface(IID_IDockingWindowSite, (void **)&fSite);
171 if (FAILED(hResult))
172 return hResult;
173 parentWindow = NULL;
174 hResult = pUnkSite->QueryInterface(IID_IOleWindow, (void **)&oleWindow);
175 if (SUCCEEDED(hResult))
176 hResult = oleWindow->GetWindow(&parentWindow);
177 if (!::IsWindow(parentWindow))
178 return E_FAIL;
179
180 hwnd = SHCreateWorkerWindowW(0, parentWindow, 0, WS_VISIBLE | WS_CHILD | WS_CLIPSIBLINGS | WS_CLIPCHILDREN, NULL, 0);
181 if (hwnd == NULL)
182 return E_FAIL;
183 SubclassWindow(hwnd);
184 hResult = pUnkSite->QueryInterface(IID_IServiceProvider, (void **)&serviceProvider);
185 if (SUCCEEDED(hResult))
186 {
187 hResult = serviceProvider->QueryService(SID_SBrandBand, IID_IProfferService, (void **)&profferService);
188 if (SUCCEEDED(hResult))
189 hResult = profferService->ProfferService(SID_SBrandBand, (IServiceProvider *)this, &fProfferCookie);
190 hResult = serviceProvider->QueryService(SID_SShellBrowser, IID_IBrowserService, (void **)&browserService);
191 if (SUCCEEDED(hResult))
192 hResult = AtlAdvise(browserService, (IDispatch *)this, DIID_DWebBrowserEvents, &fAdviseCookie);
193 }
194 // ignore any hResult errors up to here - they are nonfatal
195 hResult = S_OK;
196 SelectImage();
197 return hResult;
198 }
199
200 HRESULT STDMETHODCALLTYPE CBrandBand::GetSite(REFIID riid, void **ppvSite)
201 {
202 if (ppvSite == NULL)
203 return E_POINTER;
204 if (fSite.p == NULL)
205 {
206 *ppvSite = NULL;
207 return E_FAIL;
208 }
209 return fSite.p->QueryInterface(riid, ppvSite);
210 }
211
212 HRESULT STDMETHODCALLTYPE CBrandBand::GetWindow(HWND *lphwnd)
213 {
214 if (lphwnd == NULL)
215 return E_POINTER;
216 *lphwnd = m_hWnd;
217 return S_OK;
218 }
219
220 HRESULT STDMETHODCALLTYPE CBrandBand::ContextSensitiveHelp(BOOL fEnterMode)
221 {
222 return E_NOTIMPL;
223 }
224
225 HRESULT STDMETHODCALLTYPE CBrandBand::CloseDW(DWORD dwReserved)
226 {
227 ShowDW(FALSE);
228
229 if (IsWindow())
230 DestroyWindow();
231
232 m_hWnd = NULL;
233
234 return S_OK;
235 }
236
237 HRESULT STDMETHODCALLTYPE CBrandBand::ResizeBorderDW(const RECT* prcBorder, IUnknown* punkToolbarSite, BOOL fReserved)
238 {
239 return E_NOTIMPL;
240 }
241
242 HRESULT STDMETHODCALLTYPE CBrandBand::ShowDW(BOOL fShow)
243 {
244 if (m_hWnd)
245 {
246 if (fShow)
247 ShowWindow(SW_SHOW);
248 else
249 ShowWindow(SW_HIDE);
250 }
251 return S_OK;
252 }
253
254 HRESULT STDMETHODCALLTYPE CBrandBand::HasFocusIO()
255 {
256 if (GetFocus() == m_hWnd)
257 return S_OK;
258 return S_FALSE;
259 }
260
261 HRESULT STDMETHODCALLTYPE CBrandBand::TranslateAcceleratorIO(LPMSG lpMsg)
262 {
263 return E_NOTIMPL;
264 }
265
266 HRESULT STDMETHODCALLTYPE CBrandBand::UIActivateIO(BOOL fActivate, LPMSG lpMsg)
267 {
268 return E_NOTIMPL;
269 }
270
271 HRESULT STDMETHODCALLTYPE CBrandBand::GetClassID(CLSID *pClassID)
272 {
273 if (pClassID == NULL)
274 return E_POINTER;
275 *pClassID = CLSID_BrandBand;
276 return S_OK;
277 }
278
279 HRESULT STDMETHODCALLTYPE CBrandBand::IsDirty()
280 {
281 return S_FALSE;
282 }
283
284 HRESULT STDMETHODCALLTYPE CBrandBand::Load(IStream *pStm)
285 {
286 return E_NOTIMPL;
287 }
288
289 HRESULT STDMETHODCALLTYPE CBrandBand::Save(IStream *pStm, BOOL fClearDirty)
290 {
291 return E_NOTIMPL;
292 }
293
294 HRESULT STDMETHODCALLTYPE CBrandBand::GetSizeMax(ULARGE_INTEGER *pcbSize)
295 {
296 return E_NOTIMPL;
297 }
298
299 HRESULT STDMETHODCALLTYPE CBrandBand::OnWinEvent(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(const GUID *pguidCmdGroup, ULONG cCmds, OLECMD prgCmds[ ], OLECMDTEXT *pCmdText)
312 {
313 return E_NOTIMPL;
314 }
315
316 HRESULT STDMETHODCALLTYPE CBrandBand::Exec(const GUID *pguidCmdGroup, DWORD nCmdID, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
317 {
318 if (IsEqualIID(*pguidCmdGroup, CGID_PrivCITCommands))
319 {
320 }
321 else if (IsEqualIID(*pguidCmdGroup, CGID_BrandCmdGroup))
322 {
323 switch (nCmdID)
324 {
325 case BBID_STARTANIMATION:
326 StartAnimation();
327 return S_OK;
328 case BBID_STOPANIMATION:
329 StopAnimation();
330 return S_OK;
331 }
332 }
333 return E_FAIL;
334 }
335
336 HRESULT STDMETHODCALLTYPE CBrandBand::QueryService(REFGUID guidService, REFIID riid, void **ppvObject)
337 {
338 CComPtr<IServiceProvider> serviceProvider;
339 HRESULT hResult;
340
341 if (IsEqualIID(guidService, SID_SBrandBand))
342 return this->QueryInterface(riid, ppvObject);
343 hResult = fSite->QueryInterface(IID_IServiceProvider, (void **)&serviceProvider);
344 if (FAILED (hResult))
345 return hResult;
346 return serviceProvider->QueryService(guidService, riid, ppvObject);
347 }
348
349 HRESULT STDMETHODCALLTYPE CBrandBand::GetTypeInfoCount(UINT *pctinfo)
350 {
351 return E_NOTIMPL;
352 }
353
354 HRESULT STDMETHODCALLTYPE CBrandBand::GetTypeInfo(UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo)
355 {
356 return E_NOTIMPL;
357 }
358
359 HRESULT STDMETHODCALLTYPE CBrandBand::GetIDsOfNames(REFIID riid, LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
360 {
361 return E_NOTIMPL;
362 }
363
364 HRESULT STDMETHODCALLTYPE CBrandBand::Invoke(DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
365 {
366 if (pDispParams == NULL)
367 return E_INVALIDARG;
368 switch (dispIdMember)
369 {
370 case DISPID_DOWNLOADCOMPLETE:
371 StopAnimation();
372 break;
373 case DISPID_DOWNLOADBEGIN:
374 StartAnimation();
375 break;
376 }
377 return E_INVALIDARG;
378 }
379
380 LRESULT CBrandBand::OnSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
381 {
382 Invalidate(FALSE);
383 return 0;
384 }
385
386 LRESULT CBrandBand::OnEraseBkgnd (UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
387 {
388 return 1;
389 }
390
391 LRESULT CBrandBand::OnPaint(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
392 {
393 PAINTSTRUCT paintInfo;
394 HDC dc;
395 POINT destinationPoint;
396 HDC sourceDC;
397 HBITMAP oldBitmap;
398 RECT clientRect;
399 RECT tempRect;
400
401 dc = BeginPaint(&paintInfo);
402 GetClientRect(&clientRect);
403
404 destinationPoint.x = (clientRect.right - clientRect.left - fBitmapSize) / 2;
405 destinationPoint.y = (clientRect.bottom - clientRect.top - fBitmapSize) / 2;
406
407 ::SetBkColor(dc, RGB(255, 255, 255));
408
409 tempRect.left = 0;
410 tempRect.top = 0;
411 tempRect.right = clientRect.right;
412 tempRect.bottom = destinationPoint.y;
413 FillSolidRect(dc, &tempRect, RGB(255, 255, 255));
414
415 tempRect.left = 0;
416 tempRect.top = destinationPoint.y + fBitmapSize;
417 tempRect.right = clientRect.right;
418 tempRect.bottom = clientRect.bottom;
419 FillSolidRect(dc, &paintInfo.rcPaint, RGB(255, 255, 255));
420
421 tempRect.left = 0;
422 tempRect.top = destinationPoint.y;
423 tempRect.right = destinationPoint.x;
424 tempRect.bottom = destinationPoint.y + fBitmapSize;
425 FillSolidRect(dc, &paintInfo.rcPaint, RGB(255, 255, 255));
426
427 tempRect.left = destinationPoint.x + fBitmapSize;
428 tempRect.top = destinationPoint.y;
429 tempRect.right = clientRect.right;
430 tempRect.bottom = destinationPoint.y + fBitmapSize;
431 FillSolidRect(dc, &paintInfo.rcPaint, RGB(255, 255, 255));
432
433 sourceDC = CreateCompatibleDC(dc);
434 oldBitmap = (HBITMAP)SelectObject(sourceDC, fImageBitmap);
435
436 BitBlt(dc, destinationPoint.x, destinationPoint.y, fBitmapSize, fBitmapSize, sourceDC, 0, fCurrentFrame * fBitmapSize, SRCCOPY);
437
438 SelectObject(sourceDC, oldBitmap);
439 DeleteDC(sourceDC);
440
441 EndPaint(&paintInfo);
442 return 0;
443 }
444
445 LRESULT CBrandBand::OnTimer(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
446 {
447 fCurrentFrame++;
448 if (fCurrentFrame >= fMaxFrameCount)
449 fCurrentFrame = 0;
450 Invalidate(FALSE);
451 return 0;
452 }
453
454 HRESULT CreateBrandBand(REFIID riid, void **ppv)
455 {
456 CComObject<CBrandBand> *theMenuBar;
457 HRESULT hResult;
458
459 if (ppv == NULL)
460 return E_POINTER;
461 *ppv = NULL;
462 ATLTRY (theMenuBar = new CComObject<CBrandBand>);
463 if (theMenuBar == NULL)
464 return E_OUTOFMEMORY;
465 hResult = theMenuBar->QueryInterface (riid, (void **)ppv);
466 if (FAILED (hResult))
467 {
468 delete theMenuBar;
469 return hResult;
470 }
471 return S_OK;
472 }