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