4 * Copyright 2006 - 2007 Thomas Weidenmueller <w3seek@reactos.org>
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.
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.
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
23 /*****************************************************************************
24 ** ITaskBand ****************************************************************
25 *****************************************************************************/
27 const GUID CLSID_ITaskBand
= {0x68284FAA,0x6A48,0x11D0,{0x8C,0x78,0x00,0xC0,0x4F,0xD9,0x18,0xB4}};
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 IWindowEventHandlerVtbl IWindowEventHandlerImpl_Vtbl
;
38 const ITaskBandVtbl
*lpVtbl
;
39 const IDeskBandVtbl
*lpDeskBandVtbl
;
40 const IObjectWithSiteVtbl
*lpObjectWithSiteVtbl
;
41 const IDeskBarVtbl
*lpDeskBarVtbl
;
42 const IPersistStreamVtbl
*lpPersistStreamVtbl
;
43 const IWindowEventHandlerVtbl
*lpWindowEventHandlerVtbl
;
44 /* FIXME: Implement IOleCommandTarget */
55 IUnknown_from_ITaskBandImpl(ITaskBandImpl
*This
)
57 return (IUnknown
*)&This
->lpVtbl
;
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(IWindowEventHandler
, ITaskBand
, lpWindowEventHandlerVtbl
)
67 static ULONG STDMETHODCALLTYPE
68 ITaskBandImpl_AddRef(IN OUT ITaskBand
*iface
)
70 ITaskBandImpl
*This
= ITaskBandImpl_from_ITaskBand(iface
);
72 return InterlockedIncrement(&This
->Ref
);
76 ITaskBandImpl_Free(IN OUT ITaskBandImpl
*This
)
78 if (This
->punkSite
!= NULL
)
80 IUnknown_Release(This
->punkSite
);
81 This
->punkSite
= NULL
;
84 HeapFree(hProcessHeap
,
89 static ULONG STDMETHODCALLTYPE
90 ITaskBandImpl_Release(IN OUT ITaskBand
*iface
)
92 ITaskBandImpl
*This
= ITaskBandImpl_from_ITaskBand(iface
);
95 Ret
= InterlockedDecrement(&This
->Ref
);
98 ITaskBandImpl_Free(This
);
103 static HRESULT STDMETHODCALLTYPE
104 ITaskBandImpl_QueryInterface(IN OUT ITaskBand
*iface
,
113 This
= ITaskBandImpl_from_ITaskBand(iface
);
118 *ppvObj
= IUnknown_from_ITaskBandImpl(This
);
120 else if (IsEqualIID(riid
,
125 &IID_IDockingWindow
))
127 *ppvObj
= IDeskBand_from_ITaskBandImpl(This
);
129 else if (IsEqualIID(riid
,
130 &IID_IObjectWithSite
))
132 *ppvObj
= IObjectWithSite_from_ITaskBandImpl(This
);
134 else if (IsEqualIID(riid
,
137 *ppvObj
= IDeskBar_from_ITaskBandImpl(This
);
139 else if (IsEqualIID(riid
,
140 &IID_IWindowEventHandler
))
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
152 *ppvObj
= IWindowEventHandler_from_ITaskBandImpl(This
);
155 else if (IsEqualIID(riid
,
156 &IID_IPersistStream
) ||
160 *ppvObj
= IPersistStream_from_ITaskBandImpl(This
);
166 return E_NOINTERFACE
;
169 ITaskBandImpl_AddRef(iface
);
173 static HRESULT STDMETHODCALLTYPE
174 ITaskBandImpl_GetRebarBandID(IN OUT ITaskBand
*iface
,
175 OUT DWORD
*pdwBandID
)
177 ITaskBandImpl
*This
= ITaskBandImpl_from_ITaskBand(iface
);
179 if (This
->dwBandID
!= (DWORD
)-1)
181 if (pdwBandID
!= NULL
)
182 *pdwBandID
= This
->dwBandID
;
190 static const ITaskBandVtbl ITaskBandImpl_Vtbl
=
192 /*** IUnknown methods ***/
193 ITaskBandImpl_QueryInterface
,
194 ITaskBandImpl_AddRef
,
195 ITaskBandImpl_Release
,
196 /*** ITaskBand methods ***/
197 ITaskBandImpl_GetRebarBandID
200 /*****************************************************************************/
202 METHOD_IUNKNOWN_INHERITED_ADDREF(IDeskBand
, ITaskBand
)
203 METHOD_IUNKNOWN_INHERITED_RELEASE(IDeskBand
, ITaskBand
)
204 METHOD_IUNKNOWN_INHERITED_QUERYINTERFACE(IDeskBand
, ITaskBand
)
206 static HRESULT STDMETHODCALLTYPE
207 ITaskBandImpl_GetWindow(IN OUT IDeskBand
*iface
,
210 ITaskBandImpl
*This
= ITaskBandImpl_from_IDeskBand(iface
);
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
)
219 *phwnd
= ITrayWindow_GetHWND(This
->Tray
);
221 DbgPrint("ITaskBand::GetWindow(0x%p->0x%p)\n", phwnd
, *phwnd
);
229 static HRESULT STDMETHODCALLTYPE
230 ITaskBandImpl_ContextSensitiveHelp(IN OUT IDeskBand
*iface
,
233 /* FIXME: Implement */
237 static HRESULT STDMETHODCALLTYPE
238 ITaskBandImpl_ShowDW(IN OUT IDeskBand
*iface
,
241 /* We don't do anything... */
245 static HRESULT STDMETHODCALLTYPE
246 ITaskBandImpl_CloseDW(IN OUT IDeskBand
*iface
,
249 /* We don't do anything... */
253 static HRESULT STDMETHODCALLTYPE
254 ITaskBandImpl_ResizeBoderDW(IN OUT IDeskBand
*iface
,
255 IN LPCRECT prcBorder
,
256 IN IUnknown
*punkToolbarSite
,
259 /* No need to implement this method */
263 static HRESULT STDMETHODCALLTYPE
264 ITaskBandImpl_GetBandInfo(IN OUT IDeskBand
*iface
,
267 IN OUT DESKBANDINFO
*pdbi
)
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
);
272 /* NOTE: We could save dwBandID in the instance in case we need it later... */
274 if (This
->hWnd
!= NULL
)
276 /* The task band never has a title */
277 pdbi
->dwMask
&= ~DBIM_TITLE
;
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
284 /* FIXME: What about DBIMF_NOGRIPPER and DBIMF_ALWAYSGRIPPER */
285 pdbi
->dwModeFlags
= DBIMF_VARIABLEHEIGHT
;
287 if (dwViewMode
& DBIF_VIEWMODE_VERTICAL
)
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!!! */
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
;
303 /* Ignored: pdbi->ptMaxSize.x */
304 pdbi
->ptMaxSize
.y
= -1;
306 /* FIXME: We should query the height from the task bar object!!! */
307 pdbi
->ptActual
.y
= GetSystemMetrics(SM_CYSIZE
) + (2 * GetSystemMetrics(SM_CYEDGE
));
309 /* Save the band ID for future use in case we need to check whether a given band
311 This
->dwBandID
= dwBandID
;
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
);
323 static const IDeskBandVtbl IDeskBandImpl_Vtbl
=
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
340 /*****************************************************************************/
342 METHOD_IUNKNOWN_INHERITED_ADDREF(IDeskBar
, ITaskBand
)
343 METHOD_IUNKNOWN_INHERITED_RELEASE(IDeskBar
, ITaskBand
)
344 METHOD_IUNKNOWN_INHERITED_QUERYINTERFACE(IDeskBar
, ITaskBand
)
346 static HRESULT STDMETHODCALLTYPE
347 IDeskBarImpl_GetWindow(IN OUT IDeskBar
*iface
,
350 ITaskBandImpl
*This
= ITaskBandImpl_from_IDeskBar(iface
);
351 IDeskBand
*DeskBand
= IDeskBand_from_ITaskBandImpl(This
);
353 /* Proxy to IDeskBand interface */
354 return IDeskBand_GetWindow(DeskBand
,
358 static HRESULT STDMETHODCALLTYPE
359 IDeskBarImpl_ContextSensitiveHelp(IN OUT IDeskBar
*iface
,
362 ITaskBandImpl
*This
= ITaskBandImpl_from_IDeskBar(iface
);
363 IDeskBand
*DeskBand
= IDeskBand_from_ITaskBandImpl(This
);
365 /* Proxy to IDeskBand interface */
366 return IDeskBand_ContextSensitiveHelp(DeskBand
,
370 static HRESULT STDMETHODCALLTYPE
371 IDeskBarImpl_SetClient(IN OUT IDeskBar
*iface
,
372 IN IUnknown
*punkClient
)
374 DbgPrint("IDeskBar::SetClient(0x%p)\n", punkClient
);
378 static HRESULT STDMETHODCALLTYPE
379 IDeskBarImpl_GetClient(IN OUT IDeskBar
*iface
,
380 OUT IUnknown
**ppunkClient
)
382 DbgPrint("IDeskBar::GetClient(0x%p)\n", ppunkClient
);
386 static HRESULT STDMETHODCALLTYPE
387 IDeskBarImpl_OnPosRectChangeDB(IN OUT IDeskBar
*iface
,
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)
397 static const IDeskBarVtbl IDeskBarImpl_Vtbl
=
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
412 /*****************************************************************************/
414 METHOD_IUNKNOWN_INHERITED_ADDREF(IPersistStream
, ITaskBand
)
415 METHOD_IUNKNOWN_INHERITED_RELEASE(IPersistStream
, ITaskBand
)
416 METHOD_IUNKNOWN_INHERITED_QUERYINTERFACE(IPersistStream
, ITaskBand
)
418 static HRESULT STDMETHODCALLTYPE
419 ITaskBandImpl_GetClassID(IN OUT IPersistStream
*iface
,
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
;
428 static HRESULT STDMETHODCALLTYPE
429 ITaskBandImpl_IsDirty(IN OUT IPersistStream
*iface
)
431 /* The object hasn't changed since the last save! */
435 static HRESULT STDMETHODCALLTYPE
436 ITaskBandImpl_Load(IN OUT IPersistStream
*iface
,
439 DbgPrint("ITaskBand::Load called\n");
444 static HRESULT STDMETHODCALLTYPE
445 ITaskBandImpl_Save(IN OUT IPersistStream
*iface
,
453 static HRESULT STDMETHODCALLTYPE
454 ITaskBandImpl_GetSizeMax(IN OUT IPersistStream
*iface
,
455 OUT ULARGE_INTEGER
*pcbSize
)
457 DbgPrint("ITaskBand::GetSizeMax called\n");
458 /* We don't need any space for the task band */
459 pcbSize
->QuadPart
= 0;
463 static const IPersistStreamVtbl IPersistStreamImpl_Vtbl
=
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
,
475 ITaskBandImpl_GetSizeMax
478 /*****************************************************************************/
480 METHOD_IUNKNOWN_INHERITED_ADDREF(IObjectWithSite
, ITaskBand
)
481 METHOD_IUNKNOWN_INHERITED_RELEASE(IObjectWithSite
, ITaskBand
)
482 METHOD_IUNKNOWN_INHERITED_QUERYINTERFACE(IObjectWithSite
, ITaskBand
)
484 static HRESULT STDMETHODCALLTYPE
485 ITaskBandImpl_SetSite(IN OUT IObjectWithSite
*iface
,
486 IN IUnknown
* pUnkSite
)
488 ITaskBandImpl
*This
= ITaskBandImpl_from_IObjectWithSite(iface
);
489 HRESULT hRet
= E_FAIL
;
491 DbgPrint("ITaskBand::SetSite(0x%p)\n", pUnkSite
);
493 /* Release the current site */
494 if (This
->punkSite
!= NULL
)
496 IUnknown_Release(This
->punkSite
);
499 This
->punkSite
= NULL
;
502 if (pUnkSite
!= NULL
)
504 IOleWindow
*OleWindow
;
506 /* Check if the site supports IOleWindow */
507 hRet
= IUnknown_QueryInterface(pUnkSite
,
512 HWND hWndParent
= NULL
;
514 hRet
= IOleWindow_GetWindow(OleWindow
,
518 /* Attempt to create the task switch window */
520 DbgPrint("CreateTaskSwitchWnd(Parent: 0x%p)\n", hWndParent
);
521 This
->hWnd
= CreateTaskSwitchWnd(hWndParent
,
523 if (This
->hWnd
!= NULL
)
525 This
->punkSite
= pUnkSite
;
530 DbgPrint("CreateTaskSwitchWnd() failed!\n");
531 IUnknown_Release(OleWindow
);
536 IUnknown_Release(OleWindow
);
539 DbgPrint("Querying IOleWindow failed: 0x%x\n", hRet
);
545 static HRESULT STDMETHODCALLTYPE
546 ITaskBandImpl_GetSite(IN OUT IObjectWithSite
*iface
,
550 ITaskBandImpl
*This
= ITaskBandImpl_from_IObjectWithSite(iface
);
551 DbgPrint("ITaskBand::GetSite(0x%p,0x%p)\n", riid
, ppvSite
);
553 if (This
->punkSite
!= NULL
)
555 return IUnknown_QueryInterface(This
->punkSite
,
564 static const IObjectWithSiteVtbl IObjectWithSiteImpl_Vtbl
=
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
576 /*****************************************************************************/
578 METHOD_IUNKNOWN_INHERITED_ADDREF(IWindowEventHandler
, ITaskBand
)
579 METHOD_IUNKNOWN_INHERITED_RELEASE(IWindowEventHandler
, ITaskBand
)
580 METHOD_IUNKNOWN_INHERITED_QUERYINTERFACE(IWindowEventHandler
, ITaskBand
)
582 static HRESULT STDMETHODCALLTYPE
583 IWindowEventHandlerImpl_ProcessMessage(IN OUT IWindowEventHandler
*iface
,
588 OUT LRESULT
*plrResult
)
590 DbgPrint("ITaskBand: IWindowEventHandler::ProcessMessage(0x%p, 0x%x, 0x%p, 0x%p, 0x%p)\n", hWnd
, uMsg
, wParam
, lParam
, plrResult
);
594 static HRESULT STDMETHODCALLTYPE
595 IWindowEventHandlerImpl_ContainsWindow(IN OUT IWindowEventHandler
*iface
,
598 ITaskBandImpl
*This
= ITaskBandImpl_from_IWindowEventHandler(iface
);
601 if (This
->hWnd
!= hWnd
||
608 DbgPrint("ITaskBand::ContainsWindow(0x%p) returns %s\n", hWnd
, hRet
== S_OK
? "S_OK" : "S_FALSE");
613 static const IWindowEventHandlerVtbl IWindowEventHandlerImpl_Vtbl
=
615 /*** IUnknown methods ***/
616 METHOD_IUNKNOWN_INHERITED_QUERYINTERFACE_NAME(IWindowEventHandler
, ITaskBand
),
617 METHOD_IUNKNOWN_INHERITED_ADDREF_NAME(IWindowEventHandler
, ITaskBand
),
618 METHOD_IUNKNOWN_INHERITED_RELEASE_NAME(IWindowEventHandler
, ITaskBand
),
619 /*** IWindowEventHandler methods ***/
620 IWindowEventHandlerImpl_ProcessMessage
,
621 IWindowEventHandlerImpl_ContainsWindow
624 /*****************************************************************************/
626 static ITaskBandImpl
*
627 ITaskBandImpl_Construct(IN OUT ITrayWindow
*Tray
)
631 This
= HeapAlloc(hProcessHeap
,
639 This
->lpVtbl
= &ITaskBandImpl_Vtbl
;
640 This
->lpDeskBandVtbl
= &IDeskBandImpl_Vtbl
;
641 This
->lpObjectWithSiteVtbl
= &IObjectWithSiteImpl_Vtbl
;
642 This
->lpDeskBarVtbl
= &IDeskBarImpl_Vtbl
;
643 This
->lpPersistStreamVtbl
= &IPersistStreamImpl_Vtbl
;
644 This
->lpWindowEventHandlerVtbl
= &IWindowEventHandlerImpl_Vtbl
;
648 This
->dwBandID
= (DWORD
)-1;
654 CreateTaskBand(IN OUT ITrayWindow
*Tray
)
658 This
= ITaskBandImpl_Construct(Tray
);
661 return ITaskBand_from_ITaskBandImpl(This
);