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
CBandSiteBase()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
_GetBandID(struct BandObject * Band)49 UINT CBandSiteBase::_GetBandID(struct BandObject *Band)
50 {
51 return (UINT)(Band - m_bands);
52 }
53
_GetBandByID(DWORD dwBandID)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
_FreeBand(struct BandObject * Band)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
_GetViewMode()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
_BuildBandInfo(struct BandObject * Band,REBARBANDINFOW * prbi)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
_UpdateBand(struct BandObject * Band)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
_UpdateAllBands()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
_UpdateBand(DWORD dwBandID)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
_IsBandDeletable(DWORD dwBandID)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
_OnContextMenu(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam,LRESULT * plrResult)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
_GetBandFromHwnd(HWND hwnd)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
~CBandSiteBase()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
AddBand(IUnknown * punk)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
EnumBands(UINT uBand,DWORD * pdwBandID)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
QueryBand(DWORD dwBandID,IDeskBand ** ppstb,DWORD * pdwState,LPWSTR pszName,int cchName)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
SetBandState(DWORD dwBandID,DWORD dwMask,DWORD dwState)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
RemoveBand(DWORD dwBandID)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
GetBandObject(DWORD dwBandID,REFIID riid,VOID ** ppv)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
SetBandSiteInfo(const BANDSITEINFO * pbsinfo)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
GetBandSiteInfo(BANDSITEINFO * pbsinfo)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
OnWinEvent(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam,LRESULT * plrResult)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
IsWindowOwner(HWND hWnd)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
GetWindow(HWND * phWnd)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
ContextSensitiveHelp(BOOL fEnterMode)788 HRESULT STDMETHODCALLTYPE CBandSiteBase::ContextSensitiveHelp(BOOL fEnterMode)
789 {
790 FIXME("(%p, %d)\n", this, fEnterMode);
791 return E_NOTIMPL;
792 }
793
SetDeskBarSite(IUnknown * pUnk)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
SetModeDBC(DWORD dwMode)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
UIActivateDBC(DWORD dwState)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
GetSize(DWORD unknown1,LPRECT unknown2)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
QueryStatus(const GUID * pguidCmdGroup,DWORD cCmds,OLECMD * prgCmds,OLECMDTEXT * pCmdText)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
Exec(const GUID * pguidCmdGroup,DWORD nCmdID,DWORD nCmdExecOpt,VARIANTARG * pvaIn,VARIANTARG * pvaOut)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
UIActivateIO(BOOL fActivate,LPMSG lpMsg)927 HRESULT STDMETHODCALLTYPE CBandSiteBase::UIActivateIO(BOOL fActivate, LPMSG lpMsg)
928 {
929 return E_NOTIMPL;
930 }
931
HasFocusIO()932 HRESULT STDMETHODCALLTYPE CBandSiteBase::HasFocusIO()
933 {
934 return E_NOTIMPL;
935 }
936
TranslateAcceleratorIO(LPMSG lpMsg)937 HRESULT STDMETHODCALLTYPE CBandSiteBase::TranslateAcceleratorIO(LPMSG lpMsg)
938 {
939 return E_NOTIMPL;
940 }
941
OnFocusChangeIS(struct IUnknown * paramC,int param10)942 HRESULT STDMETHODCALLTYPE CBandSiteBase::OnFocusChangeIS(struct IUnknown *paramC, int param10)
943 {
944 return E_NOTIMPL;
945 }
946
QueryService(REFGUID guidService,REFIID riid,void ** ppvObject)947 HRESULT STDMETHODCALLTYPE CBandSiteBase::QueryService(REFGUID guidService, REFIID riid, void **ppvObject)
948 {
949 return E_NOTIMPL;
950 }
951
GetClassID(CLSID * pClassID)952 HRESULT STDMETHODCALLTYPE CBandSiteBase::GetClassID(CLSID *pClassID)
953 {
954 return E_NOTIMPL;
955 }
956
IsDirty()957 HRESULT STDMETHODCALLTYPE CBandSiteBase::IsDirty()
958 {
959 return E_NOTIMPL;
960 }
961
Load(IStream * pStm)962 HRESULT STDMETHODCALLTYPE CBandSiteBase::Load(IStream *pStm)
963 {
964 return E_NOTIMPL;
965 }
966
Save(IStream * pStm,BOOL fClearDirty)967 HRESULT STDMETHODCALLTYPE CBandSiteBase::Save(IStream *pStm, BOOL fClearDirty)
968 {
969 return E_NOTIMPL;
970 }
971
GetSizeMax(ULARGE_INTEGER * pcbSize)972 HRESULT STDMETHODCALLTYPE CBandSiteBase::GetSizeMax(ULARGE_INTEGER *pcbSize)
973 {
974 return E_NOTIMPL;
975 }
976
DragEnter(IDataObject * pDataObj,DWORD grfKeyState,POINTL pt,DWORD * pdwEffect)977 HRESULT STDMETHODCALLTYPE CBandSiteBase::DragEnter(
978 IDataObject *pDataObj, DWORD grfKeyState, POINTL pt, DWORD *pdwEffect)
979 {
980 return E_NOTIMPL;
981 }
982
DragOver(DWORD grfKeyState,POINTL pt,DWORD * pdwEffect)983 HRESULT STDMETHODCALLTYPE CBandSiteBase::DragOver(DWORD grfKeyState, POINTL pt, DWORD *pdwEffect)
984 {
985 return E_NOTIMPL;
986 }
987
DragLeave()988 HRESULT STDMETHODCALLTYPE CBandSiteBase::DragLeave()
989 {
990 return E_NOTIMPL;
991 }
992
Drop(IDataObject * pDataObj,DWORD grfKeyState,POINTL pt,DWORD * pdwEffect)993 HRESULT STDMETHODCALLTYPE CBandSiteBase::Drop(IDataObject *pDataObj, DWORD grfKeyState, POINTL pt, DWORD *pdwEffect)
994 {
995 return E_NOTIMPL;
996 }
997
LoadFromStreamBS(IStream *,const GUID &,void **)998 HRESULT STDMETHODCALLTYPE CBandSiteBase::LoadFromStreamBS(IStream *, const GUID &, void **)
999 {
1000 return E_NOTIMPL;
1001 }
1002
SaveToStreamBS(IUnknown *,IStream *)1003 HRESULT STDMETHODCALLTYPE CBandSiteBase::SaveToStreamBS(IUnknown *, IStream *)
1004 {
1005 return E_NOTIMPL;
1006 }
1007
1008 extern "C"
RSHELL_CBandSite_CreateInstance(LPUNKNOWN pUnkOuter,REFIID riid,void ** ppv)1009 HRESULT WINAPI RSHELL_CBandSite_CreateInstance(LPUNKNOWN pUnkOuter, REFIID riid, void **ppv)
1010 {
1011 return CBandSite::_CreatorClass::CreateInstance(pUnkOuter, riid, ppv);
1012 }
1013