1 /* 2 * ReactOS Explorer 3 * 4 * Copyright 2009 Andrew Hill <ash77 at domain 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 */ 20 21 /* 22 Base bar that contains a vertical or horizontal explorer band. It also 23 provides resizing abilities. 24 */ 25 26 #include "precomp.h" 27 28 /* 29 TODO: 30 ****Fix so an already created bar will be detected and just shown instead of added again 31 ****When a new bar is added, initiate a resize 32 **Add owner draw for base bar 33 **Make label text in base bar always draw in black 34 **Make base bar show close box 35 **Create close toolbar button 36 **Fix to delete all CBarInfo on deletion 37 38 */ 39 40 class CBaseBarSite : 41 public CWindowImpl<CBaseBarSite, CWindow, CControlWinTraits>, 42 public CComObjectRootEx<CComMultiThreadModelNoCS>, 43 // public IDockingWindowSite, 44 public IInputObject, 45 public IServiceProvider, 46 public IWinEventHandler, 47 public IInputObjectSite, 48 public IDeskBarClient, 49 public IOleCommandTarget, 50 public IBandSite, 51 // public IBandSiteHelper, 52 // public IExplorerToolbar, 53 public IPersistStream 54 { 55 private: 56 class CBarInfo 57 { 58 public: 59 CComPtr<IUnknown> fTheBar; 60 CLSID fBarClass; // class of active bar 61 DWORD fBandID; 62 63 }; 64 CBarInfo *fCurrentActiveBar; // 65 // HWND fRebarWindow; // rebar for top of window 66 CComPtr<IUnknown> fDeskBarSite; 67 DWORD fNextBandID; 68 public: 69 CBaseBarSite(); 70 ~CBaseBarSite(); 71 private: 72 HRESULT InsertBar(IUnknown *newBar); 73 74 // *** IOleWindow methods *** 75 virtual HRESULT STDMETHODCALLTYPE GetWindow(HWND *lphwnd); 76 virtual HRESULT STDMETHODCALLTYPE ContextSensitiveHelp(BOOL fEnterMode); 77 78 // *** IInputObject methods *** 79 virtual HRESULT STDMETHODCALLTYPE UIActivateIO(BOOL fActivate, LPMSG lpMsg); 80 virtual HRESULT STDMETHODCALLTYPE HasFocusIO(); 81 virtual HRESULT STDMETHODCALLTYPE TranslateAcceleratorIO(LPMSG lpMsg); 82 83 // *** IServiceProvider methods *** 84 virtual HRESULT STDMETHODCALLTYPE QueryService(REFGUID guidService, REFIID riid, void **ppvObject); 85 86 // *** IWinEventHandler methods *** 87 virtual HRESULT STDMETHODCALLTYPE OnWinEvent( 88 HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT *theResult); 89 virtual HRESULT STDMETHODCALLTYPE IsWindowOwner(HWND hWnd); 90 91 // *** IInputObjectSite specific methods *** 92 virtual HRESULT STDMETHODCALLTYPE OnFocusChangeIS(IUnknown *punkObj, BOOL fSetFocus); 93 94 // *** IDeskBarClient methods *** 95 virtual HRESULT STDMETHODCALLTYPE SetDeskBarSite(IUnknown *punkSite); 96 virtual HRESULT STDMETHODCALLTYPE SetModeDBC(DWORD dwMode); 97 virtual HRESULT STDMETHODCALLTYPE UIActivateDBC(DWORD dwState); 98 virtual HRESULT STDMETHODCALLTYPE GetSize(DWORD dwWhich, LPRECT prc); 99 100 // *** IOleCommandTarget methods *** 101 virtual HRESULT STDMETHODCALLTYPE QueryStatus(const GUID *pguidCmdGroup, ULONG cCmds, 102 OLECMD prgCmds[ ], OLECMDTEXT *pCmdText); 103 virtual HRESULT STDMETHODCALLTYPE Exec(const GUID *pguidCmdGroup, DWORD nCmdID, 104 DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut); 105 106 // *** IBandSite specific methods *** 107 virtual HRESULT STDMETHODCALLTYPE AddBand(IUnknown *punk); 108 virtual HRESULT STDMETHODCALLTYPE EnumBands(UINT uBand, DWORD *pdwBandID); 109 virtual HRESULT STDMETHODCALLTYPE QueryBand(DWORD dwBandID, IDeskBand **ppstb, DWORD *pdwState, 110 LPWSTR pszName, int cchName); 111 virtual HRESULT STDMETHODCALLTYPE SetBandState(DWORD dwBandID, DWORD dwMask, DWORD dwState); 112 virtual HRESULT STDMETHODCALLTYPE RemoveBand(DWORD dwBandID); 113 virtual HRESULT STDMETHODCALLTYPE GetBandObject(DWORD dwBandID, REFIID riid, void **ppv); 114 virtual HRESULT STDMETHODCALLTYPE SetBandSiteInfo(const BANDSITEINFO *pbsinfo); 115 virtual HRESULT STDMETHODCALLTYPE GetBandSiteInfo(BANDSITEINFO *pbsinfo); 116 117 // *** IPersist methods *** 118 virtual HRESULT STDMETHODCALLTYPE GetClassID(CLSID *pClassID); 119 120 // *** IPersistStream methods *** 121 virtual HRESULT STDMETHODCALLTYPE IsDirty(); 122 virtual HRESULT STDMETHODCALLTYPE Load(IStream *pStm); 123 virtual HRESULT STDMETHODCALLTYPE Save(IStream *pStm, BOOL fClearDirty); 124 virtual HRESULT STDMETHODCALLTYPE GetSizeMax(ULARGE_INTEGER *pcbSize); 125 126 // message handlers 127 LRESULT OnNotify(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled); 128 129 BEGIN_MSG_MAP(CBaseBarSite) 130 MESSAGE_HANDLER(WM_NOTIFY, OnNotify) 131 END_MSG_MAP() 132 133 BEGIN_COM_MAP(CBaseBarSite) 134 COM_INTERFACE_ENTRY_IID(IID_IOleWindow, IOleWindow) 135 // COM_INTERFACE_ENTRY_IID(IID_IDockingWindowSite, IDockingWindowSite) 136 COM_INTERFACE_ENTRY_IID(IID_IInputObject, IInputObject) 137 COM_INTERFACE_ENTRY_IID(IID_IServiceProvider, IServiceProvider) 138 COM_INTERFACE_ENTRY_IID(IID_IWinEventHandler, IWinEventHandler) 139 COM_INTERFACE_ENTRY_IID(IID_IInputObjectSite, IInputObjectSite) 140 COM_INTERFACE_ENTRY_IID(IID_IDeskBarClient, IDeskBarClient) 141 COM_INTERFACE_ENTRY_IID(IID_IOleCommandTarget, IOleCommandTarget) 142 COM_INTERFACE_ENTRY_IID(IID_IBandSite, IBandSite) 143 // COM_INTERFACE_ENTRY_IID(IID_IBandSiteHelper, IBandSiteHelper) 144 // COM_INTERFACE_ENTRY_IID(IID_IExplorerToolbar, IExplorerToolbar) 145 COM_INTERFACE_ENTRY_IID(IID_IPersist, IPersist) 146 COM_INTERFACE_ENTRY_IID(IID_IPersistStream, IPersistStream) 147 END_COM_MAP() 148 }; 149 150 CBaseBarSite::CBaseBarSite() 151 { 152 fCurrentActiveBar = NULL; 153 fNextBandID = 1; 154 } 155 156 CBaseBarSite::~CBaseBarSite() 157 { 158 } 159 160 HRESULT CBaseBarSite::InsertBar(IUnknown *newBar) 161 { 162 CComPtr<IPersist> persist; 163 CComPtr<IObjectWithSite> site; 164 CComPtr<IOleWindow> oleWindow; 165 CComPtr<IDeskBand> deskBand; 166 CComPtr<IDockingWindow> dockingWindow; 167 CBarInfo *newInfo; 168 REBARBANDINFOW bandInfo; 169 DESKBANDINFO deskBandInfo; 170 DWORD thisBandID; 171 HRESULT hResult; 172 173 hResult = newBar->QueryInterface(IID_PPV_ARG(IPersist, &persist)); 174 if (FAILED_UNEXPECTEDLY(hResult)) 175 return hResult; 176 hResult = newBar->QueryInterface(IID_PPV_ARG(IObjectWithSite, &site)); 177 if (FAILED_UNEXPECTEDLY(hResult)) 178 return hResult; 179 hResult = newBar->QueryInterface(IID_PPV_ARG(IOleWindow, &oleWindow)); 180 if (FAILED_UNEXPECTEDLY(hResult)) 181 return hResult; 182 hResult = newBar->QueryInterface(IID_PPV_ARG(IDeskBand, &deskBand)); 183 if (FAILED_UNEXPECTEDLY(hResult)) 184 return hResult; 185 hResult = newBar->QueryInterface(IID_PPV_ARG(IDockingWindow, &dockingWindow)); 186 if (FAILED_UNEXPECTEDLY(hResult)) 187 return hResult; 188 hResult = site->SetSite(static_cast<IOleWindow *>(this)); 189 if (FAILED_UNEXPECTEDLY(hResult)) 190 return hResult; 191 ATLTRY(newInfo = new CBarInfo); 192 if (newInfo == NULL) 193 return E_OUTOFMEMORY; 194 195 // set new bar info 196 thisBandID = fNextBandID++; 197 newInfo->fTheBar = newBar; 198 newInfo->fBandID = thisBandID; 199 hResult = persist->GetClassID(&newInfo->fBarClass); 200 201 // get band info 202 deskBandInfo.dwMask = DBIM_MINSIZE | DBIM_ACTUAL | DBIM_TITLE; 203 deskBandInfo.wszTitle[0] = 0; 204 hResult = deskBand->GetBandInfo(0, 0, &deskBandInfo); 205 206 // insert band 207 memset(&bandInfo, 0, sizeof(bandInfo)); 208 bandInfo.cbSize = sizeof(bandInfo); 209 bandInfo.fMask = RBBIM_STYLE | RBBIM_CHILD | RBBIM_CHILDSIZE | RBBIM_IDEALSIZE | RBBIM_TEXT | 210 RBBIM_LPARAM | RBBIM_ID; 211 bandInfo.fStyle = RBBS_NOGRIPPER | RBBS_VARIABLEHEIGHT; 212 bandInfo.lpText = deskBandInfo.wszTitle; 213 hResult = oleWindow->GetWindow(&bandInfo.hwndChild); 214 bandInfo.cxMinChild = 200; //deskBandInfo.ptMinSize.x; 215 bandInfo.cyMinChild = 200; //deskBandInfo.ptMinSize.y; 216 bandInfo.cx = 0; 217 bandInfo.wID = thisBandID; 218 bandInfo.cyChild = -1; //deskBandInfo.ptActual.y; 219 bandInfo.cyMaxChild = 32000; 220 bandInfo.cyIntegral = 1; 221 bandInfo.cxIdeal = 0; //deskBandInfo.ptActual.x; 222 bandInfo.lParam = reinterpret_cast<LPARAM>(newInfo); 223 SendMessage(RB_INSERTBANDW, -1, reinterpret_cast<LPARAM>(&bandInfo)); 224 225 // this call is what makes the tree fill with contents 226 hResult = dockingWindow->ShowDW(TRUE); 227 if (FAILED_UNEXPECTEDLY(hResult)) 228 return hResult; 229 // for now 230 fCurrentActiveBar = newInfo; 231 return S_OK; 232 } 233 234 HRESULT STDMETHODCALLTYPE CBaseBarSite::GetWindow(HWND *lphwnd) 235 { 236 if (lphwnd == NULL) 237 return E_POINTER; 238 *lphwnd = m_hWnd; 239 return S_OK; 240 } 241 242 HRESULT STDMETHODCALLTYPE CBaseBarSite::ContextSensitiveHelp(BOOL fEnterMode) 243 { 244 return E_NOTIMPL; 245 } 246 247 HRESULT STDMETHODCALLTYPE CBaseBarSite::UIActivateIO(BOOL fActivate, LPMSG lpMsg) 248 { 249 return E_NOTIMPL; 250 } 251 252 HRESULT STDMETHODCALLTYPE CBaseBarSite::HasFocusIO() 253 { 254 return E_NOTIMPL; 255 } 256 257 HRESULT STDMETHODCALLTYPE CBaseBarSite::TranslateAcceleratorIO(LPMSG lpMsg) 258 { 259 return E_NOTIMPL; 260 } 261 262 HRESULT STDMETHODCALLTYPE CBaseBarSite::QueryService(REFGUID guidService, REFIID riid, void **ppvObject) 263 { 264 CComPtr<IServiceProvider> serviceProvider; 265 HRESULT hResult; 266 267 if (fDeskBarSite == NULL) 268 return E_FAIL; 269 hResult = fDeskBarSite->QueryInterface(IID_PPV_ARG(IServiceProvider, &serviceProvider)); 270 if (FAILED_UNEXPECTEDLY(hResult)) 271 return hResult; 272 // called for SID_STopLevelBrowser, IID_IBrowserService to find top level browser 273 // called for SID_IWebBrowserApp, IID_IConnectionPointContainer 274 // connection point called for DIID_DWebBrowserEvents2 to establish connection 275 return serviceProvider->QueryService(guidService, riid, ppvObject); 276 } 277 278 HRESULT STDMETHODCALLTYPE CBaseBarSite::OnWinEvent( 279 HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT *theResult) 280 { 281 CComPtr<IDeskBar> deskBar; 282 CComPtr<IWinEventHandler> winEventHandler; 283 NMHDR *notifyHeader; 284 RECT newBounds; 285 HRESULT hResult; 286 287 hResult = S_OK; 288 if (uMsg == WM_NOTIFY) 289 { 290 notifyHeader = (NMHDR *)lParam; 291 if (notifyHeader->hwndFrom == m_hWnd && notifyHeader->code == RBN_AUTOSIZE) 292 { 293 hResult = fDeskBarSite->QueryInterface(IID_PPV_ARG(IDeskBar, &deskBar)); 294 GetClientRect(&newBounds); 295 hResult = deskBar->OnPosRectChangeDB(&newBounds); 296 } 297 } 298 if (fCurrentActiveBar != NULL) 299 { 300 hResult = fCurrentActiveBar->fTheBar->QueryInterface( 301 IID_PPV_ARG(IWinEventHandler, &winEventHandler)); 302 if (SUCCEEDED(hResult) && winEventHandler.p != NULL) 303 hResult = winEventHandler->OnWinEvent(hWnd, uMsg, wParam, lParam, theResult); 304 } 305 return hResult; 306 } 307 308 HRESULT STDMETHODCALLTYPE CBaseBarSite::IsWindowOwner(HWND hWnd) 309 { 310 return E_NOTIMPL; 311 } 312 313 HRESULT STDMETHODCALLTYPE CBaseBarSite::OnFocusChangeIS (IUnknown *punkObj, BOOL fSetFocus) 314 { 315 return E_NOTIMPL; 316 } 317 318 HRESULT STDMETHODCALLTYPE CBaseBarSite::SetDeskBarSite(IUnknown *punkSite) 319 { 320 CComPtr<IOleWindow> oleWindow; 321 HWND ownerWindow; 322 HRESULT hResult; 323 324 if (punkSite == NULL) 325 fDeskBarSite.Release(); 326 else 327 { 328 hResult = punkSite->QueryInterface(IID_PPV_ARG(IOleWindow, &oleWindow)); 329 if (FAILED_UNEXPECTEDLY(hResult)) 330 return hResult; 331 hResult = punkSite->QueryInterface(IID_PPV_ARG(IUnknown, &fDeskBarSite)); 332 if (FAILED_UNEXPECTEDLY(hResult)) 333 return hResult; 334 hResult = oleWindow->GetWindow(&ownerWindow); 335 if (FAILED_UNEXPECTEDLY(hResult)) 336 return hResult; 337 m_hWnd = CreateWindow(REBARCLASSNAMEW, NULL, WS_VISIBLE | WS_CHILDWINDOW | WS_CLIPSIBLINGS | 338 WS_CLIPCHILDREN | 339 RBS_VARHEIGHT | RBS_REGISTERDROP | RBS_AUTOSIZE | RBS_VERTICALGRIPPER | RBS_DBLCLKTOGGLE | 340 CCS_LEFT | CCS_NODIVIDER | CCS_NOPARENTALIGN | CCS_NORESIZE, 0, 0, 0, 0, ownerWindow, NULL, 341 _AtlBaseModule.GetModuleInstance(), NULL); 342 SendMessage(RB_SETTEXTCOLOR, 0, CLR_DEFAULT); 343 SendMessage(RB_SETBKCOLOR, 0, CLR_DEFAULT); 344 } 345 return S_OK; 346 } 347 348 HRESULT STDMETHODCALLTYPE CBaseBarSite::SetModeDBC(DWORD dwMode) 349 { 350 return E_NOTIMPL; 351 } 352 353 HRESULT STDMETHODCALLTYPE CBaseBarSite::UIActivateDBC(DWORD dwState) 354 { 355 return E_NOTIMPL; 356 } 357 358 HRESULT STDMETHODCALLTYPE CBaseBarSite::GetSize(DWORD dwWhich, LPRECT prc) 359 { 360 return E_NOTIMPL; 361 } 362 363 HRESULT STDMETHODCALLTYPE CBaseBarSite::QueryStatus(const GUID *pguidCmdGroup, 364 ULONG cCmds, OLECMD prgCmds[ ], OLECMDTEXT *pCmdText) 365 { 366 return E_NOTIMPL; 367 } 368 369 HRESULT STDMETHODCALLTYPE CBaseBarSite::Exec(const GUID *pguidCmdGroup, DWORD nCmdID, 370 DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut) 371 { 372 if (IsEqualIID(*pguidCmdGroup, IID_IDeskBand)) 373 { 374 switch (nCmdID) 375 { 376 case 1: // insert a new band 377 if (V_VT(pvaIn) != VT_UNKNOWN) 378 return E_INVALIDARG; 379 return InsertBar(V_UNKNOWN(pvaIn)); 380 } 381 } 382 return E_FAIL; 383 } 384 385 HRESULT STDMETHODCALLTYPE CBaseBarSite::AddBand(IUnknown *punk) 386 { 387 return InsertBar(punk); 388 } 389 390 HRESULT STDMETHODCALLTYPE CBaseBarSite::EnumBands(UINT uBand, DWORD *pdwBandID) 391 { 392 if (uBand == 0xffffffff) 393 { 394 *pdwBandID = (DWORD)SendMessage(RB_GETBANDCOUNT, 0, 0); 395 return S_OK; 396 } 397 return E_NOTIMPL; 398 } 399 400 HRESULT STDMETHODCALLTYPE CBaseBarSite::QueryBand(DWORD dwBandID, IDeskBand **ppstb, 401 DWORD *pdwState, LPWSTR pszName, int cchName) 402 { 403 return E_NOTIMPL; 404 } 405 406 HRESULT STDMETHODCALLTYPE CBaseBarSite::SetBandState(DWORD dwBandID, DWORD dwMask, DWORD dwState) 407 { 408 return E_NOTIMPL; 409 } 410 411 HRESULT STDMETHODCALLTYPE CBaseBarSite::RemoveBand(DWORD dwBandID) 412 { 413 return E_NOTIMPL; 414 } 415 416 HRESULT STDMETHODCALLTYPE CBaseBarSite::GetBandObject(DWORD dwBandID, REFIID riid, void **ppv) 417 { 418 if (ppv == NULL) 419 return E_POINTER; 420 return E_NOTIMPL; 421 } 422 423 HRESULT STDMETHODCALLTYPE CBaseBarSite::SetBandSiteInfo(const BANDSITEINFO *pbsinfo) 424 { 425 if (pbsinfo == NULL) 426 return E_POINTER; 427 return E_NOTIMPL; 428 } 429 430 HRESULT STDMETHODCALLTYPE CBaseBarSite::GetBandSiteInfo(BANDSITEINFO *pbsinfo) 431 { 432 if (pbsinfo == NULL) 433 return E_POINTER; 434 return E_NOTIMPL; 435 } 436 437 HRESULT STDMETHODCALLTYPE CBaseBarSite::GetClassID(CLSID *pClassID) 438 { 439 if (pClassID == NULL) 440 return E_POINTER; 441 // TODO: what class to return here? 442 return E_NOTIMPL; 443 } 444 445 HRESULT STDMETHODCALLTYPE CBaseBarSite::IsDirty() 446 { 447 return E_NOTIMPL; 448 } 449 450 HRESULT STDMETHODCALLTYPE CBaseBarSite::Load(IStream *pStm) 451 { 452 return E_NOTIMPL; 453 } 454 455 HRESULT STDMETHODCALLTYPE CBaseBarSite::Save(IStream *pStm, BOOL fClearDirty) 456 { 457 return E_NOTIMPL; 458 } 459 460 HRESULT STDMETHODCALLTYPE CBaseBarSite::GetSizeMax(ULARGE_INTEGER *pcbSize) 461 { 462 if (pcbSize == NULL) 463 return E_POINTER; 464 return E_NOTIMPL; 465 } 466 467 LRESULT CBaseBarSite::OnNotify(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled) 468 { 469 NMHDR *notifyHeader; 470 471 notifyHeader = reinterpret_cast<NMHDR *>(lParam); 472 if (notifyHeader->hwndFrom == m_hWnd) 473 { 474 } 475 return 0; 476 } 477 478 HRESULT CreateBaseBarSite(REFIID riid, void **ppv) 479 { 480 return ShellObjectCreator<CBaseBarSite>(riid, ppv); 481 } 482