0ec21b78b41c9beb6d01e778c6714b78bb01f3ca
[reactos.git] / base / shell / rshell / CMenuBand.cpp
1 /*
2 * Shell Menu Band
3 *
4 * Copyright 2014 David Quintana
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 */
20 #include "precomp.h"
21 #include <windowsx.h>
22 #include <CommonControls.h>
23 #include <shlwapi_undoc.h>
24
25 #include "CMenuBand.h"
26 #include "CMenuToolbars.h"
27 #include "CMenuFocusManager.h"
28
29 WINE_DEFAULT_DEBUG_CHANNEL(CMenuBand);
30
31 extern "C"
32 HRESULT CMenuBand_Constructor(REFIID riid, LPVOID *ppv)
33 {
34 *ppv = NULL;
35
36 CMenuBand * site = new CComObject<CMenuBand>();
37
38 if (!site)
39 return E_OUTOFMEMORY;
40
41 HRESULT hr = site->QueryInterface(riid, ppv);
42
43 if (FAILED(hr))
44 site->Release();
45
46 return hr;
47 }
48
49 CMenuBand::CMenuBand() :
50 m_staticToolbar(NULL),
51 m_SFToolbar(NULL),
52 m_site(NULL),
53 m_psmc(NULL),
54 m_subMenuChild(NULL),
55 m_useBigIcons(FALSE),
56 m_hotBar(NULL),
57 m_hotItem(-1),
58 m_popupItem(-1)
59 {
60 m_focusManager = CMenuFocusManager::AcquireManager();
61
62 m_marlett = CreateFont(
63 0, 0, 0, 0, 0, 0, 0, 0, DEFAULT_CHARSET,
64 OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
65 DEFAULT_QUALITY, FF_DONTCARE, L"Marlett");
66 }
67
68 CMenuBand::~CMenuBand()
69 {
70 CMenuFocusManager::ReleaseManager(m_focusManager);
71
72 if (m_staticToolbar)
73 delete m_staticToolbar;
74
75 if (m_SFToolbar)
76 delete m_SFToolbar;
77
78 DeleteObject(m_marlett);
79 }
80
81 HRESULT STDMETHODCALLTYPE CMenuBand::Initialize(
82 IShellMenuCallback *psmc,
83 UINT uId,
84 UINT uIdAncestor,
85 DWORD dwFlags)
86 {
87 if (m_psmc != psmc)
88 m_psmc = psmc;
89 m_uId = uId;
90 m_uIdAncestor = uIdAncestor;
91 m_dwFlags = dwFlags;
92
93 if (m_psmc)
94 {
95 _CallCB(SMC_CREATE, 0, reinterpret_cast<LPARAM>(&m_UserData));
96 }
97
98 return S_OK;
99 }
100
101 HRESULT STDMETHODCALLTYPE CMenuBand::GetMenuInfo(
102 IShellMenuCallback **ppsmc,
103 UINT *puId,
104 UINT *puIdAncestor,
105 DWORD *pdwFlags)
106 {
107 if (!pdwFlags) // maybe?
108 return E_INVALIDARG;
109
110 if (ppsmc)
111 *ppsmc = m_psmc;
112
113 if (puId)
114 *puId = m_uId;
115
116 if (puIdAncestor)
117 *puIdAncestor = m_uIdAncestor;
118
119 *pdwFlags = m_dwFlags;
120
121 return S_OK;
122 }
123
124 HRESULT STDMETHODCALLTYPE CMenuBand::SetMenu(
125 HMENU hmenu,
126 HWND hwnd,
127 DWORD dwFlags)
128 {
129 if (m_staticToolbar == NULL)
130 {
131 m_staticToolbar = new CMenuStaticToolbar(this);
132 }
133 m_hmenu = hmenu;
134 m_menuOwner;
135
136 HRESULT hr = m_staticToolbar->SetMenu(hmenu, hwnd, dwFlags);
137 if (FAILED(hr))
138 return hr;
139
140 if (m_site)
141 {
142 HWND hwndParent;
143
144 hr = m_site->GetWindow(&hwndParent);
145 if (FAILED(hr))
146 return hr;
147
148 hr = m_staticToolbar->CreateToolbar(hwndParent, m_dwFlags);
149 if (FAILED(hr))
150 return hr;
151
152 hr = m_staticToolbar->FillToolbar();
153 }
154
155 return hr;
156 }
157
158 HRESULT STDMETHODCALLTYPE CMenuBand::GetMenu(
159 HMENU *phmenu,
160 HWND *phwnd,
161 DWORD *pdwFlags)
162 {
163 if (m_staticToolbar == NULL)
164 return E_FAIL;
165
166 return m_staticToolbar->GetMenu(phmenu, phwnd, pdwFlags);
167 }
168
169 HRESULT STDMETHODCALLTYPE CMenuBand::SetSite(IUnknown *pUnkSite)
170 {
171 HWND hwndParent;
172 HRESULT hr;
173
174 m_site = NULL;
175
176 if (pUnkSite == NULL)
177 return S_OK;
178
179 hwndParent = NULL;
180 hr = pUnkSite->QueryInterface(IID_PPV_ARG(IOleWindow, &m_site));
181 if (FAILED(hr))
182 return hr;
183
184 hr = m_site->GetWindow(&hwndParent);
185 if (FAILED(hr))
186 return hr;
187
188 if (!::IsWindow(hwndParent))
189 return E_FAIL;
190
191 if (m_staticToolbar != NULL)
192 {
193 hr = m_staticToolbar->CreateToolbar(hwndParent, m_dwFlags);
194 if (FAILED(hr))
195 return hr;
196
197 hr = m_staticToolbar->FillToolbar();
198 if (FAILED(hr))
199 return hr;
200 }
201
202 if (m_SFToolbar != NULL)
203 {
204 hr = m_SFToolbar->CreateToolbar(hwndParent, m_dwFlags);
205 if (FAILED(hr))
206 return hr;
207
208 hr = m_SFToolbar->FillToolbar();
209 if (FAILED(hr))
210 return hr;
211 }
212
213 hr = IUnknown_QueryService(m_site, SID_SMenuPopup, IID_PPV_ARG(IMenuPopup, &m_subMenuParent));
214 if (FAILED(hr))
215 return hr;
216
217 CComPtr<IOleWindow> pTopLevelWindow;
218 hr = IUnknown_QueryService(m_site, SID_STopLevelBrowser, IID_PPV_ARG(IOleWindow, &pTopLevelWindow));
219 if (FAILED(hr))
220 return hr;
221
222 return pTopLevelWindow->GetWindow(&m_topLevelWindow);
223 }
224
225 HRESULT STDMETHODCALLTYPE CMenuBand::GetSite(REFIID riid, PVOID *ppvSite)
226 {
227 if (m_site == NULL)
228 return E_FAIL;
229
230 return m_site->QueryInterface(riid, ppvSite);
231 }
232
233 HRESULT STDMETHODCALLTYPE CMenuBand::GetWindow(
234 HWND *phwnd)
235 {
236 if (m_SFToolbar != NULL)
237 return m_SFToolbar->GetWindow(phwnd);
238
239 if (m_staticToolbar != NULL)
240 return m_staticToolbar->GetWindow(phwnd);
241
242 return E_FAIL;
243 }
244
245 HRESULT STDMETHODCALLTYPE CMenuBand::OnPosRectChangeDB(RECT *prc)
246 {
247 SIZE sizeStatic = { 0 };
248 SIZE sizeShlFld = { 0 };
249 HRESULT hr = S_OK;
250
251 if (m_staticToolbar != NULL)
252 hr = m_staticToolbar->GetIdealSize(sizeStatic);
253 if (FAILED(hr))
254 return hr;
255
256 if (m_SFToolbar != NULL)
257 hr = m_SFToolbar->GetIdealSize(sizeShlFld);
258 if (FAILED(hr))
259 return hr;
260
261 if (m_staticToolbar == NULL && m_SFToolbar == NULL)
262 return E_FAIL;
263
264 int sy = min(prc->bottom - prc->top, sizeStatic.cy + sizeShlFld.cy);
265
266 int syStatic = sizeStatic.cy;
267 int syShlFld = sy - syStatic;
268
269 if (m_SFToolbar)
270 {
271 m_SFToolbar->SetPosSize(
272 prc->left,
273 prc->top,
274 prc->right - prc->left,
275 syShlFld);
276 }
277 if (m_staticToolbar)
278 {
279 m_staticToolbar->SetPosSize(
280 prc->left,
281 prc->top + syShlFld,
282 prc->right - prc->left,
283 syStatic);
284 }
285
286 return S_OK;
287 }
288 HRESULT STDMETHODCALLTYPE CMenuBand::GetBandInfo(
289 DWORD dwBandID,
290 DWORD dwViewMode,
291 DESKBANDINFO *pdbi)
292 {
293 SIZE sizeStatic = { 0 };
294 SIZE sizeShlFld = { 0 };
295
296 HRESULT hr = S_OK;
297
298 if (m_staticToolbar != NULL)
299 hr = m_staticToolbar->GetIdealSize(sizeStatic);
300 if (FAILED(hr))
301 return hr;
302
303 if (m_SFToolbar != NULL)
304 hr = m_SFToolbar->GetIdealSize(sizeShlFld);
305 if (FAILED(hr))
306 return hr;
307
308 if (m_staticToolbar == NULL && m_SFToolbar == NULL)
309 return E_FAIL;
310
311 pdbi->ptMaxSize.x = max(sizeStatic.cx, sizeShlFld.cx) + 20;
312 pdbi->ptMaxSize.y = sizeStatic.cy + sizeShlFld.cy;
313
314 return S_OK;
315 }
316
317 HRESULT STDMETHODCALLTYPE CMenuBand::ShowDW(BOOL fShow)
318 {
319 HRESULT hr = S_OK;
320
321 if (m_staticToolbar != NULL)
322 hr = m_staticToolbar->ShowWindow(fShow);
323 if (FAILED(hr))
324 return hr;
325 if (m_SFToolbar != NULL)
326 hr = m_SFToolbar->ShowWindow(fShow);
327 if (FAILED(hr))
328 return hr;
329
330 if (fShow)
331 {
332 hr = _CallCB(SMC_INITMENU, 0, 0);
333 if (FAILED(hr))
334 return hr;
335 }
336
337 if (fShow)
338 hr = m_focusManager->PushMenu(this);
339 else
340 hr = m_focusManager->PopMenu(this);
341
342 return S_OK;
343 }
344
345 HRESULT STDMETHODCALLTYPE CMenuBand::CloseDW(DWORD dwReserved)
346 {
347 ShowDW(FALSE);
348
349 if (m_staticToolbar != NULL)
350 return m_staticToolbar->Close();
351
352 if (m_SFToolbar != NULL)
353 return m_SFToolbar->Close();
354
355 return S_OK;
356 }
357 HRESULT STDMETHODCALLTYPE CMenuBand::ResizeBorderDW(LPCRECT prcBorder, IUnknown *punkToolbarSite, BOOL fReserved)
358 {
359 UNIMPLEMENTED;
360 return S_OK;
361 }
362
363 HRESULT STDMETHODCALLTYPE CMenuBand::ContextSensitiveHelp(BOOL fEnterMode)
364 {
365 UNIMPLEMENTED;
366 return S_OK;
367 }
368
369 HRESULT STDMETHODCALLTYPE CMenuBand::UIActivateIO(BOOL fActivate, LPMSG lpMsg)
370 {
371 HRESULT hr;
372
373 hr = m_subMenuParent->SetSubMenu(this, fActivate);
374 if (FAILED(hr))
375 return hr;
376
377 if (fActivate)
378 {
379 CComPtr<IOleWindow> pTopLevelWindow;
380 hr = IUnknown_QueryService(m_site, SID_SMenuPopup, IID_PPV_ARG(IOleWindow, &pTopLevelWindow));
381 if (FAILED(hr))
382 return hr;
383
384 hr = pTopLevelWindow->GetWindow(&m_topLevelWindow);
385 if (FAILED(hr))
386 return hr;
387 }
388 else
389 {
390 m_topLevelWindow = NULL;
391 }
392
393 return S_FALSE;
394 }
395
396 HRESULT STDMETHODCALLTYPE CMenuBand::Exec(const GUID *pguidCmdGroup, DWORD nCmdID, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
397 {
398 if (!pguidCmdGroup)
399 return E_FAIL;
400
401 if (IsEqualGUID(*pguidCmdGroup, CLSID_MenuBand))
402 {
403 if (nCmdID == 16) // set (big) icon size
404 {
405 this->m_useBigIcons = nCmdexecopt == 2;
406 return S_OK;
407 }
408 else if (nCmdID == 19) // popup-related
409 {
410 return S_FALSE;
411 }
412 }
413
414 UNIMPLEMENTED;
415 return S_OK;
416 }
417
418 HRESULT STDMETHODCALLTYPE CMenuBand::QueryService(REFGUID guidService, REFIID riid, void **ppvObject)
419 {
420 if (IsEqualIID(guidService, SID_SMenuBandChild) ||
421 IsEqualIID(guidService, SID_SMenuBandBottom) ||
422 IsEqualIID(guidService, SID_SMenuBandBottomSelected))
423 return this->QueryInterface(riid, ppvObject);
424 WARN("Unknown service requested %s\n", wine_dbgstr_guid(&guidService));
425 return E_NOINTERFACE;
426 }
427
428 HRESULT STDMETHODCALLTYPE CMenuBand::Popup(POINTL *ppt, RECTL *prcExclude, MP_POPUPFLAGS dwFlags)
429 {
430 UNIMPLEMENTED;
431 return S_OK;
432 }
433
434 HRESULT STDMETHODCALLTYPE CMenuBand::OnSelect(DWORD dwSelectType)
435 {
436 switch (dwSelectType)
437 {
438 case MPOS_CHILDTRACKING:
439 // TODO: Cancel timers?
440 return m_subMenuParent->OnSelect(dwSelectType);
441 case MPOS_SELECTLEFT:
442 if (m_subMenuChild)
443 m_subMenuChild->OnSelect(MPOS_CANCELLEVEL);
444 return m_subMenuParent->OnSelect(dwSelectType);
445 case MPOS_SELECTRIGHT:
446 return m_subMenuParent->OnSelect(dwSelectType);
447 case MPOS_EXECUTE:
448 case MPOS_FULLCANCEL:
449 if (m_subMenuChild)
450 m_subMenuChild->OnSelect(dwSelectType);
451 return m_subMenuParent->OnSelect(dwSelectType);
452 case MPOS_CANCELLEVEL:
453 if (m_subMenuChild)
454 m_subMenuChild->OnSelect(dwSelectType);
455 break;
456 }
457 return S_FALSE;
458 }
459
460 HRESULT STDMETHODCALLTYPE CMenuBand::SetSubMenu(IMenuPopup *pmp, BOOL fSet)
461 {
462 UNIMPLEMENTED;
463 return S_OK;
464 }
465
466 HRESULT STDMETHODCALLTYPE CMenuBand::SetClient(IUnknown *punkClient)
467 {
468 UNIMPLEMENTED;
469 return S_OK;
470 }
471
472 HRESULT STDMETHODCALLTYPE CMenuBand::GetClient(IUnknown **ppunkClient)
473 {
474 // HACK, so I can test for a submenu in the DeskBar
475 //UNIMPLEMENTED;
476 if (ppunkClient)
477 {
478 if (m_subMenuChild)
479 *ppunkClient = m_subMenuChild;
480 else
481 *ppunkClient = NULL;
482 }
483 return S_OK;
484 }
485
486 HRESULT STDMETHODCALLTYPE CMenuBand::IsMenuMessage(MSG *pmsg)
487 {
488 //UNIMPLEMENTED;
489 //return S_OK;
490 return S_FALSE;
491 //return E_NOTIMPL;
492 }
493
494 HRESULT STDMETHODCALLTYPE CMenuBand::TranslateMenuMessage(MSG *pmsg, LRESULT *plRet)
495 {
496 //UNIMPLEMENTED;
497 return S_FALSE;
498 }
499
500 HRESULT STDMETHODCALLTYPE CMenuBand::SetShellFolder(IShellFolder *psf, LPCITEMIDLIST pidlFolder, HKEY hKey, DWORD dwFlags)
501 {
502 if (m_SFToolbar == NULL)
503 {
504 m_SFToolbar = new CMenuSFToolbar(this);
505 }
506
507 HRESULT hr = m_SFToolbar->SetShellFolder(psf, pidlFolder, hKey, dwFlags);
508 if (FAILED(hr))
509 return hr;
510
511 if (m_site)
512 {
513 HWND hwndParent;
514
515 hr = m_site->GetWindow(&hwndParent);
516 if (FAILED(hr))
517 return hr;
518
519 hr = m_SFToolbar->CreateToolbar(hwndParent, m_dwFlags);
520 if (FAILED(hr))
521 return hr;
522
523 hr = m_SFToolbar->FillToolbar();
524 }
525
526 return hr;
527 }
528
529 HRESULT STDMETHODCALLTYPE CMenuBand::GetShellFolder(DWORD *pdwFlags, LPITEMIDLIST *ppidl, REFIID riid, void **ppv)
530 {
531 if (m_SFToolbar)
532 return m_SFToolbar->GetShellFolder(pdwFlags, ppidl, riid, ppv);
533 return E_FAIL;
534 }
535
536 HRESULT STDMETHODCALLTYPE CMenuBand::InvalidateItem(LPSMDATA psmd, DWORD dwFlags)
537 {
538 UNIMPLEMENTED;
539 return S_OK;
540 }
541
542 HRESULT STDMETHODCALLTYPE CMenuBand::GetState(LPSMDATA psmd)
543 {
544 UNIMPLEMENTED;
545 return S_OK;
546 }
547
548 HRESULT STDMETHODCALLTYPE CMenuBand::SetMenuToolbar(IUnknown *punk, DWORD dwFlags)
549 {
550 UNIMPLEMENTED;
551 return S_OK;
552 }
553
554 HRESULT STDMETHODCALLTYPE CMenuBand::OnWinEvent(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT *theResult)
555 {
556 RECT rc;
557 HDC hdc;
558 HBRUSH bgBrush;
559 HBRUSH hotBrush;
560 NMHDR * hdr;
561 NMTBCUSTOMDRAW * cdraw;
562 NMTBHOTITEM * hot;
563 NMMOUSE * rclick;
564 NMPGCALCSIZE* csize;
565 TBBUTTONINFO btni;
566 BOOL useFlatMenus = FALSE;
567 COLORREF clrText;
568 COLORREF clrTextHighlight;
569
570
571 *theResult = 0;
572 switch (uMsg)
573 {
574 case WM_COMMAND:
575
576 if (m_staticToolbar && m_staticToolbar->IsWindowOwner(hWnd) == S_OK)
577 {
578 return m_staticToolbar->OnCommand(wParam, lParam, theResult);
579 }
580
581 if (m_SFToolbar && m_SFToolbar->IsWindowOwner(hWnd) == S_OK)
582 {
583 return m_SFToolbar->OnCommand(wParam, lParam, theResult);
584 }
585
586 return S_OK;
587
588 case WM_NOTIFY:
589 hdr = reinterpret_cast<LPNMHDR>(lParam);
590 switch (hdr->code)
591 {
592 case PGN_CALCSIZE:
593 csize = reinterpret_cast<LPNMPGCALCSIZE>(hdr);
594
595 if (m_staticToolbar && m_staticToolbar->IsWindowOwner(hWnd) == S_OK)
596 {
597 SIZE tbs;
598 m_staticToolbar->GetIdealSize(tbs);
599 if (csize->dwFlag == PGF_CALCHEIGHT)
600 {
601 csize->iHeight = tbs.cy;
602 }
603 else if (csize->dwFlag == PGF_CALCWIDTH)
604 {
605 csize->iHeight = tbs.cx;
606 }
607 }
608
609 if (m_SFToolbar && m_SFToolbar->IsWindowOwner(hWnd) == S_OK)
610 {
611 SIZE tbs;
612 m_SFToolbar->GetIdealSize(tbs);
613 if (csize->dwFlag == PGF_CALCHEIGHT)
614 {
615 csize->iHeight = tbs.cy;
616 }
617 else if (csize->dwFlag == PGF_CALCWIDTH)
618 {
619 csize->iHeight = tbs.cx;
620 }
621 }
622 return S_OK;
623
624 case TBN_DROPDOWN:
625
626 if (m_staticToolbar && m_staticToolbar->IsWindowOwner(hWnd) == S_OK)
627 {
628 WPARAM wp = reinterpret_cast<LPNMTOOLBAR>(hdr)->iItem;
629 return m_staticToolbar->OnCommand(wp, 0, theResult);
630 }
631
632 if (m_SFToolbar && m_SFToolbar->IsWindowOwner(hWnd) == S_OK)
633 {
634 WPARAM wp = reinterpret_cast<LPNMTOOLBAR>(hdr)->iItem;
635 return m_SFToolbar->OnCommand(wp, 0, theResult);
636 }
637
638 return S_OK;
639
640 case TBN_HOTITEMCHANGE:
641 hot = reinterpret_cast<LPNMTBHOTITEM>(hdr);
642
643 if (m_staticToolbar && m_staticToolbar->IsWindowOwner(hWnd) == S_OK)
644 {
645 return m_staticToolbar->OnHotItemChange(hot);
646 }
647
648 if (m_SFToolbar && m_SFToolbar->IsWindowOwner(hWnd) == S_OK)
649 {
650 return m_SFToolbar->OnHotItemChange(hot);
651 }
652
653 return S_OK;
654
655 case NM_RCLICK:
656 rclick = reinterpret_cast<LPNMMOUSE>(hdr);
657
658 if (m_staticToolbar && m_staticToolbar->IsWindowOwner(hWnd) == S_OK)
659 {
660 return m_staticToolbar->OnContextMenu(rclick);
661 }
662
663 if (m_SFToolbar && m_SFToolbar->IsWindowOwner(hWnd) == S_OK)
664 {
665 return m_SFToolbar->OnContextMenu(rclick);
666 }
667
668 return S_OK;
669
670 case NM_CUSTOMDRAW:
671 cdraw = reinterpret_cast<LPNMTBCUSTOMDRAW>(hdr);
672 switch (cdraw->nmcd.dwDrawStage)
673 {
674 case CDDS_PREPAINT:
675 *theResult = CDRF_NOTIFYITEMDRAW;
676 return S_OK;
677
678 case CDDS_ITEMPREPAINT:
679
680 SystemParametersInfo(SPI_GETFLATMENU, 0, &useFlatMenus, 0);
681
682 clrText = GetSysColor(COLOR_MENUTEXT);
683 clrTextHighlight = GetSysColor(COLOR_HIGHLIGHTTEXT);
684
685 bgBrush = GetSysColorBrush(COLOR_MENU);
686 hotBrush = GetSysColorBrush(useFlatMenus ? COLOR_MENUHILIGHT : COLOR_HIGHLIGHT);
687
688 rc = cdraw->nmcd.rc;
689 hdc = cdraw->nmcd.hdc;
690
691 if (((INT)cdraw->nmcd.dwItemSpec == m_hotItem ||
692 (m_hotItem < 0 && (INT)cdraw->nmcd.dwItemSpec == m_popupItem)))
693 {
694 cdraw->nmcd.uItemState = CDIS_HOT;
695 }
696
697 switch (cdraw->nmcd.uItemState)
698 {
699 case CDIS_HOT:
700 case CDIS_FOCUS:
701 FillRect(hdc, &rc, hotBrush);
702 SetTextColor(hdc, clrTextHighlight);
703 cdraw->clrText = clrTextHighlight;
704 break;
705 default:
706 FillRect(hdc, &rc, bgBrush);
707 SetTextColor(hdc, clrText);
708 cdraw->clrText = clrText;
709 break;
710 }
711
712 *theResult = CDRF_NOTIFYPOSTPAINT | TBCDRF_NOBACKGROUND | TBCDRF_NOEDGES | TBCDRF_NOOFFSET | TBCDRF_NOMARK | 0x00800000; // FIXME: the last bit is Vista+, for debugging only
713 return S_OK;
714
715 case CDDS_ITEMPOSTPAINT:
716 btni.cbSize = sizeof(btni);
717 btni.dwMask = TBIF_STYLE;
718 SendMessage(hWnd, TB_GETBUTTONINFO, cdraw->nmcd.dwItemSpec, reinterpret_cast<LPARAM>(&btni));
719 if (btni.fsStyle & BTNS_DROPDOWN)
720 {
721 SelectObject(cdraw->nmcd.hdc, m_marlett);
722 WCHAR text [] = L"8";
723 SetBkMode(cdraw->nmcd.hdc, TRANSPARENT);
724 DrawTextEx(cdraw->nmcd.hdc, text, 1, &cdraw->nmcd.rc, DT_NOCLIP | DT_VCENTER | DT_RIGHT | DT_SINGLELINE, NULL);
725 }
726 *theResult = TRUE;
727 return S_OK;
728 }
729 return S_OK;
730 }
731 return S_OK;
732 }
733
734 return S_FALSE;
735 }
736
737 HRESULT STDMETHODCALLTYPE CMenuBand::IsWindowOwner(HWND hWnd)
738 {
739 if (m_staticToolbar && m_staticToolbar->IsWindowOwner(hWnd) == S_OK)
740 return S_OK;
741
742 if (m_SFToolbar && m_SFToolbar->IsWindowOwner(hWnd) == S_OK)
743 return S_OK;
744
745 return S_FALSE;
746 }
747
748 HRESULT CMenuBand::_CallCBWithItemId(UINT id, UINT uMsg, WPARAM wParam, LPARAM lParam)
749 {
750 return _CallCB(uMsg, wParam, lParam, id);
751 }
752
753 HRESULT CMenuBand::_CallCBWithItemPidl(LPITEMIDLIST pidl, UINT uMsg, WPARAM wParam, LPARAM lParam)
754 {
755 return _CallCB(uMsg, wParam, lParam, 0, pidl);
756 }
757
758 HRESULT CMenuBand::_CallCB(UINT uMsg, WPARAM wParam, LPARAM lParam, UINT id, LPITEMIDLIST pidl)
759 {
760 if (!m_psmc)
761 return S_FALSE;
762
763 HWND hwnd;
764 GetWindow(&hwnd);
765
766 SMDATA smData = { 0 };
767 smData.punk = static_cast<IShellMenu2*>(this);
768 smData.uId = id;
769 smData.uIdParent = m_uId;
770 smData.uIdAncestor = m_uIdAncestor;
771 smData.hwnd = hwnd;
772 smData.pidlItem = pidl;
773 if (m_staticToolbar)
774 {
775 smData.hmenu = m_hmenu;
776 }
777 smData.pvUserData = NULL;
778 if (m_SFToolbar)
779 m_SFToolbar->GetShellFolder(NULL, &smData.pidlFolder, IID_PPV_ARG(IShellFolder, &smData.psf));
780 HRESULT hr = m_psmc->CallbackSM(&smData, uMsg, wParam, lParam);
781 ILFree(smData.pidlFolder);
782 if (smData.psf)
783 smData.psf->Release();
784 return hr;
785 }
786
787 HRESULT CMenuBand::_TrackSubMenuUsingTrackPopupMenu(HMENU popup, INT x, INT y)
788 {
789 ::TrackPopupMenu(popup, 0, x, y, 0, m_menuOwner, NULL);
790 return S_OK;
791 }
792
793 HRESULT CMenuBand::_GetTopLevelWindow(HWND*topLevel)
794 {
795 *topLevel = m_topLevelWindow;
796 return S_OK;
797 }
798
799 HRESULT CMenuBand::_OnHotItemChanged(CMenuToolbarBase * tb, INT id)
800 {
801 if (m_hotBar && m_hotBar != tb)
802 m_hotBar->ChangeHotItem(-1);
803 m_hotBar = tb;
804 m_hotItem = id;
805 if (m_staticToolbar) m_staticToolbar->InvalidateDraw();
806 if (m_SFToolbar) m_SFToolbar->InvalidateDraw();
807 return S_OK;
808 }
809
810 HRESULT CMenuBand::_MenuItemHotTrack(DWORD changeType)
811 {
812 HRESULT hr;
813
814 if (changeType == VK_DOWN)
815 {
816 if (m_SFToolbar && (m_hotBar == m_SFToolbar || m_hotBar == NULL))
817 {
818 hr = m_SFToolbar->ChangeHotItem(VK_DOWN);
819 if (hr == S_FALSE)
820 {
821 if (m_staticToolbar)
822 return m_staticToolbar->ChangeHotItem(VK_HOME);
823 else
824 return m_SFToolbar->ChangeHotItem(VK_HOME);
825 }
826 return hr;
827 }
828 else if (m_staticToolbar && m_hotBar == m_staticToolbar)
829 {
830 hr = m_staticToolbar->ChangeHotItem(VK_DOWN);
831 if (hr == S_FALSE)
832 {
833 if (m_SFToolbar)
834 return m_SFToolbar->ChangeHotItem(VK_HOME);
835 else
836 return m_staticToolbar->ChangeHotItem(VK_HOME);
837 }
838 return hr;
839 }
840 }
841 else if (changeType == VK_UP)
842 {
843 if (m_staticToolbar && (m_hotBar == m_staticToolbar || m_hotBar == NULL))
844 {
845 hr = m_staticToolbar->ChangeHotItem(VK_UP);
846 if (hr == S_FALSE)
847 {
848 if (m_SFToolbar)
849 return m_SFToolbar->ChangeHotItem(VK_END);
850 else
851 return m_staticToolbar->ChangeHotItem(VK_END);
852 }
853 return hr;
854 }
855 else if (m_SFToolbar && m_hotBar == m_SFToolbar)
856 {
857 hr = m_SFToolbar->ChangeHotItem(VK_UP);
858 if (hr == S_FALSE)
859 {
860 if (m_staticToolbar)
861 return m_staticToolbar->ChangeHotItem(VK_END);
862 else
863 return m_SFToolbar->ChangeHotItem(VK_END);
864 }
865 return hr;
866 }
867 }
868 else if (changeType == MPOS_SELECTLEFT)
869 {
870 if (m_subMenuChild)
871 m_subMenuChild->OnSelect(MPOS_CANCELLEVEL);
872 return m_subMenuParent->OnSelect(MPOS_CANCELLEVEL);
873 }
874 else if (changeType == MPOS_SELECTRIGHT)
875 {
876 if (m_hotBar && m_hotItem >= 0)
877 {
878 // TODO: popup the current child if it has subitems, otherwise spread up.
879 if (m_hotBar->HasSubMenu(m_hotItem)==S_OK)
880 {
881 LRESULT result;
882 m_hotBar->PopupItem(m_hotItem);
883 return S_FALSE;
884 }
885 }
886 return m_subMenuParent->OnSelect(changeType);
887 }
888 else
889 {
890 return m_subMenuParent->OnSelect(changeType);
891 }
892 return S_OK;
893 }
894
895 HRESULT CMenuBand::_OnPopupSubMenu(INT popupItem, IMenuPopup * popup, POINTL * pAt, RECTL * pExclude)
896 {
897 if (m_subMenuChild)
898 {
899 HRESULT hr = m_subMenuChild->OnSelect(MPOS_CANCELLEVEL);
900 if (FAILED(hr))
901 return hr;
902 }
903 m_popupItem = popupItem;
904 m_subMenuChild = popup;
905 if (popup)
906 {
907 IUnknown_SetSite(popup, m_subMenuParent);
908 popup->Popup(pAt, pExclude, MPPF_RIGHT);
909 }
910 if (m_staticToolbar) m_staticToolbar->InvalidateDraw();
911 if (m_SFToolbar) m_SFToolbar->InvalidateDraw();
912 return S_OK;
913 }
914
915 HRESULT STDMETHODCALLTYPE CMenuBand::GetSubMenu(THIS)
916 {
917 UNIMPLEMENTED;
918 return S_OK;
919 }
920
921 HRESULT STDMETHODCALLTYPE CMenuBand::SetToolbar(THIS)
922 {
923 UNIMPLEMENTED;
924 return S_OK;
925 }
926
927 HRESULT STDMETHODCALLTYPE CMenuBand::SetMinWidth(THIS)
928 {
929 UNIMPLEMENTED;
930 return S_OK;
931 }
932
933 HRESULT STDMETHODCALLTYPE CMenuBand::SetNoBorder(THIS)
934 {
935 UNIMPLEMENTED;
936 return S_OK;
937 }
938
939 HRESULT STDMETHODCALLTYPE CMenuBand::SetTheme(THIS)
940 {
941 UNIMPLEMENTED;
942 return S_OK;
943 }
944
945 HRESULT STDMETHODCALLTYPE CMenuBand::GetTop(THIS)
946 {
947 UNIMPLEMENTED;
948 return S_OK;
949 }
950
951 HRESULT STDMETHODCALLTYPE CMenuBand::GetBottom(THIS)
952 {
953 UNIMPLEMENTED;
954 return S_OK;
955 }
956
957 HRESULT STDMETHODCALLTYPE CMenuBand::GetTracked(THIS)
958 {
959 UNIMPLEMENTED;
960 return S_OK;
961 }
962
963 HRESULT STDMETHODCALLTYPE CMenuBand::GetParentSite(THIS)
964 {
965 UNIMPLEMENTED;
966 return S_OK;
967 }
968
969 HRESULT STDMETHODCALLTYPE CMenuBand::GetState(THIS)
970 {
971 UNIMPLEMENTED;
972 return S_OK;
973 }
974
975 HRESULT STDMETHODCALLTYPE CMenuBand::DoDefaultAction(THIS)
976 {
977 UNIMPLEMENTED;
978 return S_OK;
979 }
980
981 HRESULT STDMETHODCALLTYPE CMenuBand::IsEmpty(THIS)
982 {
983 UNIMPLEMENTED;
984 return S_OK;
985 }
986
987 HRESULT STDMETHODCALLTYPE CMenuBand::HasFocusIO()
988 {
989 UNIMPLEMENTED;
990 return S_OK;
991 }
992
993 HRESULT STDMETHODCALLTYPE CMenuBand::TranslateAcceleratorIO(LPMSG lpMsg)
994 {
995 UNIMPLEMENTED;
996 return S_OK;
997 }
998
999 HRESULT STDMETHODCALLTYPE CMenuBand::IsDirty()
1000 {
1001 UNIMPLEMENTED;
1002 return S_OK;
1003 }
1004
1005 HRESULT STDMETHODCALLTYPE CMenuBand::Load(IStream *pStm)
1006 {
1007 UNIMPLEMENTED;
1008 return S_OK;
1009 }
1010
1011 HRESULT STDMETHODCALLTYPE CMenuBand::Save(IStream *pStm, BOOL fClearDirty)
1012 {
1013 UNIMPLEMENTED;
1014 return S_OK;
1015 }
1016
1017 HRESULT STDMETHODCALLTYPE CMenuBand::GetSizeMax(ULARGE_INTEGER *pcbSize)
1018 {
1019 UNIMPLEMENTED;
1020 return S_OK;
1021 }
1022
1023 HRESULT STDMETHODCALLTYPE CMenuBand::GetClassID(CLSID *pClassID)
1024 {
1025 UNIMPLEMENTED;
1026 return S_OK;
1027 }
1028
1029 HRESULT STDMETHODCALLTYPE CMenuBand::QueryStatus(const GUID *pguidCmdGroup, ULONG cCmds, OLECMD prgCmds[], OLECMDTEXT *pCmdText)
1030 {
1031 UNIMPLEMENTED;
1032 return S_OK;
1033 }