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 ****When a new bar is added, resize correctly the band inside instead of keeping current size. 31 *Translate close button label 32 **Add owner draw for base bar -- hackplemented atm 33 **Make label text in base bar always draw in black 34 ***Set rebar band style flags accordingly to what band object asked. 35 ***Set rebar style accordingly to direction 36 ****This class should also manage desktop bands ? (another kind of explorer bands) 37 */ 38 39 class CBaseBarSite : 40 public CWindowImpl<CBaseBarSite, CWindow, CControlWinTraits>, 41 public CComObjectRootEx<CComMultiThreadModelNoCS>, 42 // public IDockingWindowSite, 43 public IInputObject, 44 public IServiceProvider, 45 public IWinEventHandler, 46 public IInputObjectSite, 47 public IDeskBarClient, 48 public IOleCommandTarget, 49 public IBandSite, 50 // public IBandSiteHelper, 51 // public IExplorerToolbar, 52 public IPersistStream 53 { 54 private: 55 class CBarInfo 56 { 57 public: 58 CComPtr<IUnknown> fTheBar; 59 CLSID fBarClass; // class of active bar 60 DWORD fBandID; 61 62 }; 63 CBarInfo *fCurrentActiveBar; // 64 // HWND fRebarWindow; // rebar for top of window 65 CComPtr<IUnknown> fDeskBarSite; 66 DWORD fNextBandID; 67 HWND toolbarWnd; 68 HIMAGELIST toolImageList; 69 BOOL fVertical; 70 public: 71 CBaseBarSite(); 72 ~CBaseBarSite(); 73 HRESULT Initialize(BOOL vert) { fVertical = vert; return S_OK; }; 74 private: 75 HRESULT InsertBar(IUnknown *newBar); 76 77 // *** IOleWindow methods *** 78 virtual HRESULT STDMETHODCALLTYPE GetWindow(HWND *lphwnd); 79 virtual HRESULT STDMETHODCALLTYPE ContextSensitiveHelp(BOOL fEnterMode); 80 81 // *** IInputObject methods *** 82 virtual HRESULT STDMETHODCALLTYPE UIActivateIO(BOOL fActivate, LPMSG lpMsg); 83 virtual HRESULT STDMETHODCALLTYPE HasFocusIO(); 84 virtual HRESULT STDMETHODCALLTYPE TranslateAcceleratorIO(LPMSG lpMsg); 85 86 // *** IServiceProvider methods *** 87 virtual HRESULT STDMETHODCALLTYPE QueryService(REFGUID guidService, REFIID riid, void **ppvObject); 88 89 // *** IWinEventHandler methods *** 90 virtual HRESULT STDMETHODCALLTYPE OnWinEvent( 91 HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT *theResult); 92 virtual HRESULT STDMETHODCALLTYPE IsWindowOwner(HWND hWnd); 93 94 // *** IInputObjectSite specific methods *** 95 virtual HRESULT STDMETHODCALLTYPE OnFocusChangeIS(IUnknown *punkObj, BOOL fSetFocus); 96 97 // *** IDeskBarClient methods *** 98 virtual HRESULT STDMETHODCALLTYPE SetDeskBarSite(IUnknown *punkSite); 99 virtual HRESULT STDMETHODCALLTYPE SetModeDBC(DWORD dwMode); 100 virtual HRESULT STDMETHODCALLTYPE UIActivateDBC(DWORD dwState); 101 virtual HRESULT STDMETHODCALLTYPE GetSize(DWORD dwWhich, LPRECT prc); 102 103 // *** IOleCommandTarget methods *** 104 virtual HRESULT STDMETHODCALLTYPE QueryStatus(const GUID *pguidCmdGroup, ULONG cCmds, 105 OLECMD prgCmds[ ], OLECMDTEXT *pCmdText); 106 virtual HRESULT STDMETHODCALLTYPE Exec(const GUID *pguidCmdGroup, DWORD nCmdID, 107 DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut); 108 109 // *** IBandSite specific methods *** 110 virtual HRESULT STDMETHODCALLTYPE AddBand(IUnknown *punk); 111 virtual HRESULT STDMETHODCALLTYPE EnumBands(UINT uBand, DWORD *pdwBandID); 112 virtual HRESULT STDMETHODCALLTYPE QueryBand(DWORD dwBandID, IDeskBand **ppstb, DWORD *pdwState, 113 LPWSTR pszName, int cchName); 114 virtual HRESULT STDMETHODCALLTYPE SetBandState(DWORD dwBandID, DWORD dwMask, DWORD dwState); 115 virtual HRESULT STDMETHODCALLTYPE RemoveBand(DWORD dwBandID); 116 virtual HRESULT STDMETHODCALLTYPE GetBandObject(DWORD dwBandID, REFIID riid, void **ppv); 117 virtual HRESULT STDMETHODCALLTYPE SetBandSiteInfo(const BANDSITEINFO *pbsinfo); 118 virtual HRESULT STDMETHODCALLTYPE GetBandSiteInfo(BANDSITEINFO *pbsinfo); 119 120 // *** IPersist methods *** 121 virtual HRESULT STDMETHODCALLTYPE GetClassID(CLSID *pClassID); 122 123 // *** IPersistStream methods *** 124 virtual HRESULT STDMETHODCALLTYPE IsDirty(); 125 virtual HRESULT STDMETHODCALLTYPE Load(IStream *pStm); 126 virtual HRESULT STDMETHODCALLTYPE Save(IStream *pStm, BOOL fClearDirty); 127 virtual HRESULT STDMETHODCALLTYPE GetSizeMax(ULARGE_INTEGER *pcbSize); 128 129 // message handlers 130 LRESULT OnNotify(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled); 131 LRESULT OnCommand(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled); 132 LRESULT OnCustomDraw(LPNMCUSTOMDRAW pnmcd); 133 134 // Helper functions 135 HFONT GetTitleFont(); 136 HRESULT FindBandByGUID(REFIID pGuid, DWORD *pdwBandID); 137 HRESULT ShowBand(DWORD dwBandID); 138 HRESULT GetInternalBandInfo(UINT uBand, REBARBANDINFO *pBandInfo); 139 HRESULT GetInternalBandInfo(UINT uBand, REBARBANDINFO *pBandInfo, DWORD fMask); 140 141 142 BEGIN_MSG_MAP(CBaseBarSite) 143 MESSAGE_HANDLER(WM_NOTIFY, OnNotify) 144 MESSAGE_HANDLER(WM_COMMAND, OnCommand) 145 END_MSG_MAP() 146 147 BEGIN_COM_MAP(CBaseBarSite) 148 COM_INTERFACE_ENTRY_IID(IID_IOleWindow, IOleWindow) 149 // COM_INTERFACE_ENTRY_IID(IID_IDockingWindowSite, IDockingWindowSite) 150 COM_INTERFACE_ENTRY_IID(IID_IInputObject, IInputObject) 151 COM_INTERFACE_ENTRY_IID(IID_IServiceProvider, IServiceProvider) 152 COM_INTERFACE_ENTRY_IID(IID_IWinEventHandler, IWinEventHandler) 153 COM_INTERFACE_ENTRY_IID(IID_IInputObjectSite, IInputObjectSite) 154 COM_INTERFACE_ENTRY_IID(IID_IDeskBarClient, IDeskBarClient) 155 COM_INTERFACE_ENTRY_IID(IID_IOleCommandTarget, IOleCommandTarget) 156 COM_INTERFACE_ENTRY_IID(IID_IBandSite, IBandSite) 157 // COM_INTERFACE_ENTRY_IID(IID_IBandSiteHelper, IBandSiteHelper) 158 // COM_INTERFACE_ENTRY_IID(IID_IExplorerToolbar, IExplorerToolbar) 159 COM_INTERFACE_ENTRY_IID(IID_IPersist, IPersist) 160 COM_INTERFACE_ENTRY_IID(IID_IPersistStream, IPersistStream) 161 END_COM_MAP() 162 }; 163 164 CBaseBarSite::CBaseBarSite() : fVertical(TRUE) 165 { 166 fCurrentActiveBar = NULL; 167 fNextBandID = 1; 168 } 169 170 CBaseBarSite::~CBaseBarSite() 171 { 172 TRACE("CBaseBarSite deleted\n"); 173 } 174 175 HRESULT CBaseBarSite::InsertBar(IUnknown *newBar) 176 { 177 CComPtr<IPersist> persist; 178 CComPtr<IObjectWithSite> site; 179 CComPtr<IOleWindow> oleWindow; 180 CComPtr<IDeskBand> deskBand; 181 CBarInfo *newInfo; 182 REBARBANDINFOW bandInfo; 183 DESKBANDINFO deskBandInfo; 184 DWORD thisBandID; 185 HRESULT hResult; 186 CLSID tmp; 187 188 hResult = newBar->QueryInterface(IID_PPV_ARG(IPersist, &persist)); 189 if (FAILED_UNEXPECTEDLY(hResult)) 190 return hResult; 191 hResult = newBar->QueryInterface(IID_PPV_ARG(IObjectWithSite, &site)); 192 if (FAILED_UNEXPECTEDLY(hResult)) 193 return hResult; 194 hResult = newBar->QueryInterface(IID_PPV_ARG(IOleWindow, &oleWindow)); 195 if (FAILED_UNEXPECTEDLY(hResult)) 196 return hResult; 197 hResult = newBar->QueryInterface(IID_PPV_ARG(IDeskBand, &deskBand)); 198 if (FAILED_UNEXPECTEDLY(hResult)) 199 return hResult; 200 201 // Check if the GUID already exists 202 hResult = persist->GetClassID(&tmp); 203 if (!SUCCEEDED(hResult)) 204 { 205 return E_INVALIDARG; 206 } 207 if (FindBandByGUID(tmp, &thisBandID) == S_OK) 208 { 209 return ShowBand(thisBandID); 210 } 211 212 hResult = site->SetSite(static_cast<IOleWindow *>(this)); 213 if (FAILED_UNEXPECTEDLY(hResult)) 214 return hResult; 215 216 ATLTRY(newInfo = new CBarInfo); 217 if (newInfo == NULL) 218 return E_OUTOFMEMORY; 219 220 // set new bar info 221 thisBandID = fNextBandID++; 222 newInfo->fTheBar = newBar; 223 newInfo->fBandID = thisBandID; 224 newInfo->fBarClass = tmp; 225 226 // get band info 227 deskBandInfo.dwMask = DBIM_MINSIZE | DBIM_ACTUAL | DBIM_TITLE | DBIM_BKCOLOR; 228 deskBandInfo.wszTitle[0] = 0; 229 hResult = deskBand->GetBandInfo(0, (fVertical) ? DBIF_VIEWMODE_VERTICAL : DBIF_VIEWMODE_NORMAL, &deskBandInfo); 230 231 // insert band 232 memset(&bandInfo, 0, sizeof(bandInfo)); 233 bandInfo.cbSize = sizeof(bandInfo); 234 bandInfo.fMask = RBBIM_STYLE | RBBIM_CHILD | RBBIM_CHILDSIZE | RBBIM_IDEALSIZE | RBBIM_TEXT | 235 RBBIM_LPARAM | RBBIM_ID; 236 bandInfo.fStyle = RBBS_TOPALIGN | RBBS_VARIABLEHEIGHT | RBBS_NOGRIPPER; 237 bandInfo.lpText = deskBandInfo.wszTitle; 238 hResult = oleWindow->GetWindow(&bandInfo.hwndChild); 239 /* It seems Windows XP doesn't take account of band minsize */ 240 #if 0 241 bandInfo.cxMinChild = 200; //deskBandInfo.ptMinSize.x; 242 bandInfo.cyMinChild = 200; //deskBandInfo.ptMinSize.y; 243 #endif 244 bandInfo.cx = 0; 245 bandInfo.wID = thisBandID; 246 bandInfo.cyChild = -1; //deskBandInfo.ptActual.y; 247 bandInfo.cyMaxChild = 32000; 248 bandInfo.cyIntegral = 1; 249 bandInfo.cxIdeal = 0; //deskBandInfo.ptActual.x; 250 bandInfo.lParam = reinterpret_cast<LPARAM>(newInfo); 251 SendMessage(RB_INSERTBANDW, -1, reinterpret_cast<LPARAM>(&bandInfo)); 252 hResult = ShowBand(newInfo->fBandID); 253 //fCurrentActiveBar = newInfo; 254 return hResult; 255 } 256 257 HRESULT STDMETHODCALLTYPE CBaseBarSite::GetWindow(HWND *lphwnd) 258 { 259 if (lphwnd == NULL) 260 return E_POINTER; 261 *lphwnd = m_hWnd; 262 return S_OK; 263 } 264 265 HRESULT STDMETHODCALLTYPE CBaseBarSite::ContextSensitiveHelp(BOOL fEnterMode) 266 { 267 return E_NOTIMPL; 268 } 269 270 HRESULT STDMETHODCALLTYPE CBaseBarSite::UIActivateIO(BOOL fActivate, LPMSG lpMsg) 271 { 272 if (!fCurrentActiveBar) 273 return S_OK; 274 275 return IUnknown_UIActivateIO(fCurrentActiveBar->fTheBar, fActivate, lpMsg); 276 } 277 278 HRESULT STDMETHODCALLTYPE CBaseBarSite::HasFocusIO() 279 { 280 if (!fCurrentActiveBar) 281 return S_FALSE; 282 283 return IUnknown_HasFocusIO(fCurrentActiveBar->fTheBar); 284 } 285 286 HRESULT STDMETHODCALLTYPE CBaseBarSite::TranslateAcceleratorIO(LPMSG lpMsg) 287 { 288 if (!fCurrentActiveBar) 289 { 290 if (lpMsg) 291 { 292 TranslateMessage(lpMsg); 293 DispatchMessage(lpMsg); 294 } 295 return S_OK; 296 } 297 298 return IUnknown_TranslateAcceleratorIO(fCurrentActiveBar->fTheBar, lpMsg); 299 } 300 301 HRESULT STDMETHODCALLTYPE CBaseBarSite::QueryService(REFGUID guidService, REFIID riid, void **ppvObject) 302 { 303 CComPtr<IServiceProvider> serviceProvider; 304 HRESULT hResult; 305 306 if (fDeskBarSite == NULL) 307 return E_FAIL; 308 hResult = fDeskBarSite->QueryInterface(IID_PPV_ARG(IServiceProvider, &serviceProvider)); 309 if (FAILED_UNEXPECTEDLY(hResult)) 310 return hResult; 311 // called for SID_STopLevelBrowser, IID_IBrowserService to find top level browser 312 // called for SID_IWebBrowserApp, IID_IConnectionPointContainer 313 // connection point called for DIID_DWebBrowserEvents2 to establish connection 314 return serviceProvider->QueryService(guidService, riid, ppvObject); 315 } 316 317 HRESULT STDMETHODCALLTYPE CBaseBarSite::OnWinEvent( 318 HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT *theResult) 319 { 320 CComPtr<IDeskBar> deskBar; 321 CComPtr<IWinEventHandler> winEventHandler; 322 NMHDR *notifyHeader; 323 // RECT newBounds; 324 HRESULT hResult; 325 LRESULT result; 326 327 hResult = S_OK; 328 if (uMsg == WM_NOTIFY) 329 { 330 notifyHeader = (NMHDR *)lParam; 331 if (notifyHeader->hwndFrom == m_hWnd) 332 { 333 switch (notifyHeader->code) 334 { 335 case RBN_AUTOSIZE: 336 // For now, don't notify basebar we tried to resize ourselves, we don't 337 // get correct values at the moment. 338 #if 0 339 hResult = fDeskBarSite->QueryInterface(IID_PPV_ARG(IDeskBar, &deskBar)); 340 GetClientRect(&newBounds); 341 hResult = deskBar->OnPosRectChangeDB(&newBounds); 342 343 #endif 344 break; 345 case NM_CUSTOMDRAW: 346 result = OnCustomDraw((LPNMCUSTOMDRAW)lParam); 347 if (theResult) 348 *theResult = result; 349 return S_OK; 350 } 351 } 352 } 353 if (fCurrentActiveBar != NULL) 354 { 355 hResult = fCurrentActiveBar->fTheBar->QueryInterface( 356 IID_PPV_ARG(IWinEventHandler, &winEventHandler)); 357 if (SUCCEEDED(hResult) && winEventHandler.p != NULL) 358 hResult = winEventHandler->OnWinEvent(hWnd, uMsg, wParam, lParam, theResult); 359 } 360 return hResult; 361 } 362 363 HRESULT STDMETHODCALLTYPE CBaseBarSite::IsWindowOwner(HWND hWnd) 364 { 365 return E_NOTIMPL; 366 } 367 368 HRESULT STDMETHODCALLTYPE CBaseBarSite::OnFocusChangeIS (IUnknown *punkObj, BOOL fSetFocus) 369 { 370 // FIXME: should we directly pass-through, or advertise ourselves as focus owner ? 371 return IUnknown_OnFocusChangeIS(fDeskBarSite, punkObj, fSetFocus); 372 } 373 374 HRESULT STDMETHODCALLTYPE CBaseBarSite::SetDeskBarSite(IUnknown *punkSite) 375 { 376 CComPtr<IOleWindow> oleWindow; 377 HWND ownerWindow; 378 HRESULT hResult; 379 DWORD dwBandID; 380 381 if (punkSite == NULL) 382 { 383 384 TRACE("Destroying site \n"); 385 /* Cleanup our bands */ 386 while(SUCCEEDED(EnumBands(-1, &dwBandID)) && dwBandID) 387 { 388 hResult = EnumBands(0, &dwBandID); 389 if(FAILED_UNEXPECTEDLY(hResult)) 390 continue; 391 RemoveBand(dwBandID); 392 } 393 fDeskBarSite = NULL; 394 } 395 else 396 { 397 TBBUTTON closeBtn; 398 HBITMAP hBmp; 399 400 hResult = punkSite->QueryInterface(IID_PPV_ARG(IOleWindow, &oleWindow)); 401 if (FAILED_UNEXPECTEDLY(hResult)) 402 return hResult; 403 hResult = punkSite->QueryInterface(IID_PPV_ARG(IUnknown, &fDeskBarSite)); 404 if (FAILED_UNEXPECTEDLY(hResult)) 405 return hResult; 406 hResult = oleWindow->GetWindow(&ownerWindow); 407 if (FAILED_UNEXPECTEDLY(hResult)) 408 return hResult; 409 410 DWORD dwStyle = WS_VISIBLE | WS_CHILD | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_BORDER | 411 RBS_VARHEIGHT | RBS_REGISTERDROP | RBS_AUTOSIZE | RBS_VERTICALGRIPPER | RBS_DBLCLKTOGGLE | 412 CCS_NODIVIDER | CCS_NOPARENTALIGN | CCS_NORESIZE; 413 if (fVertical) 414 dwStyle |= CCS_VERT; 415 416 /* Create site window */ 417 HWND tmp = CreateWindowW(REBARCLASSNAMEW, NULL, dwStyle, 0, 0, 0, 0, ownerWindow, NULL, 418 _AtlBaseModule.GetModuleInstance(), NULL); 419 420 /* Give window management to ATL */ 421 SubclassWindow(tmp); 422 423 SendMessage(RB_SETTEXTCOLOR, 0, CLR_DEFAULT); 424 SendMessage(RB_SETBKCOLOR, 0, CLR_DEFAULT); 425 426 /* Create close toolbar and imagelist */ 427 toolbarWnd = CreateWindowW(TOOLBARCLASSNAMEW, NULL, 428 WS_VISIBLE | WS_CHILD | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | 429 TBSTYLE_FLAT | TBSTYLE_TRANSPARENT | TBSTYLE_TOOLTIPS | 430 CCS_NOMOVEY | CCS_NORESIZE | CCS_NOPARENTALIGN | CCS_NODIVIDER 431 , 0, 0, 0, 0, m_hWnd, NULL, _AtlBaseModule.GetModuleInstance(), NULL); 432 433 toolImageList = ImageList_Create(13, 11, ILC_COLOR24 | ILC_MASK, 3, 0); 434 435 hBmp = (HBITMAP)LoadImage(_AtlBaseModule.GetModuleInstance(), 436 MAKEINTRESOURCE(IDB_BANDBUTTONS), IMAGE_BITMAP, 0, 0, 437 LR_LOADTRANSPARENT); 438 439 ImageList_AddMasked(toolImageList, hBmp, RGB(192, 192, 192)); 440 DeleteObject(hBmp); 441 442 SendMessage(toolbarWnd, TB_SETIMAGELIST, 0, (LPARAM)toolImageList); 443 444 /* Add button to toolbar */ 445 closeBtn.iBitmap = MAKELONG(1, 0); 446 closeBtn.idCommand = IDM_BASEBAR_CLOSE; 447 closeBtn.fsState = TBSTATE_ENABLED; 448 closeBtn.fsStyle = BTNS_BUTTON; 449 ZeroMemory(closeBtn.bReserved, sizeof(closeBtn.bReserved)); 450 closeBtn.dwData = 0; 451 closeBtn.iString = (INT_PTR)L"Close"; 452 453 SendMessage(toolbarWnd, TB_INSERTBUTTON, 0, (LPARAM)&closeBtn); 454 SendMessage(toolbarWnd, TB_SETMAXTEXTROWS, 0, 0); 455 //SendMessage(toolbarWnd, TB_AUTOSIZE, 0, 0); 456 } 457 return S_OK; 458 } 459 460 HRESULT STDMETHODCALLTYPE CBaseBarSite::SetModeDBC(DWORD dwMode) 461 { 462 return E_NOTIMPL; 463 } 464 465 HRESULT STDMETHODCALLTYPE CBaseBarSite::UIActivateDBC(DWORD dwState) 466 { 467 return E_NOTIMPL; 468 } 469 470 HRESULT STDMETHODCALLTYPE CBaseBarSite::GetSize(DWORD dwWhich, LPRECT prc) 471 { 472 return E_NOTIMPL; 473 } 474 475 HRESULT STDMETHODCALLTYPE CBaseBarSite::QueryStatus(const GUID *pguidCmdGroup, 476 ULONG cCmds, OLECMD prgCmds[ ], OLECMDTEXT *pCmdText) 477 { 478 return E_NOTIMPL; 479 } 480 481 HRESULT STDMETHODCALLTYPE CBaseBarSite::Exec(const GUID *pguidCmdGroup, DWORD nCmdID, 482 DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut) 483 { 484 if (IsEqualIID(*pguidCmdGroup, IID_IDeskBand)) 485 { 486 switch (nCmdID) 487 { 488 case 0: 489 //update band info ? 490 case 1: // insert a new band 491 if (V_VT(pvaIn) != VT_UNKNOWN) 492 return E_INVALIDARG; 493 return InsertBar(V_UNKNOWN(pvaIn)); 494 case 0x17: 495 // redim band 496 break; 497 } 498 } 499 return E_FAIL; 500 } 501 502 HRESULT CBaseBarSite::GetInternalBandInfo(UINT uBand, REBARBANDINFO *pBandInfo) 503 { 504 if (!pBandInfo) 505 return E_INVALIDARG; 506 memset(pBandInfo, 0, sizeof(REBARBANDINFO)); 507 pBandInfo->cbSize = sizeof(REBARBANDINFO); 508 pBandInfo->fMask = RBBIM_LPARAM | RBBIM_ID; 509 510 // Grab our bandinfo from rebar control 511 if (!SendMessage(RB_GETBANDINFO, uBand, reinterpret_cast<LPARAM>(pBandInfo))) 512 return E_INVALIDARG; 513 return S_OK; 514 } 515 516 HRESULT CBaseBarSite::GetInternalBandInfo(UINT uBand, REBARBANDINFO *pBandInfo, DWORD fMask) 517 { 518 if (!pBandInfo) 519 return E_INVALIDARG; 520 pBandInfo->cbSize = sizeof(REBARBANDINFO); 521 pBandInfo->fMask = fMask; 522 523 // Grab our bandinfo from rebar control 524 if (!SendMessage(RB_GETBANDINFO, uBand, reinterpret_cast<LPARAM>(pBandInfo))) 525 return E_INVALIDARG; 526 return S_OK; 527 } 528 529 HRESULT STDMETHODCALLTYPE CBaseBarSite::AddBand(IUnknown *punk) 530 { 531 return InsertBar(punk); 532 } 533 534 HRESULT STDMETHODCALLTYPE CBaseBarSite::EnumBands(UINT uBand, DWORD *pdwBandID) 535 { 536 REBARBANDINFO bandInfo; 537 538 if (pdwBandID == NULL) 539 return E_INVALIDARG; 540 if (uBand == 0xffffffff) 541 { 542 *pdwBandID = (DWORD)SendMessage(RB_GETBANDCOUNT, 0, 0); 543 return S_OK; 544 } 545 if (!SUCCEEDED(GetInternalBandInfo(uBand, &bandInfo))) 546 return E_INVALIDARG; 547 *pdwBandID = bandInfo.wID; 548 return S_OK; 549 } 550 551 HRESULT STDMETHODCALLTYPE CBaseBarSite::QueryBand(DWORD dwBandID, IDeskBand **ppstb, 552 DWORD *pdwState, LPWSTR pszName, int cchName) 553 { 554 return E_NOTIMPL; 555 } 556 557 HRESULT STDMETHODCALLTYPE CBaseBarSite::SetBandState(DWORD dwBandID, DWORD dwMask, DWORD dwState) 558 { 559 return E_NOTIMPL; 560 } 561 562 HRESULT STDMETHODCALLTYPE CBaseBarSite::RemoveBand(DWORD dwBandID) 563 { 564 REBARBANDINFO bandInfo; 565 HRESULT hr; 566 CBarInfo *pInfo; 567 CComPtr<IObjectWithSite> pSite; 568 CComPtr<IDeskBand> pDockWnd; 569 DWORD index; 570 571 // Retrieve the right index of the coolbar knowing the id 572 index = SendMessage(RB_IDTOINDEX, dwBandID, 0); 573 if (index == 0xffffffff) 574 return E_INVALIDARG; 575 576 if (FAILED_UNEXPECTEDLY(GetInternalBandInfo(index, &bandInfo))) 577 return E_INVALIDARG; 578 579 pInfo = reinterpret_cast<CBarInfo*>(bandInfo.lParam); 580 if (!pInfo) 581 return E_INVALIDARG; 582 583 hr = pInfo->fTheBar->QueryInterface(IID_PPV_ARG(IDeskBand, &pDockWnd)); 584 if (FAILED_UNEXPECTEDLY(hr)) 585 { 586 return E_NOINTERFACE; 587 } 588 hr = pInfo->fTheBar->QueryInterface(IID_PPV_ARG(IObjectWithSite, &pSite)); 589 if (FAILED_UNEXPECTEDLY(hr)) 590 { 591 return E_NOINTERFACE; 592 } 593 /* Windows sends a CloseDW before setting site to NULL */ 594 pDockWnd->CloseDW(0); 595 pSite->SetSite(NULL); 596 597 // Delete the band from rebar 598 if (!SendMessage(RB_DELETEBAND, index, 0)) 599 { 600 ERR("Can't delete the band\n"); 601 return E_INVALIDARG; 602 } 603 if (pInfo == fCurrentActiveBar) 604 { 605 // FIXME: what to do when we are deleting active bar ? Let's assume we remove it for now 606 fCurrentActiveBar = NULL; 607 } 608 delete pInfo; 609 return S_OK; 610 } 611 612 HRESULT STDMETHODCALLTYPE CBaseBarSite::GetBandObject(DWORD dwBandID, REFIID riid, void **ppv) 613 { 614 REBARBANDINFO bandInfo; 615 HRESULT hr; 616 CBarInfo *pInfo; 617 DWORD index; 618 619 if (ppv == NULL) 620 return E_POINTER; 621 622 // Retrieve the right index of the coolbar knowing the id 623 index = SendMessage(RB_IDTOINDEX, dwBandID, 0); 624 if (index == 0xffffffff) 625 return E_INVALIDARG; 626 627 if (FAILED_UNEXPECTEDLY(GetInternalBandInfo(index, &bandInfo))) 628 return E_INVALIDARG; 629 630 pInfo = reinterpret_cast<CBarInfo*>(bandInfo.lParam); 631 hr = pInfo->fTheBar->QueryInterface(riid, ppv); 632 if (!SUCCEEDED(hr)) 633 return E_NOINTERFACE; 634 return S_OK; 635 } 636 637 HRESULT STDMETHODCALLTYPE CBaseBarSite::SetBandSiteInfo(const BANDSITEINFO *pbsinfo) 638 { 639 if (pbsinfo == NULL) 640 return E_POINTER; 641 return E_NOTIMPL; 642 } 643 644 HRESULT STDMETHODCALLTYPE CBaseBarSite::GetBandSiteInfo(BANDSITEINFO *pbsinfo) 645 { 646 if (pbsinfo == NULL) 647 return E_POINTER; 648 return E_NOTIMPL; 649 } 650 651 HRESULT STDMETHODCALLTYPE CBaseBarSite::GetClassID(CLSID *pClassID) 652 { 653 if (pClassID == NULL) 654 return E_POINTER; 655 // TODO: what class to return here? 656 return E_NOTIMPL; 657 } 658 659 HRESULT STDMETHODCALLTYPE CBaseBarSite::IsDirty() 660 { 661 return E_NOTIMPL; 662 } 663 664 HRESULT STDMETHODCALLTYPE CBaseBarSite::Load(IStream *pStm) 665 { 666 return E_NOTIMPL; 667 } 668 669 HRESULT STDMETHODCALLTYPE CBaseBarSite::Save(IStream *pStm, BOOL fClearDirty) 670 { 671 return E_NOTIMPL; 672 } 673 674 HRESULT STDMETHODCALLTYPE CBaseBarSite::GetSizeMax(ULARGE_INTEGER *pcbSize) 675 { 676 if (pcbSize == NULL) 677 return E_POINTER; 678 return E_NOTIMPL; 679 } 680 681 LRESULT CBaseBarSite::OnNotify(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled) 682 { 683 NMHDR *notifyHeader; 684 685 notifyHeader = reinterpret_cast<NMHDR *>(lParam); 686 if (notifyHeader->hwndFrom == m_hWnd) 687 { 688 } 689 bHandled = FALSE; /* forward notification to parent */ 690 return 0; 691 } 692 693 LRESULT CBaseBarSite::OnCommand(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled) 694 { 695 if (HIWORD(wParam) == BN_CLICKED && LOWORD(wParam) == IDM_BASEBAR_CLOSE) 696 { 697 /* Tell the base bar to hide */ 698 IUnknown_Exec(fDeskBarSite, IID_IDeskBarClient, 0, 0, NULL, NULL); 699 bHandled = TRUE; 700 } 701 return 0; 702 } 703 704 LRESULT CBaseBarSite::OnCustomDraw(LPNMCUSTOMDRAW pnmcd) 705 { 706 switch (pnmcd->dwDrawStage) 707 { 708 case CDDS_PREPAINT: 709 case CDDS_PREERASE: 710 return CDRF_NOTIFYITEMDRAW; 711 case CDDS_ITEMPREPAINT: 712 if (fVertical) 713 { 714 REBARBANDINFO info; 715 WCHAR wszTitle[MAX_PATH]; 716 DWORD index; 717 RECT rt; 718 HFONT newFont, oldFont; 719 720 index = SendMessage(RB_IDTOINDEX, fCurrentActiveBar->fBandID , 0); 721 ZeroMemory(&info, sizeof(info)); 722 ZeroMemory(wszTitle, sizeof(wszTitle)); 723 DrawEdge(pnmcd->hdc, &pnmcd->rc, EDGE_ETCHED, BF_BOTTOM); 724 // We also resize our close button 725 ::SetWindowPos(toolbarWnd, HWND_TOP, pnmcd->rc.right - 22, 0, 20, 18, SWP_SHOWWINDOW); 726 // Draw the text 727 info.cch = MAX_PATH; 728 info.lpText = wszTitle; 729 rt = pnmcd->rc; 730 rt.right -= 24; 731 rt.left += 2; 732 rt.bottom -= 1; 733 if (FAILED_UNEXPECTEDLY(GetInternalBandInfo(index, &info, RBBIM_TEXT))) 734 return CDRF_SKIPDEFAULT; 735 newFont = GetTitleFont(); 736 if (newFont) 737 oldFont = (HFONT)SelectObject(pnmcd->hdc, newFont); 738 DrawText(pnmcd->hdc, info.lpText, -1, &rt, DT_SINGLELINE | DT_LEFT | DT_VCENTER); 739 SelectObject(pnmcd->hdc, oldFont); 740 DeleteObject(newFont); 741 return CDRF_SKIPDEFAULT; 742 } 743 else 744 { 745 DrawEdge(pnmcd->hdc, &pnmcd->rc, EDGE_ETCHED, BF_BOTTOM); 746 // We also resize our close button 747 ::SetWindowPos(toolbarWnd, HWND_TOP, 0, 2, 20, 18, SWP_SHOWWINDOW); 748 } 749 return CDRF_SKIPDEFAULT; 750 default: 751 break; 752 } 753 return CDRF_DODEFAULT; 754 } 755 756 HFONT CBaseBarSite::GetTitleFont() 757 { 758 NONCLIENTMETRICS mt; 759 mt.cbSize = sizeof(mt); 760 if (!SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(mt), &mt, 0)) 761 { 762 ERR("Can't get system parameters !\n"); 763 return NULL; 764 } 765 return CreateFontIndirect(&mt.lfMenuFont); 766 767 } 768 769 HRESULT CBaseBarSite::FindBandByGUID(REFGUID pGuid, DWORD *pdwBandID) 770 { 771 DWORD numBands; 772 DWORD i; 773 HRESULT hr; 774 REBARBANDINFO bandInfo; 775 CBarInfo *realInfo; 776 777 hr = EnumBands(-1, &numBands); 778 if (FAILED_UNEXPECTEDLY(hr)) 779 return E_FAIL; 780 781 for(i = 0; i < numBands; i++) 782 { 783 if (FAILED_UNEXPECTEDLY(GetInternalBandInfo(i, &bandInfo))) 784 return E_FAIL; 785 realInfo = (CBarInfo*)bandInfo.lParam; 786 if (IsEqualGUID(pGuid, realInfo->fBarClass)) 787 { 788 *pdwBandID = realInfo->fBandID; 789 return S_OK; 790 } 791 } 792 return S_FALSE; 793 } 794 795 HRESULT CBaseBarSite::ShowBand(DWORD dwBandID) 796 { 797 UINT index; 798 CComPtr<IDeskBand> dockingWindow; 799 HRESULT hResult; 800 REBARBANDINFO bandInfo; 801 802 // show our band 803 hResult = GetBandObject(dwBandID, IID_PPV_ARG(IDeskBand, &dockingWindow)); 804 if (FAILED_UNEXPECTEDLY(hResult)) 805 return E_FAIL; 806 807 hResult = dockingWindow->ShowDW(TRUE); 808 809 // Hide old band while adding new one 810 if (fCurrentActiveBar && fCurrentActiveBar->fBandID != dwBandID) 811 { 812 DWORD index; 813 index = SendMessage(RB_IDTOINDEX, fCurrentActiveBar->fBandID, 0); 814 if (index != 0xffffffff) 815 SendMessage(RB_SHOWBAND, index, 0); 816 } 817 if (FAILED_UNEXPECTEDLY(hResult)) 818 return hResult; 819 820 // Display the current band 821 index = SendMessage(RB_IDTOINDEX, dwBandID, 0); 822 if (index != 0xffffffff) 823 SendMessage(RB_SHOWBAND, index, 1); 824 if (FAILED_UNEXPECTEDLY(GetInternalBandInfo(index, &bandInfo))) 825 return E_FAIL; 826 fCurrentActiveBar = (CBarInfo*)bandInfo.lParam; 827 return S_OK; 828 } 829 830 HRESULT CBaseBarSite_CreateInstance(REFIID riid, void **ppv, BOOL bVertical) 831 { 832 return ShellObjectCreatorInit<CBaseBarSite, BOOL>(bVertical, riid, ppv); 833 } 834