xref: /reactos/dll/win32/browseui/brandband.cpp (revision ba3f0743)
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