xref: /reactos/base/shell/explorer/taskband.cpp (revision 84344399)
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  ** CTaskBand ****************************************************************
25  *****************************************************************************/
26 
27 const GUID CLSID_ITaskBand = { 0x68284FAA, 0x6A48, 0x11D0, { 0x8C, 0x78, 0x00, 0xC0, 0x4F, 0xD9, 0x18, 0xB4 } };
28 
29 class CTaskBand :
30     public CComCoClass<CTaskBand>,
31     public CComObjectRootEx<CComMultiThreadModelNoCS>,
32     public IObjectWithSite,
33     public IDeskBand,
34     public IDeskBar,
35     public IPersistStream,
36     public IWinEventHandler,
37     public IOleCommandTarget
38 {
39     CComPtr<ITrayWindow> m_Tray;
40     CComPtr<IUnknown> m_Site;
41     CComPtr<IUnknown> m_TasksWnd;
42 
43     HWND m_hWnd;
44 
45 public:
46     CTaskBand() :
47         m_hWnd(NULL)
48     {
49     }
50 
51     virtual ~CTaskBand() { }
52 
53     /*****************************************************************************/
54 
55     virtual HRESULT STDMETHODCALLTYPE GetWindow(OUT HWND *phwnd)
56     {
57         if (!m_hWnd)
58             return E_FAIL;
59         if (!phwnd)
60             return E_INVALIDARG;
61         *phwnd = m_hWnd;
62         return S_OK;
63     }
64 
65     virtual HRESULT STDMETHODCALLTYPE ContextSensitiveHelp(
66         IN BOOL fEnterMode)
67     {
68         /* FIXME: Implement */
69         return E_NOTIMPL;
70     }
71 
72     virtual HRESULT STDMETHODCALLTYPE ShowDW(
73         IN BOOL bShow)
74     {
75         /* We don't do anything... */
76         return S_OK;
77     }
78 
79     virtual HRESULT STDMETHODCALLTYPE CloseDW(
80         IN DWORD dwReserved)
81     {
82         /* We don't do anything... */
83         return S_OK;
84     }
85 
86     virtual HRESULT STDMETHODCALLTYPE ResizeBorderDW(
87         LPCRECT prcBorder,
88         IUnknown *punkToolbarSite,
89         BOOL fReserved)
90     {
91         /* No need to implement this method */
92         return E_NOTIMPL;
93     }
94 
95     virtual HRESULT STDMETHODCALLTYPE GetBandInfo(
96         IN DWORD dwBandID,
97         IN DWORD dwViewMode,
98         IN OUT DESKBANDINFO *pdbi)
99     {
100         TRACE("CTaskBand::GetBandInfo(0x%x,0x%x,0x%p) hWnd=0x%p\n", dwBandID, dwViewMode, pdbi, m_hWnd);
101 
102         if (m_hWnd != NULL)
103         {
104             HWND hwndToolbar = ::GetWindow(m_hWnd, GW_CHILD);
105 
106             /* The task band never has a title */
107             pdbi->dwMask &= ~DBIM_TITLE;
108 
109             /* NOTE: We don't return DBIMF_UNDELETEABLE here, the band site will
110                      handle us differently and add this flag for us. The reason for
111                      this is future changes that might allow it to be deletable.
112                      We want the band site to be in charge of this decision rather
113                      the band itself! */
114             /* FIXME: What about DBIMF_NOGRIPPER and DBIMF_ALWAYSGRIPPER */
115             pdbi->dwModeFlags = DBIMF_VARIABLEHEIGHT;
116 
117             /* Obtain the button size, to be used as the minimum size */
118             DWORD size = SendMessageW(hwndToolbar, TB_GETBUTTONSIZE, 0, 0);
119             pdbi->ptMinSize.x = 0;
120             pdbi->ptMinSize.y = GET_Y_LPARAM(size);
121 
122             if (dwViewMode & DBIF_VIEWMODE_VERTICAL)
123             {
124                 pdbi->ptIntegral.x = 0;
125                 pdbi->ptIntegral.y = 1;
126             }
127             else
128             {
129                 pdbi->ptIntegral.x = 0;
130                 pdbi->ptIntegral.y = GET_Y_LPARAM(size);
131             }
132 
133             /* Ignored: pdbi->ptMaxSize.x */
134             pdbi->ptMaxSize.y = -1;
135 
136             RECT rcToolbar;
137             ::GetWindowRect(hwndToolbar, &rcToolbar);
138             /* FIXME: We should query the height from the task bar object!!! */
139             pdbi->ptActual.x = rcToolbar.right - rcToolbar.left;
140             pdbi->ptActual.y = rcToolbar.bottom - rcToolbar.top;
141 
142             TRACE("H: %d, Min: %d,%d, Integral.y: %d Actual: %d,%d\n", (dwViewMode & DBIF_VIEWMODE_VERTICAL) == 0,
143                 pdbi->ptMinSize.x, pdbi->ptMinSize.y, pdbi->ptIntegral.y,
144                 pdbi->ptActual.x, pdbi->ptActual.y);
145 
146             return S_OK;
147         }
148 
149         return E_FAIL;
150     }
151 
152     /*****************************************************************************/
153     // *** IOleCommandTarget methods ***
154     virtual HRESULT STDMETHODCALLTYPE QueryStatus(const GUID *pguidCmdGroup, ULONG cCmds, OLECMD prgCmds [], OLECMDTEXT *pCmdText)
155     {
156         UNIMPLEMENTED;
157         return E_NOTIMPL;
158     }
159 
160     virtual HRESULT STDMETHODCALLTYPE Exec(const GUID *pguidCmdGroup, DWORD nCmdID, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
161     {
162         if (IsEqualIID(*pguidCmdGroup, IID_IBandSite))
163         {
164             return S_OK;
165         }
166 
167         if (IsEqualIID(*pguidCmdGroup, IID_IDeskBand))
168         {
169             return S_OK;
170         }
171 
172         UNIMPLEMENTED;
173         return E_NOTIMPL;
174     }
175 
176     /*****************************************************************************/
177 
178     virtual HRESULT STDMETHODCALLTYPE SetClient(
179         IN IUnknown *punkClient)
180     {
181         TRACE("IDeskBar::SetClient(0x%p)\n", punkClient);
182         return E_NOTIMPL;
183     }
184 
185     virtual HRESULT STDMETHODCALLTYPE GetClient(
186         OUT IUnknown **ppunkClient)
187     {
188         TRACE("IDeskBar::GetClient(0x%p)\n", ppunkClient);
189         return E_NOTIMPL;
190     }
191 
192     virtual HRESULT STDMETHODCALLTYPE OnPosRectChangeDB(
193         IN RECT *prc)
194     {
195         TRACE("IDeskBar::OnPosRectChangeDB(0x%p=(%d,%d,%d,%d))\n", prc, prc->left, prc->top, prc->right, prc->bottom);
196         if (prc->bottom - prc->top == 0)
197             return S_OK;
198 
199         return S_FALSE;
200     }
201 
202     /*****************************************************************************/
203 
204     virtual HRESULT STDMETHODCALLTYPE GetClassID(
205         OUT CLSID *pClassID)
206     {
207         TRACE("CTaskBand::GetClassID(0x%p)\n", pClassID);
208         /* We're going to return the (internal!) CLSID of the task band interface */
209         *pClassID = CLSID_ITaskBand;
210         return S_OK;
211     }
212 
213     virtual HRESULT STDMETHODCALLTYPE IsDirty()
214     {
215         /* The object hasn't changed since the last save! */
216         return S_FALSE;
217     }
218 
219     virtual HRESULT STDMETHODCALLTYPE Load(
220         IN IStream *pStm)
221     {
222         TRACE("CTaskBand::Load called\n");
223         /* Nothing to do */
224         return S_OK;
225     }
226 
227     virtual HRESULT STDMETHODCALLTYPE Save(
228         IN IStream *pStm,
229         IN BOOL fClearDirty)
230     {
231         /* Nothing to do */
232         return S_OK;
233     }
234 
235     virtual HRESULT STDMETHODCALLTYPE GetSizeMax(
236         OUT ULARGE_INTEGER *pcbSize)
237     {
238         TRACE("CTaskBand::GetSizeMax called\n");
239         /* We don't need any space for the task band */
240         pcbSize->QuadPart = 0;
241         return S_OK;
242     }
243 
244     /*****************************************************************************/
245 
246     virtual HRESULT STDMETHODCALLTYPE SetSite(IUnknown *pUnkSite)
247     {
248         HRESULT hRet;
249         HWND hwndSite;
250 
251         TRACE("CTaskBand::SetSite(0x%p)\n", pUnkSite);
252 
253         hRet = IUnknown_GetWindow(pUnkSite, &hwndSite);
254         if (FAILED_UNEXPECTEDLY(hRet))
255             return hRet;
256 
257         TRACE("CreateTaskSwitchWnd(Parent: 0x%p)\n", hwndSite);
258 
259         hRet = CTaskSwitchWnd_CreateInstance(hwndSite, m_Tray, IID_PPV_ARG(IUnknown, &m_TasksWnd));
260         if (FAILED_UNEXPECTEDLY(hRet))
261             return hRet;
262 
263         hRet = IUnknown_GetWindow(m_TasksWnd, &m_hWnd);
264         if (FAILED_UNEXPECTEDLY(hRet))
265             return hRet;
266 
267         m_Site = pUnkSite;
268 
269         return S_OK;
270     }
271 
272     virtual HRESULT STDMETHODCALLTYPE GetSite(
273         IN REFIID riid,
274         OUT VOID **ppvSite)
275     {
276         TRACE("CTaskBand::GetSite(0x%p,0x%p)\n", riid, ppvSite);
277 
278         if (m_Site != NULL)
279         {
280             return m_Site->QueryInterface(riid, ppvSite);
281         }
282 
283         *ppvSite = NULL;
284         return E_FAIL;
285     }
286 
287     /*****************************************************************************/
288 
289     virtual HRESULT STDMETHODCALLTYPE ProcessMessage(
290         IN HWND hWnd,
291         IN UINT uMsg,
292         IN WPARAM wParam,
293         IN LPARAM lParam,
294         OUT LRESULT *plrResult)
295     {
296         TRACE("CTaskBand: IWinEventHandler::ProcessMessage(0x%p, 0x%x, 0x%p, 0x%p, 0x%p)\n", hWnd, uMsg, wParam, lParam, plrResult);
297         return E_NOTIMPL;
298     }
299 
300     virtual HRESULT STDMETHODCALLTYPE ContainsWindow(
301         IN HWND hWnd)
302     {
303         if (hWnd == m_hWnd ||
304             IsChild(m_hWnd, hWnd))
305         {
306             TRACE("CTaskBand::ContainsWindow(0x%p) returns S_OK\n", hWnd);
307             return S_OK;
308         }
309 
310         return S_FALSE;
311     }
312 
313     virtual HRESULT STDMETHODCALLTYPE OnWinEvent(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT *theResult)
314     {
315         //UNIMPLEMENTED;
316         return E_NOTIMPL;
317     }
318 
319     virtual HRESULT STDMETHODCALLTYPE IsWindowOwner(HWND hWnd)
320     {
321         return (hWnd == m_hWnd) ? S_OK : S_FALSE;
322     }
323 
324     /*****************************************************************************/
325 
326     HRESULT STDMETHODCALLTYPE Initialize(IN OUT ITrayWindow *tray, HWND hWndStartButton)
327     {
328         m_Tray = tray;
329         return S_OK;
330     }
331 
332     DECLARE_NOT_AGGREGATABLE(CTaskBand)
333 
334     DECLARE_PROTECT_FINAL_CONSTRUCT()
335     BEGIN_COM_MAP(CTaskBand)
336         COM_INTERFACE_ENTRY2_IID(IID_IOleWindow, IOleWindow, IDeskBand)
337         COM_INTERFACE_ENTRY_IID(IID_IDeskBand, IDeskBand)
338         COM_INTERFACE_ENTRY_IID(IID_IObjectWithSite, IObjectWithSite)
339         COM_INTERFACE_ENTRY_IID(IID_IPersist, IPersist)
340         COM_INTERFACE_ENTRY_IID(IID_IPersistStream, IPersistStream)
341         COM_INTERFACE_ENTRY_IID(IID_IWinEventHandler, IWinEventHandler)
342         COM_INTERFACE_ENTRY_IID(IID_IOleCommandTarget, IOleCommandTarget)
343     END_COM_MAP()
344 };
345 
346 HRESULT CTaskBand_CreateInstance(IN ITrayWindow *Tray, HWND hWndStartButton, REFIID riid, void **ppv)
347 {
348     return ShellObjectCreatorInit<CTaskBand>(Tray, hWndStartButton, riid, ppv);
349 }
350