bb84ff87099ed99cb6902e1473da8f0d2fa7053a
[reactos.git] / base / shell / explorer-new / taskband.c
1 /*
2 * ReactOS Explorer
3 *
4 * Copyright 2006 - 2007 Thomas Weidenmueller <w3seek@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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20
21 #include "precomp.h"
22
23 /*****************************************************************************
24 ** ITaskBand ****************************************************************
25 *****************************************************************************/
26
27 const GUID CLSID_ITaskBand = {0x68284FAA,0x6A48,0x11D0,{0x8C,0x78,0x00,0xC0,0x4F,0xD9,0x18,0xB4}};
28
29 static const ITaskBandVtbl ITaskBandImpl_Vtbl;
30 static const IDeskBandVtbl IDeskBandImpl_Vtbl;
31 static const IObjectWithSiteVtbl IObjectWithSiteImpl_Vtbl;
32 static const IDeskBarVtbl IDeskBarImpl_Vtbl;
33 static const IPersistStreamVtbl IPersistStreamImpl_Vtbl;
34 static const IWinEventHandlerVtbl IWinEventHandlerImpl_Vtbl;
35
36 typedef struct
37 {
38 const ITaskBandVtbl *lpVtbl;
39 const IDeskBandVtbl *lpDeskBandVtbl;
40 const IObjectWithSiteVtbl *lpObjectWithSiteVtbl;
41 const IDeskBarVtbl *lpDeskBarVtbl;
42 const IPersistStreamVtbl *lpPersistStreamVtbl;
43 const IWinEventHandlerVtbl *lpWindowEventHandlerVtbl;
44 /* FIXME: Implement IOleCommandTarget */
45 LONG Ref;
46
47 ITrayWindow *Tray;
48 IUnknown *punkSite;
49
50 HWND hWnd;
51 DWORD dwBandID;
52 } ITaskBandImpl;
53
54 static IUnknown *
55 IUnknown_from_ITaskBandImpl(ITaskBandImpl *This)
56 {
57 return (IUnknown *)&This->lpVtbl;
58 }
59
60 IMPL_CASTS(ITaskBand, ITaskBand, lpVtbl)
61 IMPL_CASTS(IDeskBand, ITaskBand, lpDeskBandVtbl)
62 IMPL_CASTS(IObjectWithSite, ITaskBand, lpObjectWithSiteVtbl)
63 IMPL_CASTS(IDeskBar, ITaskBand, lpDeskBarVtbl)
64 IMPL_CASTS(IPersistStream, ITaskBand, lpPersistStreamVtbl)
65 IMPL_CASTS(IWinEventHandler, ITaskBand, lpWindowEventHandlerVtbl)
66
67 static ULONG STDMETHODCALLTYPE
68 ITaskBandImpl_AddRef(IN OUT ITaskBand *iface)
69 {
70 ITaskBandImpl *This = ITaskBandImpl_from_ITaskBand(iface);
71
72 return InterlockedIncrement(&This->Ref);
73 }
74
75 static VOID
76 ITaskBandImpl_Free(IN OUT ITaskBandImpl *This)
77 {
78 if (This->punkSite != NULL)
79 {
80 IUnknown_Release(This->punkSite);
81 This->punkSite = NULL;
82 }
83
84 HeapFree(hProcessHeap,
85 0,
86 This);
87 }
88
89 static ULONG STDMETHODCALLTYPE
90 ITaskBandImpl_Release(IN OUT ITaskBand *iface)
91 {
92 ITaskBandImpl *This = ITaskBandImpl_from_ITaskBand(iface);
93 ULONG Ret;
94
95 Ret = InterlockedDecrement(&This->Ref);
96
97 if (Ret == 0)
98 ITaskBandImpl_Free(This);
99
100 return Ret;
101 }
102
103 static HRESULT STDMETHODCALLTYPE
104 ITaskBandImpl_QueryInterface(IN OUT ITaskBand *iface,
105 IN REFIID riid,
106 OUT LPVOID *ppvObj)
107 {
108 ITaskBandImpl *This;
109
110 if (ppvObj == NULL)
111 return E_POINTER;
112
113 This = ITaskBandImpl_from_ITaskBand(iface);
114
115 if (IsEqualIID(riid,
116 &IID_IUnknown))
117 {
118 *ppvObj = IUnknown_from_ITaskBandImpl(This);
119 }
120 else if (IsEqualIID(riid,
121 &IID_IDeskBand) ||
122 IsEqualIID(riid,
123 &IID_IOleWindow) ||
124 IsEqualIID(riid,
125 &IID_IDockingWindow))
126 {
127 *ppvObj = IDeskBand_from_ITaskBandImpl(This);
128 }
129 else if (IsEqualIID(riid,
130 &IID_IObjectWithSite))
131 {
132 *ppvObj = IObjectWithSite_from_ITaskBandImpl(This);
133 }
134 else if (IsEqualIID(riid,
135 &IID_IDeskBar))
136 {
137 *ppvObj = IDeskBar_from_ITaskBandImpl(This);
138 }
139 else if (IsEqualIID(riid,
140 &IID_IWinEventHandler))
141 {
142 /* When run on Windows the system queries this interface, which is completely
143 undocumented :( It's queried during initialization of the tray band site.
144 The system apparently uses this interface to forward messages to be handled
145 by the band child window. This interface appears to be implemented by a number
146 of classes provided by the shell, including the IBandSite interface. In that
147 we (the host application) forward messages to the default message handler (in
148 our case the IBandSite default message handler for the Rebar control)! This
149 interface in the ITaskBand implementation is only actually used if we use
150 the same interface to forward messages to the IBandSite implementation of
151 the shell! */
152 *ppvObj = IWinEventHandler_from_ITaskBandImpl(This);
153 }
154 #if 0
155 else if (IsEqualIID(riid,
156 &IID_IPersistStream) ||
157 IsEqualIID(riid,
158 &IID_IPersist))
159 {
160 *ppvObj = IPersistStream_from_ITaskBandImpl(This);
161 }
162 #endif
163 else
164 {
165 *ppvObj = NULL;
166 return E_NOINTERFACE;
167 }
168
169 ITaskBandImpl_AddRef(iface);
170 return S_OK;
171 }
172
173 static HRESULT STDMETHODCALLTYPE
174 ITaskBandImpl_GetRebarBandID(IN OUT ITaskBand *iface,
175 OUT DWORD *pdwBandID)
176 {
177 ITaskBandImpl *This = ITaskBandImpl_from_ITaskBand(iface);
178
179 if (This->dwBandID != (DWORD)-1)
180 {
181 if (pdwBandID != NULL)
182 *pdwBandID = This->dwBandID;
183
184 return S_OK;
185 }
186
187 return E_FAIL;
188 }
189
190 static const ITaskBandVtbl ITaskBandImpl_Vtbl =
191 {
192 /*** IUnknown methods ***/
193 ITaskBandImpl_QueryInterface,
194 ITaskBandImpl_AddRef,
195 ITaskBandImpl_Release,
196 /*** ITaskBand methods ***/
197 ITaskBandImpl_GetRebarBandID
198 };
199
200 /*****************************************************************************/
201
202 METHOD_IUNKNOWN_INHERITED_ADDREF(IDeskBand, ITaskBand)
203 METHOD_IUNKNOWN_INHERITED_RELEASE(IDeskBand, ITaskBand)
204 METHOD_IUNKNOWN_INHERITED_QUERYINTERFACE(IDeskBand, ITaskBand)
205
206 static HRESULT STDMETHODCALLTYPE
207 ITaskBandImpl_GetWindow(IN OUT IDeskBand *iface,
208 OUT HWND *phwnd)
209 {
210 ITaskBandImpl *This = ITaskBandImpl_from_IDeskBand(iface);
211
212 /* NOTE: We have to return the tray window here so that ITaskBarClient
213 knows the parent window of the Rebar control it creates when
214 calling ITaskBarClient::SetDeskBarSite()! However, once we
215 created a window we return the task switch window! */
216 if (This->hWnd != NULL)
217 *phwnd = This->hWnd;
218 else
219 *phwnd = ITrayWindow_GetHWND(This->Tray);
220
221 DbgPrint("ITaskBand::GetWindow(0x%p->0x%p)\n", phwnd, *phwnd);
222
223 if (*phwnd != NULL)
224 return S_OK;
225
226 return E_FAIL;
227 }
228
229 static HRESULT STDMETHODCALLTYPE
230 ITaskBandImpl_ContextSensitiveHelp(IN OUT IDeskBand *iface,
231 IN BOOL fEnterMode)
232 {
233 /* FIXME: Implement */
234 return E_NOTIMPL;
235 }
236
237 static HRESULT STDMETHODCALLTYPE
238 ITaskBandImpl_ShowDW(IN OUT IDeskBand *iface,
239 IN BOOL bShow)
240 {
241 /* We don't do anything... */
242 return S_OK;
243 }
244
245 static HRESULT STDMETHODCALLTYPE
246 ITaskBandImpl_CloseDW(IN OUT IDeskBand *iface,
247 IN DWORD dwReserved)
248 {
249 /* We don't do anything... */
250 return S_OK;
251 }
252
253 static HRESULT STDMETHODCALLTYPE
254 ITaskBandImpl_ResizeBoderDW(IN OUT IDeskBand *iface,
255 IN LPCRECT prcBorder,
256 IN IUnknown *punkToolbarSite,
257 IN BOOL fReserved)
258 {
259 /* No need to implement this method */
260 return E_NOTIMPL;
261 }
262
263 static HRESULT STDMETHODCALLTYPE
264 ITaskBandImpl_GetBandInfo(IN OUT IDeskBand *iface,
265 IN DWORD dwBandID,
266 IN DWORD dwViewMode,
267 IN OUT DESKBANDINFO *pdbi)
268 {
269 ITaskBandImpl *This = ITaskBandImpl_from_IDeskBand(iface);
270 DbgPrint("ITaskBand::GetBandInfo(0x%x,0x%x,0x%p) hWnd=0x%p\n", dwBandID, dwViewMode, pdbi, This->hWnd);
271
272 /* NOTE: We could save dwBandID in the instance in case we need it later... */
273
274 if (This->hWnd != NULL)
275 {
276 /* The task band never has a title */
277 pdbi->dwMask &= ~DBIM_TITLE;
278
279 /* NOTE: We don't return DBIMF_UNDELETEABLE here, the band site will
280 handle us differently and add this flag for us. The reason for
281 this is future changes that might allow it to be deletable.
282 We want the band site to be in charge of this decision rather
283 the band itself! */
284 /* FIXME: What about DBIMF_NOGRIPPER and DBIMF_ALWAYSGRIPPER */
285 pdbi->dwModeFlags = DBIMF_VARIABLEHEIGHT;
286
287 if (dwViewMode & DBIF_VIEWMODE_VERTICAL)
288 {
289 pdbi->ptIntegral.y = 1;
290 pdbi->ptMinSize.y = 1;
291 /* FIXME: Get the button metrics from the task bar object!!! */
292 pdbi->ptMinSize.x = (3 * GetSystemMetrics(SM_CXEDGE) / 2) + /* FIXME: Might be wrong if only one column! */
293 GetSystemMetrics(SM_CXSIZE) + (2 * GetSystemMetrics(SM_CXEDGE)); /* FIXME: Min button size, query!!! */
294 }
295 else
296 {
297 pdbi->ptMinSize.y = GetSystemMetrics(SM_CYSIZE) + (2 * GetSystemMetrics(SM_CYEDGE)); /* FIXME: Query */
298 pdbi->ptIntegral.y = pdbi->ptMinSize.y + (3 * GetSystemMetrics(SM_CYEDGE) / 2); /* FIXME: Query metrics */
299 /* We're not going to allow task bands where not even the minimum button size fits into the band */
300 pdbi->ptMinSize.x = pdbi->ptIntegral.y;
301 }
302
303 /* Ignored: pdbi->ptMaxSize.x */
304 pdbi->ptMaxSize.y = -1;
305
306 /* FIXME: We should query the height from the task bar object!!! */
307 pdbi->ptActual.y = GetSystemMetrics(SM_CYSIZE) + (2 * GetSystemMetrics(SM_CYEDGE));
308
309 /* Save the band ID for future use in case we need to check whether a given band
310 is the task band */
311 This->dwBandID = dwBandID;
312
313 DbgPrint("H: %d, Min: %d,%d, Integral.y: %d Actual: %d,%d\n", (dwViewMode & DBIF_VIEWMODE_VERTICAL) == 0,
314 pdbi->ptMinSize.x, pdbi->ptMinSize.y, pdbi->ptIntegral.y,
315 pdbi->ptActual.x,pdbi->ptActual.y);
316
317 return S_OK;
318 }
319
320 return E_FAIL;
321 }
322
323 static const IDeskBandVtbl IDeskBandImpl_Vtbl =
324 {
325 /*** IUnknown methods ***/
326 METHOD_IUNKNOWN_INHERITED_QUERYINTERFACE_NAME(IDeskBand, ITaskBand),
327 METHOD_IUNKNOWN_INHERITED_ADDREF_NAME(IDeskBand, ITaskBand),
328 METHOD_IUNKNOWN_INHERITED_RELEASE_NAME(IDeskBand, ITaskBand),
329 /*** IOleWindow methods ***/
330 ITaskBandImpl_GetWindow,
331 ITaskBandImpl_ContextSensitiveHelp,
332 /*** IDockingWindow methods ***/
333 ITaskBandImpl_ShowDW,
334 ITaskBandImpl_CloseDW,
335 ITaskBandImpl_ResizeBoderDW,
336 /*** IDeskBand methods ***/
337 ITaskBandImpl_GetBandInfo
338 };
339
340 /*****************************************************************************/
341
342 METHOD_IUNKNOWN_INHERITED_ADDREF(IDeskBar, ITaskBand)
343 METHOD_IUNKNOWN_INHERITED_RELEASE(IDeskBar, ITaskBand)
344 METHOD_IUNKNOWN_INHERITED_QUERYINTERFACE(IDeskBar, ITaskBand)
345
346 static HRESULT STDMETHODCALLTYPE
347 IDeskBarImpl_GetWindow(IN OUT IDeskBar *iface,
348 OUT HWND *phwnd)
349 {
350 ITaskBandImpl *This = ITaskBandImpl_from_IDeskBar(iface);
351 IDeskBand *DeskBand = IDeskBand_from_ITaskBandImpl(This);
352
353 /* Proxy to IDeskBand interface */
354 return IDeskBand_GetWindow(DeskBand,
355 phwnd);
356 }
357
358 static HRESULT STDMETHODCALLTYPE
359 IDeskBarImpl_ContextSensitiveHelp(IN OUT IDeskBar *iface,
360 IN BOOL fEnterMode)
361 {
362 ITaskBandImpl *This = ITaskBandImpl_from_IDeskBar(iface);
363 IDeskBand *DeskBand = IDeskBand_from_ITaskBandImpl(This);
364
365 /* Proxy to IDeskBand interface */
366 return IDeskBand_ContextSensitiveHelp(DeskBand,
367 fEnterMode);
368 }
369
370 static HRESULT STDMETHODCALLTYPE
371 IDeskBarImpl_SetClient(IN OUT IDeskBar *iface,
372 IN IUnknown *punkClient)
373 {
374 DbgPrint("IDeskBar::SetClient(0x%p)\n", punkClient);
375 return E_NOTIMPL;
376 }
377
378 static HRESULT STDMETHODCALLTYPE
379 IDeskBarImpl_GetClient(IN OUT IDeskBar *iface,
380 OUT IUnknown **ppunkClient)
381 {
382 DbgPrint("IDeskBar::GetClient(0x%p)\n", ppunkClient);
383 return E_NOTIMPL;
384 }
385
386 static HRESULT STDMETHODCALLTYPE
387 IDeskBarImpl_OnPosRectChangeDB(IN OUT IDeskBar *iface,
388 IN RECT *prc)
389 {
390 DbgPrint("IDeskBar::OnPosRectChangeDB(0x%p=(%d,%d,%d,%d))\n", prc, prc->left, prc->top, prc->right, prc->bottom);
391 if (prc->bottom - prc->top == 0)
392 return S_OK;
393
394 return S_FALSE;
395 }
396
397 static const IDeskBarVtbl IDeskBarImpl_Vtbl =
398 {
399 /*** IUnknown methods ***/
400 METHOD_IUNKNOWN_INHERITED_QUERYINTERFACE_NAME(IDeskBar, ITaskBand),
401 METHOD_IUNKNOWN_INHERITED_ADDREF_NAME(IDeskBar, ITaskBand),
402 METHOD_IUNKNOWN_INHERITED_RELEASE_NAME(IDeskBar, ITaskBand),
403 /*** IOleWindow methods ***/
404 IDeskBarImpl_GetWindow,
405 IDeskBarImpl_ContextSensitiveHelp,
406 /*** IDeskBar methods ***/
407 IDeskBarImpl_SetClient,
408 IDeskBarImpl_GetClient,
409 IDeskBarImpl_OnPosRectChangeDB
410 };
411
412 /*****************************************************************************/
413
414 METHOD_IUNKNOWN_INHERITED_ADDREF(IPersistStream, ITaskBand)
415 METHOD_IUNKNOWN_INHERITED_RELEASE(IPersistStream, ITaskBand)
416 METHOD_IUNKNOWN_INHERITED_QUERYINTERFACE(IPersistStream, ITaskBand)
417
418 static HRESULT STDMETHODCALLTYPE
419 ITaskBandImpl_GetClassID(IN OUT IPersistStream *iface,
420 OUT CLSID *pClassID)
421 {
422 DbgPrint("ITaskBand::GetClassID(0x%p)\n", pClassID);
423 /* We're going to return the (internal!) CLSID of the task band interface */
424 *pClassID = CLSID_ITaskBand;
425 return S_OK;
426 }
427
428 static HRESULT STDMETHODCALLTYPE
429 ITaskBandImpl_IsDirty(IN OUT IPersistStream *iface)
430 {
431 /* The object hasn't changed since the last save! */
432 return S_FALSE;
433 }
434
435 static HRESULT STDMETHODCALLTYPE
436 ITaskBandImpl_Load(IN OUT IPersistStream *iface,
437 IN IStream *pStm)
438 {
439 DbgPrint("ITaskBand::Load called\n");
440 /* Nothing to do */
441 return S_OK;
442 }
443
444 static HRESULT STDMETHODCALLTYPE
445 ITaskBandImpl_Save(IN OUT IPersistStream *iface,
446 IN IStream *pStm,
447 IN BOOL fClearDirty)
448 {
449 /* Nothing to do */
450 return S_OK;
451 }
452
453 static HRESULT STDMETHODCALLTYPE
454 ITaskBandImpl_GetSizeMax(IN OUT IPersistStream *iface,
455 OUT ULARGE_INTEGER *pcbSize)
456 {
457 DbgPrint("ITaskBand::GetSizeMax called\n");
458 /* We don't need any space for the task band */
459 pcbSize->QuadPart = 0;
460 return S_OK;
461 }
462
463 static const IPersistStreamVtbl IPersistStreamImpl_Vtbl =
464 {
465 /*** IUnknown methods ***/
466 METHOD_IUNKNOWN_INHERITED_QUERYINTERFACE_NAME(IPersistStream, ITaskBand),
467 METHOD_IUNKNOWN_INHERITED_ADDREF_NAME(IPersistStream, ITaskBand),
468 METHOD_IUNKNOWN_INHERITED_RELEASE_NAME(IPersistStream, ITaskBand),
469 /*** IPersist methods ***/
470 ITaskBandImpl_GetClassID,
471 /*** IPersistStream methods ***/
472 ITaskBandImpl_IsDirty,
473 ITaskBandImpl_Load,
474 ITaskBandImpl_Save,
475 ITaskBandImpl_GetSizeMax
476 };
477
478 /*****************************************************************************/
479
480 METHOD_IUNKNOWN_INHERITED_ADDREF(IObjectWithSite, ITaskBand)
481 METHOD_IUNKNOWN_INHERITED_RELEASE(IObjectWithSite, ITaskBand)
482 METHOD_IUNKNOWN_INHERITED_QUERYINTERFACE(IObjectWithSite, ITaskBand)
483
484 static HRESULT STDMETHODCALLTYPE
485 ITaskBandImpl_SetSite(IN OUT IObjectWithSite *iface,
486 IN IUnknown* pUnkSite)
487 {
488 ITaskBandImpl *This = ITaskBandImpl_from_IObjectWithSite(iface);
489 HRESULT hRet = E_FAIL;
490
491 DbgPrint("ITaskBand::SetSite(0x%p)\n", pUnkSite);
492
493 /* Release the current site */
494 if (This->punkSite != NULL)
495 {
496 IUnknown_Release(This->punkSite);
497 }
498
499 This->punkSite = NULL;
500 This->hWnd = NULL;
501
502 if (pUnkSite != NULL)
503 {
504 IOleWindow *OleWindow;
505
506 /* Check if the site supports IOleWindow */
507 hRet = IUnknown_QueryInterface(pUnkSite,
508 &IID_IOleWindow,
509 (PVOID *)&OleWindow);
510 if (SUCCEEDED(hRet))
511 {
512 HWND hWndParent = NULL;
513
514 hRet = IOleWindow_GetWindow(OleWindow,
515 &hWndParent);
516 if (SUCCEEDED(hRet))
517 {
518 /* Attempt to create the task switch window */
519
520 DbgPrint("CreateTaskSwitchWnd(Parent: 0x%p)\n", hWndParent);
521 This->hWnd = CreateTaskSwitchWnd(hWndParent,
522 This->Tray);
523 if (This->hWnd != NULL)
524 {
525 This->punkSite = pUnkSite;
526 hRet = S_OK;
527 }
528 else
529 {
530 DbgPrint("CreateTaskSwitchWnd() failed!\n");
531 IUnknown_Release(OleWindow);
532 hRet = E_FAIL;
533 }
534 }
535 else
536 IUnknown_Release(OleWindow);
537 }
538 else
539 DbgPrint("Querying IOleWindow failed: 0x%x\n", hRet);
540 }
541
542 return hRet;
543 }
544
545 static HRESULT STDMETHODCALLTYPE
546 ITaskBandImpl_GetSite(IN OUT IObjectWithSite *iface,
547 IN REFIID riid,
548 OUT VOID **ppvSite)
549 {
550 ITaskBandImpl *This = ITaskBandImpl_from_IObjectWithSite(iface);
551 DbgPrint("ITaskBand::GetSite(0x%p,0x%p)\n", riid, ppvSite);
552
553 if (This->punkSite != NULL)
554 {
555 return IUnknown_QueryInterface(This->punkSite,
556 riid,
557 ppvSite);
558 }
559
560 *ppvSite = NULL;
561 return E_FAIL;
562 }
563
564 static const IObjectWithSiteVtbl IObjectWithSiteImpl_Vtbl =
565 {
566 /*** IUnknown methods ***/
567 METHOD_IUNKNOWN_INHERITED_QUERYINTERFACE_NAME(IObjectWithSite, ITaskBand),
568 METHOD_IUNKNOWN_INHERITED_ADDREF_NAME(IObjectWithSite, ITaskBand),
569 METHOD_IUNKNOWN_INHERITED_RELEASE_NAME(IObjectWithSite, ITaskBand),
570 /*** IObjectWithSite methods ***/
571 ITaskBandImpl_SetSite,
572 ITaskBandImpl_GetSite
573 };
574
575
576 /*****************************************************************************/
577
578 METHOD_IUNKNOWN_INHERITED_ADDREF(IWinEventHandler, ITaskBand)
579 METHOD_IUNKNOWN_INHERITED_RELEASE(IWinEventHandler, ITaskBand)
580 METHOD_IUNKNOWN_INHERITED_QUERYINTERFACE(IWinEventHandler, ITaskBand)
581
582 static HRESULT STDMETHODCALLTYPE
583 IWinEventHandlerImpl_ProcessMessage(IN OUT IWinEventHandler *iface,
584 IN HWND hWnd,
585 IN UINT uMsg,
586 IN WPARAM wParam,
587 IN LPARAM lParam,
588 OUT LRESULT *plrResult)
589 {
590 DbgPrint("ITaskBand: IWinEventHandler::ProcessMessage(0x%p, 0x%x, 0x%p, 0x%p, 0x%p)\n", hWnd, uMsg, wParam, lParam, plrResult);
591 return E_NOTIMPL;
592 }
593
594 static HRESULT STDMETHODCALLTYPE
595 IWinEventHandlerImpl_ContainsWindow(IN OUT IWinEventHandler *iface,
596 IN HWND hWnd)
597 {
598 ITaskBandImpl *This = ITaskBandImpl_from_IWinEventHandler(iface);
599
600 if (This->hWnd == hWnd ||
601 IsChild(This->hWnd, hWnd))
602 {
603 DbgPrint("ITaskBand::ContainsWindow(0x%p) returns S_OK\n", hWnd);
604 return S_OK;
605 }
606
607 return S_FALSE;
608 }
609
610 static const IWinEventHandlerVtbl IWinEventHandlerImpl_Vtbl =
611 {
612 /*** IUnknown methods ***/
613 METHOD_IUNKNOWN_INHERITED_QUERYINTERFACE_NAME(IWinEventHandler, ITaskBand),
614 METHOD_IUNKNOWN_INHERITED_ADDREF_NAME(IWinEventHandler, ITaskBand),
615 METHOD_IUNKNOWN_INHERITED_RELEASE_NAME(IWinEventHandler, ITaskBand),
616 /*** IWinEventHandler methods ***/
617 IWinEventHandlerImpl_ProcessMessage,
618 IWinEventHandlerImpl_ContainsWindow
619 };
620
621 /*****************************************************************************/
622
623 static ITaskBandImpl *
624 ITaskBandImpl_Construct(IN OUT ITrayWindow *Tray)
625 {
626 ITaskBandImpl *This;
627
628 This = HeapAlloc(hProcessHeap,
629 HEAP_ZERO_MEMORY,
630 sizeof(*This));
631 if (This == NULL)
632 return NULL;
633
634 This->lpVtbl = &ITaskBandImpl_Vtbl;
635 This->lpDeskBandVtbl = &IDeskBandImpl_Vtbl;
636 This->lpObjectWithSiteVtbl = &IObjectWithSiteImpl_Vtbl;
637 This->lpDeskBarVtbl = &IDeskBarImpl_Vtbl;
638 This->lpPersistStreamVtbl = &IPersistStreamImpl_Vtbl;
639 This->lpWindowEventHandlerVtbl = &IWinEventHandlerImpl_Vtbl;
640 This->Ref = 1;
641
642 This->Tray = Tray;
643 This->dwBandID = (DWORD)-1;
644
645 return This;
646 }
647
648 ITaskBand *
649 CreateTaskBand(IN OUT ITrayWindow *Tray)
650 {
651 ITaskBandImpl *This;
652
653 This = ITaskBandImpl_Construct(Tray);
654 if (This != NULL)
655 {
656 return ITaskBand_from_ITaskBandImpl(This);
657 }
658
659 return NULL;
660 }