1 /* 2 * Rebar band site 3 * 4 * Copyright 2007 Herv� Poussineau 5 * Copyright 2009 Andrew Hill 6 * 7 * This library is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU Lesser General Public 9 * License as published by the Free Software Foundation; either 10 * version 2.1 of the License, or (at your option) any later version. 11 * 12 * This library is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 * Lesser General Public License for more details. 16 * 17 * You should have received a copy of the GNU Lesser General Public 18 * License along with this library; if not, write to the Free Software 19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 20 */ 21 22 #include "shellbars.h" 23 24 #ifndef ASSERT 25 #define ASSERT(cond) \ 26 if (!(cond)) \ 27 ERR ("ASSERTION %s AT %s:%d FAILED!\n", #cond, __FILE__, __LINE__) 28 #endif 29 30 31 /* 32 TODO: 33 ** Fix tasks band gripper not appearing when quick launch is added 34 ** Fix hiding grippers in locked mode 35 ** The context menu should include the menu of both the site and the band 36 ** The chevron should be shown only when needed 37 */ 38 39 CBandSiteBase::CBandSiteBase(): 40 m_cBands(0), 41 m_cBandsAllocated(0), 42 m_bands(NULL), 43 m_hwndRebar(NULL), 44 m_dwState(0), 45 m_dwStyle(0) 46 { 47 } 48 49 UINT CBandSiteBase::_GetBandID(struct BandObject *Band) 50 { 51 return (UINT)(Band - m_bands); 52 } 53 54 struct CBandSiteBase::BandObject *CBandSiteBase::_GetBandByID(DWORD dwBandID) 55 { 56 if ((LONG)dwBandID >= m_cBandsAllocated) 57 return NULL; 58 59 if (m_bands[dwBandID].DeskBand == NULL) 60 return NULL; 61 62 return &m_bands[dwBandID]; 63 } 64 65 void CBandSiteBase::_FreeBand(struct BandObject *Band) 66 { 67 ATLASSERT(Band->DeskBand != NULL); 68 ATLASSERT(Band->OleWindow != NULL); 69 ATLASSERT(Band->WndEvtHandler != NULL); 70 Band->DeskBand->Release(); 71 Band->OleWindow->Release(); 72 Band->WndEvtHandler->Release(); 73 memset(Band, 0, sizeof(*Band)); 74 m_cBands--; 75 } 76 77 DWORD CBandSiteBase::_GetViewMode() 78 { 79 DWORD dwStyle; 80 81 /* FIXME: What about DBIF_VIEWMODE_FLOATING and DBIF_VIEWMODE_TRANSPARENT? */ 82 dwStyle = GetWindowLongPtr(m_hwndRebar, GWL_STYLE); 83 84 if (dwStyle & CCS_VERT) 85 return DBIF_VIEWMODE_VERTICAL; 86 else 87 return DBIF_VIEWMODE_NORMAL; 88 } 89 90 VOID CBandSiteBase::_BuildBandInfo(struct BandObject *Band, REBARBANDINFOW *prbi) 91 { 92 ZeroMemory(prbi, sizeof(*prbi)); 93 prbi->cbSize = sizeof(*prbi); 94 95 prbi->fMask = RBBIM_ID; 96 prbi->wID = _GetBandID(Band); 97 98 if (Band->dbi.dwMask & DBIM_MINSIZE) 99 { 100 prbi->fMask |= RBBIM_CHILDSIZE; 101 prbi->cxMinChild = Band->dbi.ptMinSize.x; 102 prbi->cyMinChild = Band->dbi.ptMinSize.y; 103 } 104 105 if (Band->dbi.dwMask & DBIM_MAXSIZE) 106 { 107 prbi->fMask |= RBBIM_CHILDSIZE; 108 prbi->cyMaxChild = Band->dbi.ptMaxSize.y; 109 } 110 111 if ((Band->dbi.dwMask & (DBIM_INTEGRAL | DBIM_MODEFLAGS)) == (DBIM_INTEGRAL | DBIM_MODEFLAGS) && 112 (Band->dbi.dwModeFlags & DBIMF_VARIABLEHEIGHT)) 113 { 114 prbi->fMask |= RBBIM_CHILDSIZE; 115 prbi->cyIntegral = Band->dbi.ptIntegral.y; 116 } 117 118 if (Band->dbi.dwMask & DBIM_ACTUAL) 119 { 120 prbi->fMask |= RBBIM_IDEALSIZE | RBBIM_SIZE | RBBIM_CHILDSIZE; 121 prbi->cxIdeal = Band->dbi.ptActual.x; 122 prbi->cx = Band->dbi.ptActual.x; 123 prbi->cyChild = Band->dbi.ptActual.y; 124 } 125 126 if (Band->dbi.dwMask & DBIM_TITLE) 127 { 128 prbi->fMask |= RBBIM_TEXT; 129 prbi->lpText = Band->dbi.wszTitle; 130 prbi->cch = wcslen(Band->dbi.wszTitle); 131 } 132 133 if (Band->dbi.dwMask & DBIM_MODEFLAGS) 134 { 135 prbi->fMask |= RBBIM_STYLE; 136 137 if (Band->dbi.dwModeFlags & DBIMF_FIXED) 138 prbi->fStyle |= RBBS_FIXEDSIZE | RBBS_NOGRIPPER; 139 if (Band->dbi.dwModeFlags & DBIMF_FIXEDBMP) 140 prbi->fStyle |= RBBS_FIXEDBMP; 141 if (Band->dbi.dwModeFlags & DBIMF_VARIABLEHEIGHT) 142 prbi->fStyle |= RBBS_VARIABLEHEIGHT; 143 if (Band->dbi.dwModeFlags & DBIMF_DEBOSSED) 144 prbi->fStyle |= RBBS_CHILDEDGE; 145 if (Band->dbi.dwModeFlags & DBIMF_USECHEVRON) 146 prbi->fStyle |= RBBS_USECHEVRON; 147 if (Band->dbi.dwModeFlags & DBIMF_BREAK) 148 prbi->fStyle |= RBBS_BREAK; 149 if (Band->dbi.dwModeFlags & DBIMF_TOPALIGN) 150 prbi->fStyle |= RBBS_TOPALIGN; 151 if ((Band->dbi.dwModeFlags & DBIMF_NOGRIPPER) || (m_dwStyle & BSIS_NOGRIPPER)) 152 prbi->fStyle |= RBBS_NOGRIPPER; 153 if ((Band->dbi.dwModeFlags & DBIMF_ALWAYSGRIPPER) || (m_dwStyle & BSIS_ALWAYSGRIPPER)) 154 prbi->fStyle |= RBBS_GRIPPERALWAYS; 155 } 156 157 if (Band->bHiddenTitle || (m_dwStyle & BSIS_NOCAPTION)) 158 { 159 prbi->fMask |= RBBIM_STYLE; 160 prbi->fStyle |= RBBS_HIDETITLE; 161 } 162 163 if ((Band->dbi.dwMask & (DBIM_BKCOLOR | DBIM_MODEFLAGS)) == (DBIM_BKCOLOR | DBIM_MODEFLAGS) && 164 (Band->dbi.dwModeFlags & DBIMF_BKCOLOR)) 165 { 166 prbi->fMask |= RBBIM_COLORS; 167 prbi->clrFore = (COLORREF)(COLOR_WINDOWTEXT + 1); 168 prbi->clrBack = Band->dbi.crBkgnd; 169 } 170 } 171 172 HRESULT CBandSiteBase::_UpdateBand(struct BandObject *Band) 173 { 174 REBARBANDINFOW rbi; 175 DWORD dwViewMode; 176 UINT uBand; 177 HRESULT hRet; 178 179 ZeroMemory(&Band->dbi, sizeof(Band->dbi)); 180 Band->dbi.dwMask = DBIM_MINSIZE | DBIM_MAXSIZE | DBIM_INTEGRAL | 181 DBIM_ACTUAL | DBIM_TITLE | DBIM_MODEFLAGS | DBIM_BKCOLOR; 182 183 dwViewMode = _GetViewMode(); 184 185 hRet = Band->DeskBand->GetBandInfo((DWORD)_GetBandID(Band), dwViewMode, &Band->dbi); 186 if (SUCCEEDED(hRet)) 187 { 188 _BuildBandInfo(Band, &rbi); 189 if (SUCCEEDED(Band->OleWindow->GetWindow(&rbi.hwndChild)) && 190 rbi.hwndChild != NULL) 191 { 192 rbi.fMask |= RBBIM_CHILD; 193 WARN ("ReBar band uses child window 0x%p\n", rbi.hwndChild); 194 } 195 196 uBand = (UINT)SendMessageW(m_hwndRebar, RB_IDTOINDEX, (WPARAM)rbi.wID, 0); 197 if (uBand != (UINT)-1) 198 { 199 if (!SendMessageW(m_hwndRebar, RB_SETBANDINFOW, (WPARAM)uBand, reinterpret_cast<LPARAM>(&rbi))) 200 { 201 WARN("Failed to update the rebar band!\n"); 202 } 203 } 204 else 205 WARN("Failed to map rebar band id to index!\n"); 206 207 } 208 209 return hRet; 210 } 211 212 HRESULT CBandSiteBase::_UpdateAllBands() 213 { 214 LONG i; 215 HRESULT hRet; 216 217 for (i = 0; i < m_cBandsAllocated; i++) 218 { 219 if (m_bands[i].DeskBand != NULL) 220 { 221 hRet = _UpdateBand(&m_bands[i]); 222 if (FAILED_UNEXPECTEDLY(hRet)) 223 return hRet; 224 } 225 } 226 227 return S_OK; 228 } 229 230 HRESULT CBandSiteBase::_UpdateBand(DWORD dwBandID) 231 { 232 struct BandObject *Band; 233 234 Band = _GetBandByID(dwBandID); 235 if (Band == NULL) 236 return E_FAIL; 237 238 return _UpdateBand(Band); 239 } 240 241 HRESULT CBandSiteBase::_IsBandDeletable(DWORD dwBandID) 242 { 243 CComPtr<IBandSite> pbs; 244 245 /* Use QueryInterface so that we get the outer object in case we have one */ 246 HRESULT hr = this->QueryInterface(IID_PPV_ARG(IBandSite, &pbs)); 247 if (FAILED_UNEXPECTEDLY(hr)) 248 return hr; 249 250 DWORD dwState; 251 hr = pbs->QueryBand(dwBandID, NULL, &dwState, NULL, NULL); 252 if (FAILED_UNEXPECTEDLY(hr)) 253 return hr; 254 255 return ((dwState & BSSF_UNDELETEABLE) != 0) ? S_FALSE : S_OK; 256 } 257 258 HRESULT CBandSiteBase::_OnContextMenu(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT *plrResult) 259 { 260 /* Find the index fo the band that was clicked */ 261 int x = GET_X_LPARAM(lParam); 262 int y = GET_Y_LPARAM(lParam); 263 264 RBHITTESTINFO htInfo = {{x, y}}; 265 ScreenToClient(m_hwndRebar, &htInfo.pt); 266 int iBand = SendMessageW(m_hwndRebar, RB_HITTEST, 0, (LPARAM)&htInfo); 267 if (iBand < 0) 268 { 269 /* FIXME: what to do here? */ 270 return S_OK; 271 } 272 273 /* Now get the id of the band that was clicked */ 274 REBARBANDINFOW bandInfo = {sizeof(bandInfo), RBBIM_ID}; 275 SendMessageW(m_hwndRebar, RB_GETBANDINFOW, htInfo.iBand, (LPARAM)&bandInfo); 276 277 /* Finally get the band */ 278 DWORD dwBandID = bandInfo.wID; 279 struct BandObject *Band = _GetBandByID(dwBandID); 280 if (Band == NULL) 281 return E_FAIL; 282 283 HMENU hMenu = CreatePopupMenu(); 284 if (hMenu == NULL) 285 return E_OUTOFMEMORY; 286 287 /* Try to load the menu of the band */ 288 UINT idBandLast = 0; 289 CComPtr<IContextMenu> pcm; 290 HRESULT hr = Band->DeskBand->QueryInterface(IID_PPV_ARG(IContextMenu, &pcm)); 291 if (SUCCEEDED(hr)) 292 { 293 hr = pcm->QueryContextMenu(hMenu, 0, 0, UINT_MAX, CMF_NORMAL); 294 if (SUCCEEDED(hr)) 295 { 296 idBandLast = HRESULT_CODE(hr); 297 } 298 } 299 300 if (!(m_dwStyle & BSIS_LOCKED)) 301 { 302 /* Load the static part of the menu */ 303 HMENU hMenuStatic = LoadMenuW(GetModuleHandleW(L"browseui.dll"), MAKEINTRESOURCEW(IDM_BAND_MENU)); 304 305 if (hMenuStatic) 306 { 307 Shell_MergeMenus(hMenu, hMenuStatic, UINT_MAX, 0, UINT_MAX, MM_DONTREMOVESEPS | MM_SUBMENUSHAVEIDS); 308 309 ::DestroyMenu(hMenuStatic); 310 311 hr = _IsBandDeletable(dwBandID); 312 if (FAILED_UNEXPECTEDLY(hr)) 313 return hr; 314 315 /* Remove the close item if it is not deletable */ 316 if (hr == S_FALSE || (Band->dbi.dwModeFlags & DBIMF_UNDELETEABLE) != 0) 317 DeleteMenu(hMenu, IDM_BAND_CLOSE, MF_BYCOMMAND); 318 319 if ((Band->dbi.dwMask & DBIM_TITLE) == 0) 320 DeleteMenu(hMenu, IDM_BAND_TITLE, MF_BYCOMMAND); 321 else 322 CheckMenuItem(hMenu, IDM_BAND_TITLE, Band->bHiddenTitle ? MF_UNCHECKED : MF_CHECKED); 323 } 324 } 325 326 /* TODO: Query the menu of our site */ 327 328 UINT uCommand = ::TrackPopupMenuEx(hMenu, TPM_RETURNCMD, x, y, m_hwndRebar, NULL); 329 if (uCommand < idBandLast) 330 { 331 CMINVOKECOMMANDINFO cmi = { sizeof(cmi), 0, m_hwndRebar, MAKEINTRESOURCEA(uCommand)}; 332 hr = pcm->InvokeCommand(&cmi); 333 if (FAILED_UNEXPECTEDLY(hr)) 334 return hr; 335 } 336 else 337 { 338 if (uCommand == IDM_BAND_TITLE) 339 { 340 Band->bHiddenTitle = !Band->bHiddenTitle; 341 342 hr = _UpdateBand(dwBandID); 343 if (FAILED_UNEXPECTEDLY(hr)) 344 return hr; 345 } 346 else if(uCommand == IDM_BAND_CLOSE) 347 { 348 hr = RemoveBand(dwBandID); 349 if (FAILED_UNEXPECTEDLY(hr)) 350 return hr; 351 } 352 } 353 354 return S_OK; 355 } 356 357 struct CBandSiteBase::BandObject *CBandSiteBase::_GetBandFromHwnd(HWND hwnd) 358 { 359 HRESULT hRet; 360 HWND hWndBand; 361 LONG i; 362 363 for (i = 0; i < m_cBandsAllocated; i++) 364 { 365 if (m_bands[i].DeskBand != NULL) 366 { 367 ASSERT(m_bands[i].OleWindow); 368 369 hWndBand = NULL; 370 hRet = m_bands[i].OleWindow->GetWindow(&hWndBand); 371 if (SUCCEEDED(hRet) && hWndBand == hwnd) 372 return &m_bands[i]; 373 } 374 } 375 376 return NULL; 377 } 378 379 CBandSiteBase::~CBandSiteBase() 380 { 381 382 TRACE("destroying %p\n", this); 383 384 if (m_hwndRebar != NULL) 385 { 386 DestroyWindow(m_hwndRebar); 387 m_hwndRebar = NULL; 388 } 389 390 if (m_bands != NULL) 391 { 392 for (INT i = 0; i < m_cBandsAllocated; i++) 393 { 394 if (m_bands[i].DeskBand != NULL) 395 _FreeBand(&m_bands[i]); 396 } 397 CoTaskMemFree(m_bands); 398 m_bands = NULL; 399 } 400 } 401 402 HRESULT STDMETHODCALLTYPE CBandSiteBase::AddBand(IUnknown *punk) 403 { 404 LONG NewAllocated; 405 struct BandObject *NewBand = NULL; 406 CComPtr<IDeskBand> DeskBand; 407 CComPtr<IObjectWithSite> ObjWithSite; 408 CComPtr<IOleWindow> OleWindow; 409 CComPtr<IWinEventHandler> WndEvtHandler; 410 REBARBANDINFOW rbi; 411 HRESULT hRet; 412 UINT uBand; 413 414 TRACE("(%p, %p)\n", this, punk); 415 416 if (punk == NULL || m_hwndRebar == NULL) 417 return E_FAIL; 418 419 hRet = punk->QueryInterface(IID_PPV_ARG(IDeskBand, &DeskBand)); 420 if (FAILED_UNEXPECTEDLY(hRet)) 421 return hRet; 422 423 hRet = punk->QueryInterface(IID_PPV_ARG(IObjectWithSite, &ObjWithSite)); 424 if (FAILED_UNEXPECTEDLY(hRet)) 425 return hRet; 426 427 hRet = punk->QueryInterface(IID_PPV_ARG(IOleWindow, &OleWindow)); 428 if (FAILED_UNEXPECTEDLY(hRet)) 429 return hRet; 430 431 hRet = punk->QueryInterface(IID_PPV_ARG(IWinEventHandler, &WndEvtHandler)); 432 if (FAILED_UNEXPECTEDLY(hRet)) 433 return hRet; 434 435 if (m_cBandsAllocated > m_cBands) 436 { 437 /* Search for a free band object */ 438 for (INT i = 0; i < m_cBandsAllocated; i++) 439 { 440 if (m_bands[i].DeskBand == NULL) 441 { 442 NewBand = &m_bands[i]; 443 break; 444 } 445 } 446 } 447 else if (m_cBandsAllocated > 0) 448 { 449 ASSERT (m_bands != NULL); 450 451 /* Reallocate the band object array */ 452 NewAllocated = m_cBandsAllocated + 8; 453 if (NewAllocated > 0xFFFF) 454 NewAllocated = 0xFFFF; 455 if (NewAllocated == m_cBandsAllocated) 456 { 457 return E_OUTOFMEMORY; 458 } 459 460 461 NewBand = static_cast<struct BandObject *>(CoTaskMemAlloc(NewAllocated * sizeof(struct BandObject))); 462 if (NewBand == NULL) 463 { 464 return E_OUTOFMEMORY; 465 } 466 467 /* Copy the old array */ 468 memcpy(NewBand, m_bands, m_cBandsAllocated * sizeof(struct BandObject)); 469 470 /* Initialize the added bands */ 471 memset(&NewBand[m_cBandsAllocated], 0, (NewAllocated - m_cBandsAllocated) * sizeof(struct BandObject)); 472 473 m_cBandsAllocated = NewAllocated; 474 CoTaskMemFree(m_bands); 475 m_bands = NewBand; 476 } 477 else 478 { 479 ASSERT(m_bands == NULL); 480 ASSERT(m_cBandsAllocated == 0); 481 ASSERT(m_cBands == 0); 482 483 /* Allocate new array */ 484 m_bands = static_cast<struct BandObject *>(CoTaskMemAlloc(8 * sizeof(struct BandObject))); 485 if (m_bands == NULL) 486 { 487 return E_OUTOFMEMORY; 488 } 489 490 /* Initialize the added bands */ 491 memset(m_bands, 0, 8 * sizeof(struct BandObject)); 492 493 m_cBandsAllocated += 8; 494 NewBand = &m_bands[0]; 495 } 496 497 ASSERT(NewBand != NULL); 498 499 m_cBands++; 500 NewBand->DeskBand = DeskBand.Detach(); 501 NewBand->OleWindow = OleWindow.Detach(); 502 NewBand->WndEvtHandler = WndEvtHandler.Detach(); 503 504 /* Create the ReBar band */ 505 hRet = ObjWithSite->SetSite(static_cast<IOleWindow *>(this)); 506 if (SUCCEEDED(hRet)) 507 { 508 uBand = 0xffffffff; 509 if (SUCCEEDED(_UpdateBand(NewBand))) 510 { 511 if (NewBand->dbi.dwMask & DBIM_MODEFLAGS) 512 { 513 if (NewBand->dbi.dwModeFlags & DBIMF_ADDTOFRONT) 514 uBand = 0; 515 } 516 } 517 518 _BuildBandInfo(NewBand, &rbi); 519 520 if (SUCCEEDED(NewBand->OleWindow->GetWindow(&rbi.hwndChild)) && 521 rbi.hwndChild != NULL) 522 { 523 rbi.fMask |= RBBIM_CHILD; 524 WARN ("ReBar band uses child window 0x%p\n", rbi.hwndChild); 525 } 526 527 if (!SendMessageW(m_hwndRebar, RB_INSERTBANDW, (WPARAM)uBand, reinterpret_cast<LPARAM>(&rbi))) 528 return E_FAIL; 529 530 hRet = (HRESULT)((USHORT)_GetBandID(NewBand)); 531 532 _UpdateAllBands(); 533 } 534 else 535 { 536 WARN("IBandSite::AddBand(): Call to IDeskBand::SetSite() failed: %x\n", hRet); 537 538 /* Remove the band from the ReBar control */ 539 _BuildBandInfo(NewBand, &rbi); 540 uBand = (UINT)SendMessageW(m_hwndRebar, RB_IDTOINDEX, (WPARAM)rbi.wID, 0); 541 if (uBand != (UINT)-1) 542 { 543 if (!SendMessageW(m_hwndRebar, RB_DELETEBAND, (WPARAM)uBand, 0)) 544 { 545 ERR("Failed to delete band!\n"); 546 } 547 } 548 else 549 ERR("Failed to map band id to index!\n"); 550 551 _FreeBand(NewBand); 552 553 hRet = E_FAIL; 554 } 555 556 return hRet; 557 } 558 559 HRESULT STDMETHODCALLTYPE CBandSiteBase::EnumBands(UINT uBand, DWORD *pdwBandID) 560 { 561 DWORD i; 562 563 TRACE("(%p, %u, %p)\n", this, uBand, pdwBandID); 564 565 if (uBand == 0xffffffff) 566 return (UINT)m_cBands; 567 568 if (uBand >= (UINT)m_cBands) 569 return E_FAIL; 570 571 for (i = 0; i < (DWORD)m_cBandsAllocated; i++) 572 { 573 if (m_bands[i].DeskBand != NULL) 574 { 575 if (uBand == 0) 576 { 577 *pdwBandID = i; 578 return S_OK; 579 } 580 581 uBand--; 582 } 583 } 584 585 return E_FAIL; 586 } 587 588 HRESULT STDMETHODCALLTYPE CBandSiteBase::QueryBand(DWORD dwBandID, IDeskBand **ppstb, 589 DWORD *pdwState, LPWSTR pszName, int cchName) 590 { 591 struct BandObject *Band; 592 593 TRACE("(%p, %u, %p, %p, %p, %d)\n", this, dwBandID, ppstb, pdwState, pszName, cchName); 594 595 Band = _GetBandByID(dwBandID); 596 if (Band == NULL) 597 return E_FAIL; 598 599 if (ppstb != NULL) 600 { 601 Band->DeskBand->AddRef(); 602 *ppstb = Band->DeskBand; 603 } 604 605 if (pdwState != NULL) 606 { 607 FIXME("IBandSite::QueryBand() requests band state!\n"); 608 *pdwState = 0; 609 } 610 611 if (pszName != NULL && cchName > 0) 612 { 613 FIXME("IBandSite::QueryBand() requests band name!\n"); 614 pszName[0] = 0; 615 } 616 return S_OK; 617 } 618 619 HRESULT STDMETHODCALLTYPE CBandSiteBase::SetBandState(DWORD dwBandID, DWORD dwMask, DWORD dwState) 620 { 621 struct BandObject *Band; 622 623 TRACE("(%p, %u, %x, %x)\n", this, dwBandID, dwMask, dwState); 624 625 Band = _GetBandByID(dwBandID); 626 if (Band == NULL) 627 return E_FAIL; 628 629 FIXME("Stub\n"); 630 return E_NOTIMPL; 631 } 632 633 HRESULT STDMETHODCALLTYPE CBandSiteBase::RemoveBand(DWORD dwBandID) 634 { 635 struct BandObject *Band; 636 UINT uBand; 637 638 TRACE("(%p, %u)\n", this, dwBandID); 639 640 if (m_hwndRebar == NULL) 641 return E_FAIL; 642 643 Band = _GetBandByID(dwBandID); 644 if (Band == NULL) 645 return E_FAIL; 646 647 uBand = (UINT)SendMessageW(m_hwndRebar, RB_IDTOINDEX, (WPARAM)_GetBandID(Band), 0); 648 if (uBand != (UINT)-1) 649 { 650 if (!SendMessageW(m_hwndRebar, RB_DELETEBAND, (WPARAM)uBand, 0)) 651 { 652 ERR("Could not delete band!\n"); 653 } 654 } 655 else 656 ERR("Could not map band id to index!\n"); 657 658 _FreeBand(Band); 659 return S_OK; 660 } 661 662 HRESULT STDMETHODCALLTYPE CBandSiteBase::GetBandObject(DWORD dwBandID, REFIID riid, VOID **ppv) 663 { 664 struct BandObject *Band; 665 666 TRACE("(%p, %u, %s, %p)\n", this, dwBandID, debugstr_guid(&riid), ppv); 667 668 Band = _GetBandByID(dwBandID); 669 if (Band == NULL) 670 { 671 *ppv = NULL; 672 return E_FAIL; 673 } 674 675 return Band->DeskBand->QueryInterface(riid, ppv); 676 } 677 678 HRESULT STDMETHODCALLTYPE CBandSiteBase::SetBandSiteInfo(const BANDSITEINFO *pbsinfo) 679 { 680 if (!pbsinfo) 681 return E_INVALIDARG; 682 683 if ((pbsinfo->dwMask & BSIM_STATE)) 684 m_dwState = pbsinfo->dwState; 685 if ((pbsinfo->dwMask & BSIM_STYLE)) 686 m_dwStyle = pbsinfo->dwStyle; 687 688 _UpdateAllBands(); 689 return S_OK; 690 } 691 692 HRESULT STDMETHODCALLTYPE CBandSiteBase::GetBandSiteInfo(BANDSITEINFO *pbsinfo) 693 { 694 if (!pbsinfo) 695 return E_INVALIDARG; 696 697 if ((pbsinfo->dwMask & BSIM_STATE)) 698 pbsinfo->dwState = m_dwState; 699 if ((pbsinfo->dwMask & BSIM_STYLE)) 700 pbsinfo->dwStyle = m_dwStyle; 701 702 return S_OK; 703 } 704 705 HRESULT STDMETHODCALLTYPE CBandSiteBase::OnWinEvent(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT *plrResult) 706 { 707 struct BandObject *Band; 708 709 TRACE("(%p, %p, %u, %p, %p, %p)\n", this, hWnd, uMsg, wParam, lParam, plrResult); 710 711 if (plrResult) 712 *plrResult = 0; 713 if (m_hwndRebar == NULL) 714 return E_FAIL; 715 716 if (uMsg == WM_CONTEXTMENU) 717 { 718 HRESULT hr = _OnContextMenu(hWnd, uMsg, wParam, lParam, plrResult); 719 if (FAILED_UNEXPECTEDLY(hr)) 720 return hr; 721 722 return S_OK; 723 } 724 else if (uMsg == WM_COMMAND && lParam) 725 { 726 hWnd = reinterpret_cast<HWND>(lParam); 727 } 728 else if (uMsg == WM_NOTIFY) 729 { 730 NMHDR* pnmhdr = reinterpret_cast<NMHDR*>(lParam); 731 if (pnmhdr->hwndFrom != m_hwndRebar) 732 { 733 hWnd = pnmhdr->hwndFrom; 734 } 735 else 736 { 737 for (int i = 0; i < m_cBandsAllocated; i++) 738 { 739 if (m_bands[i].WndEvtHandler && m_bands[i].OleWindow) 740 { 741 HWND hwndBand; 742 if (SUCCEEDED(m_bands[i].OleWindow->GetWindow(&hwndBand))) 743 { 744 m_bands[i].WndEvtHandler->OnWinEvent(hwndBand, uMsg, wParam, lParam, plrResult); 745 } 746 } 747 } 748 return S_OK; 749 } 750 } 751 752 Band = _GetBandFromHwnd(hWnd); 753 if (Band != NULL) 754 { 755 return Band->WndEvtHandler->OnWinEvent(hWnd, uMsg, wParam, lParam, plrResult); 756 } 757 758 return E_FAIL; 759 } 760 761 HRESULT STDMETHODCALLTYPE CBandSiteBase::IsWindowOwner(HWND hWnd) 762 { 763 struct BandObject *Band; 764 765 TRACE("(%p, %p)\n", this, hWnd); 766 767 if (m_hwndRebar == NULL) 768 return E_FAIL; 769 770 Band = _GetBandFromHwnd(hWnd); 771 if (Band != NULL) 772 return S_OK; 773 774 return S_FALSE; 775 } 776 777 HRESULT STDMETHODCALLTYPE CBandSiteBase::GetWindow(HWND *phWnd) 778 { 779 TRACE("(%p, %p)\n", this, phWnd); 780 781 *phWnd = m_hwndRebar; 782 if (m_hwndRebar != NULL) 783 return S_OK; 784 785 return E_FAIL; 786 } 787 788 HRESULT STDMETHODCALLTYPE CBandSiteBase::ContextSensitiveHelp(BOOL fEnterMode) 789 { 790 FIXME("(%p, %d)\n", this, fEnterMode); 791 return E_NOTIMPL; 792 } 793 794 HRESULT STDMETHODCALLTYPE CBandSiteBase::SetDeskBarSite(IUnknown *pUnk) 795 { 796 HWND hWndParent; 797 HRESULT hRet; 798 DWORD style; 799 800 TRACE("(%p, %p)\n", this, pUnk); 801 802 m_site = NULL; 803 804 hRet = pUnk->QueryInterface(IID_PPV_ARG(IOleWindow, &m_site)); 805 if (FAILED_UNEXPECTEDLY(hRet)) 806 return E_FAIL; 807 808 hRet = m_site->GetWindow(&hWndParent); 809 if (FAILED_UNEXPECTEDLY(hRet)) 810 return E_FAIL; 811 812 style = WS_CHILD | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | RBS_VARHEIGHT | RBS_AUTOSIZE | 813 RBS_BANDBORDERS | CCS_NODIVIDER | /*CCS_NORESIZE |*/ CCS_NOPARENTALIGN; 814 815 m_hwndRebar = CreateWindowExW(WS_EX_TOOLWINDOW, 816 REBARCLASSNAMEW, 817 NULL, 818 style, 819 0, 0, 0, 0, 820 hWndParent, 821 NULL, 822 _AtlBaseModule.GetModuleInstance(), 823 NULL); 824 if (m_hwndRebar == NULL) 825 { 826 m_site = NULL; 827 WARN("IDeskbarClient::SetDeskBarSite() failed to create ReBar control!\n"); 828 return E_FAIL; 829 } 830 831 return S_OK; 832 } 833 834 HRESULT STDMETHODCALLTYPE CBandSiteBase::SetModeDBC(DWORD dwMode) 835 { 836 LONG dwStyle; 837 LONG dwPrevStyle; 838 839 TRACE("(%p, %x)\n", this, dwMode); 840 841 if (m_hwndRebar == NULL) 842 return E_FAIL; 843 844 dwStyle = dwPrevStyle = GetWindowLongPtr(m_hwndRebar, GWL_STYLE); 845 if (dwMode & DBIF_VIEWMODE_VERTICAL) 846 dwStyle |= CCS_VERT; 847 848 if (dwMode & ~DBIF_VIEWMODE_VERTICAL) 849 FIXME("IDeskBarClient::SetModeDBC() unhandled modes: %x\n", dwStyle & ~DBIF_VIEWMODE_VERTICAL); 850 851 if (dwStyle != dwPrevStyle) 852 { 853 SetWindowLongPtr(m_hwndRebar, GWL_STYLE, dwPrevStyle); 854 } 855 856 return S_OK; 857 } 858 859 HRESULT STDMETHODCALLTYPE CBandSiteBase::UIActivateDBC(DWORD dwState) 860 { 861 TRACE("(%p, %x)\n", this, dwState); 862 863 if (m_hwndRebar == NULL) 864 return E_FAIL; 865 866 ShowWindow(m_hwndRebar, (dwState & DBC_SHOW) ? SW_SHOW : SW_HIDE); 867 //FIXME: Properly notify bands? 868 return S_OK; 869 } 870 871 HRESULT STDMETHODCALLTYPE CBandSiteBase::GetSize(DWORD unknown1, LPRECT unknown2) 872 { 873 FIXME("(%p, %x, %p)\n", this, unknown1, unknown2); 874 return E_NOTIMPL; 875 } 876 877 HRESULT STDMETHODCALLTYPE CBandSiteBase::QueryStatus(const GUID *pguidCmdGroup, 878 DWORD cCmds, OLECMD *prgCmds, OLECMDTEXT *pCmdText) 879 { 880 FIXME("(%p, %p, %u, %p, %p)\n", this, pguidCmdGroup, cCmds, prgCmds, pCmdText); 881 return E_NOTIMPL; 882 } 883 884 HRESULT STDMETHODCALLTYPE CBandSiteBase::Exec(const GUID *pguidCmdGroup, DWORD nCmdID, 885 DWORD nCmdExecOpt, VARIANTARG *pvaIn, VARIANTARG *pvaOut) 886 { 887 HRESULT hRet = S_OK; 888 889 TRACE("(%p, %p, %u, %u, %p, %p)\n", this, pguidCmdGroup, nCmdID, nCmdExecOpt, pvaIn, pvaOut); 890 891 if (m_hwndRebar == NULL) 892 return E_FAIL; 893 894 if (IsEqualIID(*pguidCmdGroup, IID_IDeskBand)) 895 { 896 switch (nCmdID) 897 { 898 case DBID_BANDINFOCHANGED: 899 if (pvaIn == NULL) 900 hRet = _UpdateAllBands(); 901 else 902 { 903 /* Update a single band */ 904 if (pvaIn->n1.n2.vt == VT_I4) 905 hRet = _UpdateBand(pvaIn->n1.n2.n3.lVal); 906 else 907 hRet = E_FAIL; 908 } 909 break; 910 911 case DBID_SHOWONLY: 912 case DBID_MAXIMIZEBAND: 913 case DBID_PUSHCHEVRON: 914 FIXME("IOleCommandTarget::Exec(): Unsupported command ID %d\n", nCmdID); 915 return E_NOTIMPL; 916 default: 917 return E_FAIL; 918 } 919 return hRet; 920 } 921 else 922 WARN("IOleCommandTarget::Exec(): Unsupported command group GUID\n"); 923 924 return E_NOTIMPL; 925 } 926 927 HRESULT STDMETHODCALLTYPE CBandSiteBase::UIActivateIO(BOOL fActivate, LPMSG lpMsg) 928 { 929 return E_NOTIMPL; 930 } 931 932 HRESULT STDMETHODCALLTYPE CBandSiteBase::HasFocusIO() 933 { 934 return E_NOTIMPL; 935 } 936 937 HRESULT STDMETHODCALLTYPE CBandSiteBase::TranslateAcceleratorIO(LPMSG lpMsg) 938 { 939 return E_NOTIMPL; 940 } 941 942 HRESULT STDMETHODCALLTYPE CBandSiteBase::OnFocusChangeIS(struct IUnknown *paramC, int param10) 943 { 944 return E_NOTIMPL; 945 } 946 947 HRESULT STDMETHODCALLTYPE CBandSiteBase::QueryService(REFGUID guidService, REFIID riid, void **ppvObject) 948 { 949 return E_NOTIMPL; 950 } 951 952 HRESULT STDMETHODCALLTYPE CBandSiteBase::GetClassID(CLSID *pClassID) 953 { 954 return E_NOTIMPL; 955 } 956 957 HRESULT STDMETHODCALLTYPE CBandSiteBase::IsDirty() 958 { 959 return E_NOTIMPL; 960 } 961 962 HRESULT STDMETHODCALLTYPE CBandSiteBase::Load(IStream *pStm) 963 { 964 return E_NOTIMPL; 965 } 966 967 HRESULT STDMETHODCALLTYPE CBandSiteBase::Save(IStream *pStm, BOOL fClearDirty) 968 { 969 return E_NOTIMPL; 970 } 971 972 HRESULT STDMETHODCALLTYPE CBandSiteBase::GetSizeMax(ULARGE_INTEGER *pcbSize) 973 { 974 return E_NOTIMPL; 975 } 976 977 HRESULT STDMETHODCALLTYPE CBandSiteBase::DragEnter( 978 IDataObject *pDataObj, DWORD grfKeyState, POINTL pt, DWORD *pdwEffect) 979 { 980 return E_NOTIMPL; 981 } 982 983 HRESULT STDMETHODCALLTYPE CBandSiteBase::DragOver(DWORD grfKeyState, POINTL pt, DWORD *pdwEffect) 984 { 985 return E_NOTIMPL; 986 } 987 988 HRESULT STDMETHODCALLTYPE CBandSiteBase::DragLeave() 989 { 990 return E_NOTIMPL; 991 } 992 993 HRESULT STDMETHODCALLTYPE CBandSiteBase::Drop(IDataObject *pDataObj, DWORD grfKeyState, POINTL pt, DWORD *pdwEffect) 994 { 995 return E_NOTIMPL; 996 } 997 998 HRESULT STDMETHODCALLTYPE CBandSiteBase::LoadFromStreamBS(IStream *, const GUID &, void **) 999 { 1000 return E_NOTIMPL; 1001 } 1002 1003 HRESULT STDMETHODCALLTYPE CBandSiteBase::SaveToStreamBS(IUnknown *, IStream *) 1004 { 1005 return E_NOTIMPL; 1006 } 1007 1008 extern "C" 1009 HRESULT WINAPI RSHELL_CBandSite_CreateInstance(LPUNKNOWN pUnkOuter, REFIID riid, void **ppv) 1010 { 1011 return CBandSite::_CreatorClass::CreateInstance(pUnkOuter, riid, ppv); 1012 } 1013