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