fc209b73448a0fd4dc5978ec9bea8158ba915dae
[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
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 }