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