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