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