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