b7bc13388df6d0c9c08af0c5647dd61b0efa425e
[reactos.git] / base / shell / explorer / taskband.cpp
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 }