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