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 "shellmenu.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 #undef UNIMPLEMENTED
32 
33 #define UNIMPLEMENTED TRACE("%s is UNIMPLEMENTED!\n", __FUNCTION__)
34 
CMenuBand()35 CMenuBand::CMenuBand() :
36     m_staticToolbar(NULL),
37     m_SFToolbar(NULL),
38     m_site(NULL),
39     m_psmc(NULL),
40     m_subMenuChild(NULL),
41     m_subMenuParent(NULL),
42     m_childBand(NULL),
43     m_parentBand(NULL),
44     m_hmenu(NULL),
45     m_menuOwner(NULL),
46     m_useBigIcons(FALSE),
47     m_topLevelWindow(NULL),
48     m_hotBar(NULL),
49     m_hotItem(-1),
50     m_popupBar(NULL),
51     m_popupItem(-1),
52     m_Show(FALSE),
53     m_shellBottom(FALSE),
54     m_trackedPopup(NULL),
55     m_trackedHwnd(NULL)
56 {
57     m_focusManager = CMenuFocusManager::AcquireManager();
58 }
59 
~CMenuBand()60 CMenuBand::~CMenuBand()
61 {
62     CMenuFocusManager::ReleaseManager(m_focusManager);
63 
64     delete m_staticToolbar;
65     delete m_SFToolbar;
66 
67     if (m_hmenu)
68         DestroyMenu(m_hmenu);
69 }
70 
Initialize(IShellMenuCallback * psmc,UINT uId,UINT uIdAncestor,DWORD dwFlags)71 HRESULT STDMETHODCALLTYPE  CMenuBand::Initialize(
72     IShellMenuCallback *psmc,
73     UINT uId,
74     UINT uIdAncestor,
75     DWORD dwFlags)
76 {
77     if (m_psmc != psmc)
78         m_psmc = psmc;
79     m_uId = uId;
80     m_uIdAncestor = uIdAncestor;
81     m_dwFlags = dwFlags;
82 
83     if (m_psmc)
84     {
85         _CallCB(SMC_CREATE, 0, reinterpret_cast<LPARAM>(&m_UserData));
86     }
87 
88     return S_OK;
89 }
90 
GetMenuInfo(IShellMenuCallback ** ppsmc,UINT * puId,UINT * puIdAncestor,DWORD * pdwFlags)91 HRESULT STDMETHODCALLTYPE  CMenuBand::GetMenuInfo(
92     IShellMenuCallback **ppsmc,
93     UINT *puId,
94     UINT *puIdAncestor,
95     DWORD *pdwFlags)
96 {
97     if (!pdwFlags) // maybe?
98         return E_INVALIDARG;
99 
100     if (ppsmc)
101     {
102         *ppsmc = m_psmc;
103         if (*ppsmc)
104             (*ppsmc)->AddRef();
105     }
106 
107     if (puId)
108         *puId = m_uId;
109 
110     if (puIdAncestor)
111         *puIdAncestor = m_uIdAncestor;
112 
113     *pdwFlags = m_dwFlags;
114 
115     return S_OK;
116 }
117 
SetMenu(HMENU hmenu,HWND hwnd,DWORD dwFlags)118 HRESULT STDMETHODCALLTYPE  CMenuBand::SetMenu(
119     HMENU hmenu,
120     HWND hwnd,
121     DWORD dwFlags)
122 {
123     HRESULT hr;
124 
125     TRACE("CMenuBand::SetMenu called, hmenu=%p; hwnd=%p, flags=%x\n", hmenu, hwnd, dwFlags);
126 
127     BOOL created = FALSE;
128 
129     if (m_hmenu && m_hmenu != hmenu)
130     {
131         DestroyMenu(m_hmenu);
132         m_hmenu = NULL;
133     }
134 
135     m_hmenu = hmenu;
136     m_menuOwner = hwnd;
137 
138     if (m_hmenu && m_staticToolbar == NULL)
139     {
140         m_staticToolbar = new CMenuStaticToolbar(this);
141         created = true;
142     }
143 
144     if (m_staticToolbar)
145     {
146         hr = m_staticToolbar->SetMenu(hmenu, hwnd, dwFlags);
147         if (FAILED_UNEXPECTEDLY(hr))
148             return hr;
149     }
150 
151     if (m_site)
152     {
153         HWND hwndParent;
154 
155         hr = m_site->GetWindow(&hwndParent);
156         if (FAILED_UNEXPECTEDLY(hr))
157             return hr;
158 
159         if (created)
160         {
161             hr = m_staticToolbar->CreateToolbar(hwndParent, m_dwFlags);
162             if (FAILED_UNEXPECTEDLY(hr))
163                 return hr;
164 
165             hr = m_staticToolbar->FillToolbar();
166         }
167         else
168         {
169             hr = m_staticToolbar->FillToolbar(TRUE);
170         }
171     }
172 
173     return hr;
174 }
175 
GetMenu(HMENU * phmenu,HWND * phwnd,DWORD * pdwFlags)176 HRESULT STDMETHODCALLTYPE  CMenuBand::GetMenu(
177     HMENU *phmenu,
178     HWND *phwnd,
179     DWORD *pdwFlags)
180 {
181     if (m_staticToolbar == NULL)
182         return E_FAIL;
183 
184     return m_staticToolbar->GetMenu(phmenu, phwnd, pdwFlags);
185 }
186 
SetSite(IUnknown * pUnkSite)187 HRESULT STDMETHODCALLTYPE  CMenuBand::SetSite(IUnknown *pUnkSite)
188 {
189     HWND    hwndParent;
190     HRESULT hr;
191 
192     m_site = NULL;
193 
194     if (pUnkSite == NULL)
195         return S_OK;
196 
197     hwndParent = NULL;
198     hr = pUnkSite->QueryInterface(IID_PPV_ARG(IOleWindow, &m_site));
199     if (FAILED_UNEXPECTEDLY(hr))
200         return hr;
201 
202     hr = m_site->GetWindow(&hwndParent);
203     if (FAILED_UNEXPECTEDLY(hr))
204         return hr;
205 
206     if (!::IsWindow(hwndParent))
207         return E_FAIL;
208 
209     if (m_staticToolbar != NULL)
210     {
211         hr = m_staticToolbar->CreateToolbar(hwndParent, m_dwFlags);
212         if (FAILED_UNEXPECTEDLY(hr))
213             return hr;
214 
215         hr = m_staticToolbar->FillToolbar();
216         if (FAILED_UNEXPECTEDLY(hr))
217             return hr;
218     }
219 
220     if (m_SFToolbar != NULL)
221     {
222         hr = m_SFToolbar->CreateToolbar(hwndParent, m_dwFlags);
223         if (FAILED_UNEXPECTEDLY(hr))
224             return hr;
225 
226         hr = m_SFToolbar->FillToolbar();
227         if (FAILED_UNEXPECTEDLY(hr))
228             return hr;
229     }
230 
231     hr = IUnknown_QueryService(m_site, SID_SMenuPopup, IID_PPV_ARG(IMenuPopup, &m_subMenuParent));
232     if (hr != E_NOINTERFACE && FAILED_UNEXPECTEDLY(hr))
233         return hr;
234 
235     CComPtr<IOleWindow> pTopLevelWindow;
236     hr = IUnknown_QueryService(m_site, SID_STopLevelBrowser, IID_PPV_ARG(IOleWindow, &pTopLevelWindow));
237     if (SUCCEEDED(hr))
238     {
239         hr = pTopLevelWindow->GetWindow(&m_topLevelWindow);
240         if (FAILED_UNEXPECTEDLY(hr))
241             return hr;
242     }
243     else
244     {
245         m_topLevelWindow = hwndParent;
246     }
247 
248     return S_OK;
249 }
250 
GetSite(REFIID riid,PVOID * ppvSite)251 HRESULT STDMETHODCALLTYPE  CMenuBand::GetSite(REFIID riid, PVOID *ppvSite)
252 {
253     if (m_site == NULL)
254         return E_FAIL;
255 
256     return m_site->QueryInterface(riid, ppvSite);
257 }
258 
GetWindow(HWND * phwnd)259 HRESULT STDMETHODCALLTYPE CMenuBand::GetWindow(HWND *phwnd)
260 {
261     if (m_SFToolbar != NULL)
262         return m_SFToolbar->GetWindow(phwnd);
263 
264     if (m_staticToolbar != NULL)
265         return m_staticToolbar->GetWindow(phwnd);
266 
267     if (phwnd) *phwnd = NULL;
268 
269     return E_FAIL;
270 }
271 
OnPosRectChangeDB(RECT * prc)272 HRESULT STDMETHODCALLTYPE CMenuBand::OnPosRectChangeDB(RECT *prc)
273 {
274     SIZE maxStatic = { 0 };
275     SIZE maxShlFld = { 0 };
276     HRESULT hr = S_OK;
277 
278     if (m_staticToolbar != NULL)
279         hr = m_staticToolbar->GetSizes(NULL, &maxStatic, NULL);
280     if (FAILED_UNEXPECTEDLY(hr))
281         return hr;
282 
283     if (m_SFToolbar != NULL)
284         hr = m_SFToolbar->GetSizes(NULL, &maxShlFld, NULL);
285     if (FAILED_UNEXPECTEDLY(hr))
286         return hr;
287 
288     if (m_staticToolbar == NULL && m_SFToolbar == NULL)
289         return E_FAIL;
290 
291     int sy = min(prc->bottom - prc->top, maxStatic.cy + maxShlFld.cy);
292 
293     int syStatic = maxStatic.cy;
294     int syShlFld = sy - syStatic;
295 
296     // TODO: Windows has a more complex system to decide ordering.
297     // Because we only support two toolbars at once, this is enough for us.
298     if (m_shellBottom)
299     {
300         // Static menu on top
301         if (m_SFToolbar)
302         {
303             m_SFToolbar->SetPosSize(
304                 prc->left,
305                 prc->top + syStatic,
306                 prc->right - prc->left,
307                 syShlFld);
308         }
309         if (m_staticToolbar)
310         {
311             m_staticToolbar->SetPosSize(
312                 prc->left,
313                 prc->top,
314                 prc->right - prc->left,
315                 syStatic);
316         }
317     }
318     else
319     {
320         // Folder menu on top
321         if (m_SFToolbar)
322         {
323             m_SFToolbar->SetPosSize(
324                 prc->left,
325                 prc->top,
326                 prc->right - prc->left,
327                 syShlFld);
328         }
329         if (m_staticToolbar)
330         {
331             m_staticToolbar->SetPosSize(
332                 prc->left,
333                 prc->top + syShlFld,
334                 prc->right - prc->left,
335                 syStatic);
336         }
337     }
338 
339     return S_OK;
340 }
341 
GetBandInfo(DWORD dwBandID,DWORD dwViewMode,DESKBANDINFO * pdbi)342 HRESULT STDMETHODCALLTYPE  CMenuBand::GetBandInfo(
343     DWORD dwBandID,
344     DWORD dwViewMode,
345     DESKBANDINFO *pdbi)
346 {
347     SIZE minStatic = { 0 };
348     SIZE minShlFld = { 0 };
349     SIZE maxStatic = { 0 };
350     SIZE maxShlFld = { 0 };
351     SIZE intStatic = { 0 };
352     SIZE intShlFld = { 0 };
353 
354     HRESULT hr = S_OK;
355 
356     if (m_staticToolbar != NULL)
357         hr = m_staticToolbar->GetSizes(&minStatic, &maxStatic, &intStatic);
358     if (FAILED_UNEXPECTEDLY(hr))
359         return hr;
360 
361     if (m_SFToolbar != NULL)
362         hr = m_SFToolbar->GetSizes(&minShlFld, &maxShlFld, &intShlFld);
363     if (FAILED_UNEXPECTEDLY(hr))
364         return hr;
365 
366     if (m_staticToolbar == NULL && m_SFToolbar == NULL)
367         return E_FAIL;
368 
369     if (m_dwFlags & SMINIT_VERTICAL)
370     {
371         pdbi->ptMinSize.x = max(minStatic.cx, minShlFld.cx) + 20;
372         pdbi->ptMinSize.y = minStatic.cy + minShlFld.cy;
373         pdbi->ptMaxSize.x = max(maxStatic.cx, maxShlFld.cx) + 20;
374         pdbi->ptMaxSize.y = maxStatic.cy + maxShlFld.cy;
375         pdbi->dwModeFlags = DBIMF_VARIABLEHEIGHT;
376     }
377     else
378     {
379         pdbi->ptMinSize.x = minStatic.cx + minShlFld.cx;
380         pdbi->ptMinSize.y = max(minStatic.cy, minShlFld.cy);
381         pdbi->ptMaxSize.x = maxStatic.cx + maxShlFld.cx;
382         pdbi->ptMaxSize.y = max(maxStatic.cy, maxShlFld.cy);
383     }
384     pdbi->ptIntegral.x = max(intStatic.cx, intShlFld.cx);
385     pdbi->ptIntegral.y = max(intStatic.cy, intShlFld.cy);
386     pdbi->ptActual = pdbi->ptMinSize;
387 
388     return S_OK;
389 }
390 
ShowDW(BOOL fShow)391 HRESULT STDMETHODCALLTYPE  CMenuBand::ShowDW(BOOL fShow)
392 {
393     HRESULT hr = S_OK;
394 
395     if (m_Show == fShow)
396         return S_OK;
397 
398     m_Show = fShow;
399 
400     if (m_staticToolbar != NULL)
401     {
402         hr = m_staticToolbar->ShowDW(fShow);
403         if (FAILED_UNEXPECTEDLY(hr))
404             return hr;
405     }
406 
407     if (m_SFToolbar != NULL)
408     {
409         hr = m_SFToolbar->ShowDW(fShow);
410         if (FAILED_UNEXPECTEDLY(hr))
411             return hr;
412     }
413 
414     if (fShow)
415     {
416         hr = _CallCB(SMC_INITMENU, 0, 0);
417         if (FAILED_UNEXPECTEDLY(hr))
418             return hr;
419     }
420     else if (m_parentBand)
421     {
422         m_parentBand->SetClient(NULL);
423     }
424 
425     if (_IsPopup() == S_OK)
426     {
427         if (fShow)
428             hr = m_focusManager->PushMenuPopup(this);
429         else
430             hr = m_focusManager->PopMenuPopup(this);
431     }
432     else
433     {
434         if (fShow)
435             hr = m_focusManager->PushMenuBar(this);
436         else
437             hr = m_focusManager->PopMenuBar(this);
438     }
439 
440     return S_OK;
441 }
442 
CloseDW(DWORD dwReserved)443 HRESULT STDMETHODCALLTYPE CMenuBand::CloseDW(DWORD dwReserved)
444 {
445     if (m_subMenuChild)
446     {
447         m_subMenuChild->OnSelect(MPOS_CANCELLEVEL);
448     }
449 
450     if (m_subMenuChild)
451     {
452         TRACE("Child object should have removed itself.\n");
453     }
454 
455     ShowDW(FALSE);
456 
457     if (m_staticToolbar != NULL)
458     {
459         m_staticToolbar->Close();
460     }
461 
462     if (m_SFToolbar != NULL)
463     {
464         m_SFToolbar->Close();
465     }
466 
467     if (m_site) m_site.Release();
468     if (m_subMenuChild) m_subMenuChild.Release();
469     if (m_subMenuParent) m_subMenuParent.Release();
470     if (m_childBand) m_childBand.Release();
471     if (m_parentBand) m_parentBand.Release();
472 
473     return S_OK;
474 }
475 
UIActivateIO(BOOL fActivate,LPMSG lpMsg)476 HRESULT STDMETHODCALLTYPE CMenuBand::UIActivateIO(BOOL fActivate, LPMSG lpMsg)
477 {
478     HRESULT hr;
479 
480     if (m_subMenuParent)
481     {
482         hr = m_subMenuParent->SetSubMenu(this, fActivate);
483         if (FAILED_UNEXPECTEDLY(hr))
484             return hr;
485     }
486 
487     if (fActivate)
488     {
489         CComPtr<IOleWindow> pTopLevelWindow;
490         hr = IUnknown_QueryService(m_site, SID_SMenuPopup, IID_PPV_ARG(IOleWindow, &pTopLevelWindow));
491         if (FAILED_UNEXPECTEDLY(hr))
492             return hr;
493 
494         hr = pTopLevelWindow->GetWindow(&m_topLevelWindow);
495         if (FAILED_UNEXPECTEDLY(hr))
496             return hr;
497     }
498     else
499     {
500         m_topLevelWindow = NULL;
501     }
502 
503     return S_FALSE;
504 }
505 
Exec(const GUID * pguidCmdGroup,DWORD nCmdID,DWORD nCmdexecopt,VARIANT * pvaIn,VARIANT * pvaOut)506 HRESULT STDMETHODCALLTYPE CMenuBand::Exec(const GUID *pguidCmdGroup, DWORD nCmdID, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
507 {
508     if (!pguidCmdGroup)
509         return E_FAIL;
510 
511     if (IsEqualGUID(*pguidCmdGroup, CLSID_MenuBand))
512     {
513         if (nCmdID == 16) // set (big) icon size
514         {
515             this->m_useBigIcons = nCmdexecopt == 2;
516             return S_OK;
517         }
518         else if (nCmdID == 19) // popup-related
519         {
520             return S_FALSE;
521         }
522         else if (nCmdID == 5) // select an item
523         {
524             if (nCmdexecopt == 0) // first
525             {
526                 _KeyboardItemChange(VK_HOME);
527             }
528             else // last
529             {
530                 _KeyboardItemChange(VK_END);
531             }
532             return S_FALSE;
533         }
534 
535         return S_FALSE;
536     }
537 
538     UNIMPLEMENTED;
539     return S_OK;
540 }
541 
QueryService(REFGUID guidService,REFIID riid,void ** ppvObject)542 HRESULT STDMETHODCALLTYPE CMenuBand::QueryService(REFGUID guidService, REFIID riid, void **ppvObject)
543 {
544     if (IsEqualIID(guidService, SID_SMenuBandChild) ||
545         IsEqualIID(guidService, SID_SMenuBandBottom) ||
546         IsEqualIID(guidService, SID_SMenuBandBottomSelected))
547         return this->QueryInterface(riid, ppvObject);
548     WARN("Unknown service requested %s\n", wine_dbgstr_guid(&guidService));
549     return E_NOINTERFACE;
550 }
551 
Popup(POINTL * ppt,RECTL * prcExclude,MP_POPUPFLAGS dwFlags)552 HRESULT STDMETHODCALLTYPE CMenuBand::Popup(POINTL *ppt, RECTL *prcExclude, MP_POPUPFLAGS dwFlags)
553 {
554     UNIMPLEMENTED;
555     return S_OK;
556 }
557 
OnSelect(DWORD dwSelectType)558 HRESULT STDMETHODCALLTYPE CMenuBand::OnSelect(DWORD dwSelectType)
559 {
560     // When called from outside, this is straightforward:
561     // Things that a submenu needs to know, are spread down, and
562     // things that the parent needs to know, are spread up. No drama.
563     // The fun is in _MenuItemSelect (internal method).
564     switch (dwSelectType)
565     {
566     case MPOS_CHILDTRACKING:
567         if (!m_subMenuParent)
568             break;
569         // TODO: Cancel timers?
570         return m_subMenuParent->OnSelect(dwSelectType);
571     case MPOS_SELECTLEFT:
572         if (m_subMenuChild)
573             m_subMenuChild->OnSelect(MPOS_CANCELLEVEL);
574         if (!m_subMenuParent)
575             break;
576         return m_subMenuParent->OnSelect(dwSelectType);
577     case MPOS_SELECTRIGHT:
578         if (!m_subMenuParent)
579             break;
580         return m_subMenuParent->OnSelect(dwSelectType);
581     case MPOS_EXECUTE:
582     case MPOS_FULLCANCEL:
583         if (m_subMenuChild)
584             m_subMenuChild->OnSelect(dwSelectType);
585         if (!m_subMenuParent)
586             break;
587         return m_subMenuParent->OnSelect(dwSelectType);
588     case MPOS_CANCELLEVEL:
589         if (m_subMenuChild)
590             m_subMenuChild->OnSelect(dwSelectType);
591         break;
592     }
593     return S_FALSE;
594 }
595 
SetSubMenu(IMenuPopup * pmp,BOOL fSet)596 HRESULT STDMETHODCALLTYPE CMenuBand::SetSubMenu(IMenuPopup *pmp, BOOL fSet)
597 {
598     UNIMPLEMENTED;
599     return S_OK;
600 }
601 
602 // Used by the focus manager to update the child band pointer
_SetChildBand(CMenuBand * child)603 HRESULT CMenuBand::_SetChildBand(CMenuBand * child)
604 {
605     m_childBand = child;
606     if (!child)
607     {
608         _ChangePopupItem(NULL, -1);
609     }
610     return S_OK;
611 }
612 
613 // User by the focus manager to update the parent band pointer
_SetParentBand(CMenuBand * parent)614 HRESULT CMenuBand::_SetParentBand(CMenuBand * parent)
615 {
616     m_parentBand = parent;
617     return S_OK;
618 }
619 
_IsPopup()620 HRESULT CMenuBand::_IsPopup()
621 {
622     return !(m_dwFlags & SMINIT_VERTICAL);
623 }
624 
_IsTracking()625 HRESULT CMenuBand::_IsTracking()
626 {
627     return m_popupBar != NULL;
628 }
629 
SetClient(IUnknown * punkClient)630 HRESULT STDMETHODCALLTYPE CMenuBand::SetClient(IUnknown *punkClient)
631 {
632     CComPtr<IMenuPopup> child = m_subMenuChild;
633 
634     m_subMenuChild = NULL;
635 
636     if (child)
637     {
638         IUnknown_SetSite(child, NULL);
639         child.Release();
640     }
641 
642     if (!punkClient)
643     {
644         return S_OK;
645     }
646 
647     return punkClient->QueryInterface(IID_PPV_ARG(IMenuPopup, &m_subMenuChild));
648 }
649 
GetClient(IUnknown ** ppunkClient)650 HRESULT STDMETHODCALLTYPE CMenuBand::GetClient(IUnknown **ppunkClient)
651 {
652     if (!ppunkClient)
653         return E_POINTER;
654     *ppunkClient = NULL;
655 
656     if (m_subMenuChild)
657     {
658         *ppunkClient = m_subMenuChild;
659         (*ppunkClient)->AddRef();
660     }
661 
662     return S_OK;
663 }
664 
IsMenuMessage(MSG * pmsg)665 HRESULT STDMETHODCALLTYPE CMenuBand::IsMenuMessage(MSG *pmsg)
666 {
667     return S_FALSE;
668 }
669 
TranslateMenuMessage(MSG * pmsg,LRESULT * plRet)670 HRESULT STDMETHODCALLTYPE CMenuBand::TranslateMenuMessage(MSG *pmsg, LRESULT *plRet)
671 {
672     if (pmsg->message == WM_ACTIVATE && _IsPopup() == S_FALSE)
673     {
674         if (m_staticToolbar)
675             m_staticToolbar->Invalidate();
676         if (m_SFToolbar)
677             m_SFToolbar->Invalidate();
678     }
679 
680     return S_FALSE;
681 }
682 
SetShellFolder(IShellFolder * psf,LPCITEMIDLIST pidlFolder,HKEY hKey,DWORD dwFlags)683 HRESULT STDMETHODCALLTYPE CMenuBand::SetShellFolder(IShellFolder *psf, LPCITEMIDLIST pidlFolder, HKEY hKey, DWORD dwFlags)
684 {
685     if (!psf)
686         return E_INVALIDARG;
687 
688     if (m_SFToolbar == NULL)
689     {
690         m_SFToolbar = new CMenuSFToolbar(this);
691     }
692 
693     HRESULT hr = m_SFToolbar->SetShellFolder(psf, pidlFolder, hKey, dwFlags);
694     if (FAILED_UNEXPECTEDLY(hr))
695         return hr;
696 
697     m_shellBottom = (dwFlags & SMSET_BOTTOM) != 0;
698 
699     if (m_site)
700     {
701         HWND hwndParent;
702 
703         hr = m_site->GetWindow(&hwndParent);
704         if (FAILED_UNEXPECTEDLY(hr))
705             return hr;
706 
707         hr = m_SFToolbar->CreateToolbar(hwndParent, m_dwFlags);
708         if (FAILED_UNEXPECTEDLY(hr))
709             return hr;
710 
711         hr = m_SFToolbar->FillToolbar();
712     }
713 
714     return hr;
715 }
716 
GetShellFolder(DWORD * pdwFlags,LPITEMIDLIST * ppidl,REFIID riid,void ** ppv)717 HRESULT STDMETHODCALLTYPE CMenuBand::GetShellFolder(DWORD *pdwFlags, LPITEMIDLIST *ppidl, REFIID riid, void **ppv)
718 {
719     if (m_SFToolbar)
720         return m_SFToolbar->GetShellFolder(pdwFlags, ppidl, riid, ppv);
721     return E_FAIL;
722 }
723 
OnWinEvent(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam,LRESULT * theResult)724 HRESULT STDMETHODCALLTYPE CMenuBand::OnWinEvent(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT *theResult)
725 {
726     if (theResult)
727         *theResult = 0;
728 
729     if (uMsg == WM_WININICHANGE && wParam == SPI_SETFLATMENU)
730     {
731         BOOL bFlatMenus;
732         SystemParametersInfo(SPI_GETFLATMENU, 0, &bFlatMenus, 0);
733         AdjustForTheme(bFlatMenus);
734 
735         if (m_staticToolbar)
736             m_staticToolbar->OnWinEvent(hWnd, uMsg, wParam, lParam, theResult);
737 
738         if (m_SFToolbar)
739             m_SFToolbar->OnWinEvent(hWnd, uMsg, wParam, lParam, theResult);
740 
741         return S_OK;
742     }
743 
744     if (m_staticToolbar && m_staticToolbar->IsWindowOwner(hWnd) == S_OK)
745     {
746         return m_staticToolbar->OnWinEvent(hWnd, uMsg, wParam, lParam, theResult);
747     }
748 
749     if (m_SFToolbar && m_SFToolbar->IsWindowOwner(hWnd) == S_OK)
750     {
751         return m_SFToolbar->OnWinEvent(hWnd, uMsg, wParam, lParam, theResult);
752     }
753 
754     return S_FALSE;
755 }
756 
IsWindowOwner(HWND hWnd)757 HRESULT STDMETHODCALLTYPE CMenuBand::IsWindowOwner(HWND hWnd)
758 {
759     if (m_staticToolbar && m_staticToolbar->IsWindowOwner(hWnd) == S_OK)
760         return S_OK;
761 
762     if (m_SFToolbar && m_SFToolbar->IsWindowOwner(hWnd) == S_OK)
763         return S_OK;
764 
765     return S_FALSE;
766 }
767 
_CallCBWithItemId(UINT id,UINT uMsg,WPARAM wParam,LPARAM lParam)768 HRESULT CMenuBand::_CallCBWithItemId(UINT id, UINT uMsg, WPARAM wParam, LPARAM lParam)
769 {
770     return _CallCB(uMsg, wParam, lParam, id);
771 }
772 
_CallCBWithItemPidl(LPITEMIDLIST pidl,UINT uMsg,WPARAM wParam,LPARAM lParam)773 HRESULT CMenuBand::_CallCBWithItemPidl(LPITEMIDLIST pidl, UINT uMsg, WPARAM wParam, LPARAM lParam)
774 {
775     return _CallCB(uMsg, wParam, lParam, 0, pidl);
776 }
777 
_CallCB(UINT uMsg,WPARAM wParam,LPARAM lParam,UINT id,LPITEMIDLIST pidl)778 HRESULT CMenuBand::_CallCB(UINT uMsg, WPARAM wParam, LPARAM lParam, UINT id, LPITEMIDLIST pidl)
779 {
780     if (!m_psmc)
781         return S_FALSE;
782 
783     SMDATA smData = { 0 };
784     smData.punk = static_cast<IShellMenu2*>(this);
785     smData.uId = id;
786     smData.uIdParent = m_uId;
787     smData.uIdAncestor = m_uIdAncestor;
788     smData.pidlItem = pidl;
789     smData.hwnd = m_menuOwner ? m_menuOwner : m_topLevelWindow;
790     smData.hmenu = m_hmenu;
791     if (m_SFToolbar)
792         m_SFToolbar->GetShellFolder(NULL, &smData.pidlFolder, IID_PPV_ARG(IShellFolder, &smData.psf));
793     HRESULT hr = m_psmc->CallbackSM(&smData, uMsg, wParam, lParam);
794     ILFree(smData.pidlFolder);
795     if (smData.psf)
796         smData.psf->Release();
797     return hr;
798 }
799 
_TrackSubMenu(HMENU popup,INT x,INT y,RECT & rcExclude)800 HRESULT CMenuBand::_TrackSubMenu(HMENU popup, INT x, INT y, RECT& rcExclude)
801 {
802     TPMPARAMS params = { sizeof(TPMPARAMS), rcExclude };
803     UINT      flags  = TPM_VERPOSANIMATION | TPM_VERTICAL | TPM_LEFTALIGN;
804     HWND      hwnd   = m_menuOwner ? m_menuOwner : m_topLevelWindow;
805 
806     m_trackedPopup = popup;
807     m_trackedHwnd = hwnd;
808 
809     m_focusManager->PushTrackedPopup(popup);
810     ::TrackPopupMenuEx(popup, flags, x, y, hwnd, &params);
811     m_focusManager->PopTrackedPopup(popup);
812 
813     m_trackedPopup = NULL;
814     m_trackedHwnd = NULL;
815 
816     _DisableMouseTrack(FALSE);
817 
818     return S_OK;
819 }
820 
_TrackContextMenu(IContextMenu * contextMenu,INT x,INT y)821 HRESULT CMenuBand::_TrackContextMenu(IContextMenu * contextMenu, INT x, INT y)
822 {
823     HRESULT hr;
824     UINT uCommand;
825 
826     // Ensure that the menu doesn't disappear on us
827     CComPtr<IContextMenu> ctxMenu = contextMenu;
828 
829     HMENU popup = CreatePopupMenu();
830 
831     if (popup == NULL)
832         return E_FAIL;
833 
834     TRACE("Before Query\n");
835     UINT cmf = CMF_NORMAL;
836     if (GetKeyState(VK_SHIFT) < 0)
837         cmf |= CMF_EXTENDEDVERBS;
838 
839     const UINT idCmdFirst = 100, idCmdLast = 0xffff;
840     hr = contextMenu->QueryContextMenu(popup, 0, idCmdFirst, idCmdLast, cmf);
841     if (FAILED_UNEXPECTEDLY(hr))
842     {
843         TRACE("Query failed\n");
844         DestroyMenu(popup);
845         return hr;
846     }
847 
848     HWND hwnd = m_menuOwner ? m_menuOwner : m_topLevelWindow;
849 
850     m_focusManager->PushTrackedPopup(popup);
851 
852     TRACE("Before Tracking\n");
853     uCommand = ::TrackPopupMenuEx(popup, TPM_RETURNCMD, x, y, hwnd, NULL);
854 
855     m_focusManager->PopTrackedPopup(popup);
856 
857     if (uCommand != 0)
858     {
859         _MenuItemSelect(MPOS_FULLCANCEL);
860 
861         TRACE("Before InvokeCommand\n");
862         CMINVOKECOMMANDINFO cmi = { sizeof(cmi), 0, hwnd };
863         cmi.lpVerb = MAKEINTRESOURCEA(uCommand - idCmdFirst);
864         if (GetKeyState(VK_SHIFT) < 0)
865             cmi.fMask |= CMIC_MASK_SHIFT_DOWN;
866         if (GetKeyState(VK_CONTROL) < 0)
867             cmi.fMask |= CMIC_MASK_CONTROL_DOWN;
868         hr = contextMenu->InvokeCommand(&cmi);
869         TRACE("InvokeCommand returned hr=%08x\n", hr);
870     }
871     else
872     {
873         TRACE("TrackPopupMenu failed. Code=%d, LastError=%d\n", uCommand, GetLastError());
874         hr = S_FALSE;
875     }
876 
877     DestroyMenu(popup);
878     return hr;
879 }
880 
_GetTopLevelWindow(HWND * topLevel)881 HRESULT CMenuBand::_GetTopLevelWindow(HWND*topLevel)
882 {
883     *topLevel = m_topLevelWindow;
884     return S_OK;
885 }
886 
_ChangeHotItem(CMenuToolbarBase * tb,INT id,DWORD dwFlags)887 HRESULT CMenuBand::_ChangeHotItem(CMenuToolbarBase * tb, INT id, DWORD dwFlags)
888 {
889     if (m_hotBar == tb && m_hotItem == id)
890         return S_FALSE;
891 
892     TRACE("Hot item changed from %p %p, to %p %p\n", m_hotBar, m_hotItem, tb, id);
893 
894     _KillPopupTimers();
895 
896     m_hotBar = tb;
897     m_hotItem = id;
898     if (m_staticToolbar) m_staticToolbar->ChangeHotItem(tb, id, dwFlags);
899     if (m_SFToolbar) m_SFToolbar->ChangeHotItem(tb, id, dwFlags);
900 
901     _MenuItemSelect(MPOS_CHILDTRACKING);
902 
903     return S_OK;
904 }
905 
_ChangePopupItem(CMenuToolbarBase * tb,INT id)906 HRESULT CMenuBand::_ChangePopupItem(CMenuToolbarBase * tb, INT id)
907 {
908     TRACE("Popup item changed from %p %p, to %p %p\n", m_popupBar, m_popupItem, tb, id);
909 
910     m_popupBar = tb;
911     m_popupItem = id;
912     if (m_staticToolbar) m_staticToolbar->ChangePopupItem(tb, id);
913     if (m_SFToolbar) m_SFToolbar->ChangePopupItem(tb, id);
914 
915     return S_OK;
916 }
917 
_KeyboardItemChange(DWORD change)918 HRESULT  CMenuBand::_KeyboardItemChange(DWORD change)
919 {
920     HRESULT hr;
921     CMenuToolbarBase *tb = m_hotBar;
922 
923     if (!tb)
924     {
925         // If no hot item was selected choose the appropriate toolbar
926         if (change == VK_UP || change == VK_END)
927         {
928             if (m_staticToolbar)
929                 tb = m_staticToolbar;
930             else
931                 tb = m_SFToolbar;
932         }
933         else if (change == VK_DOWN || change == VK_HOME)
934         {
935             if (m_SFToolbar)
936                 tb = m_SFToolbar;
937             else
938                 tb = m_staticToolbar;
939         }
940     }
941 
942     // Ask the first toolbar to change
943     hr = tb->KeyboardItemChange(change);
944 
945     if (hr != S_FALSE)
946         return hr;
947 
948     // Select the second toolbar based on the first
949     if (tb == m_SFToolbar && m_staticToolbar)
950         tb = m_staticToolbar;
951     else if (m_SFToolbar)
952         tb = m_SFToolbar;
953 
954     if (!tb)
955         return hr;
956 
957     // Ask the second toolbar to change
958     return tb->KeyboardItemChange(change == VK_DOWN ? VK_HOME : VK_END);
959 }
960 
_MenuItemSelect(DWORD changeType)961 HRESULT CMenuBand::_MenuItemSelect(DWORD changeType)
962 {
963     // Needed to prevent the this point from vanishing mid-function
964     CComPtr<CMenuBand> safeThis = this;
965     HRESULT hr;
966 
967     if (m_dwFlags & SMINIT_VERTICAL)
968     {
969         switch (changeType)
970         {
971         case VK_UP:
972         case VK_DOWN:
973             return _KeyboardItemChange(changeType);
974 
975             // TODO: Left/Right across multi-column menus, if they ever work.
976         case VK_LEFT:
977             changeType = MPOS_SELECTLEFT;
978             break;
979         case VK_RIGHT:
980             changeType = MPOS_SELECTRIGHT;
981             break;
982         }
983     }
984     else
985     {
986         // In horizontal menubars, left/right are equivalent to vertical's up/down
987         switch (changeType)
988         {
989         case VK_LEFT:
990             hr = _KeyboardItemChange(VK_UP);
991             if (hr != S_FALSE)
992                 return hr;
993         case VK_RIGHT:
994             hr = _KeyboardItemChange(VK_DOWN);
995             if (hr != S_FALSE)
996                 return hr;
997         }
998     }
999 
1000     // In this context, the parent is the CMenuDeskBar, so when it bubbles upward,
1001     // it is notifying the deskbar, and not the the higher-level menu.
1002     // Same for the child: since it points to a CMenuDeskBar, it's not just recursing.
1003     switch (changeType)
1004     {
1005     case MPOS_EXECUTE:
1006     {
1007         CMenuToolbarBase * tb = m_hotBar;
1008         int item = m_hotItem;
1009         tb->PrepareExecuteItem(item);
1010         if (m_subMenuParent)
1011         {
1012             m_subMenuParent->OnSelect(changeType);
1013         }
1014         TRACE("Menu closed, executing item...\n");
1015         tb->ExecuteItem();
1016         break;
1017     }
1018     case MPOS_SELECTLEFT:
1019         if (m_parentBand && m_parentBand->_IsPopup()==S_FALSE)
1020             return m_parentBand->_MenuItemSelect(VK_LEFT);
1021         if (m_subMenuChild)
1022             return m_subMenuChild->OnSelect(MPOS_CANCELLEVEL);
1023         if (!m_subMenuParent)
1024             return S_OK;
1025         return m_subMenuParent->OnSelect(MPOS_CANCELLEVEL);
1026 
1027     case MPOS_SELECTRIGHT:
1028         if (m_hotBar && m_hotItem >= 0 && m_hotBar->PopupItem(m_hotItem, TRUE) == S_OK)
1029             return S_FALSE;
1030         if (m_parentBand)
1031             return m_parentBand->_MenuItemSelect(VK_RIGHT);
1032         if (!m_subMenuParent)
1033             return S_OK;
1034         return m_subMenuParent->OnSelect(MPOS_SELECTRIGHT);
1035 
1036     default:
1037         if (!m_subMenuParent)
1038             return S_OK;
1039         return m_subMenuParent->OnSelect(changeType);
1040     }
1041 
1042     return S_OK;
1043 }
1044 
_CancelCurrentPopup()1045 HRESULT CMenuBand::_CancelCurrentPopup()
1046 {
1047     if (m_subMenuChild)
1048     {
1049         HRESULT hr = m_subMenuChild->OnSelect(MPOS_CANCELLEVEL);
1050         return hr;
1051     }
1052 
1053     if (m_trackedPopup)
1054     {
1055         ::SendMessage(m_trackedHwnd, WM_CANCELMODE, 0, 0);
1056         return S_OK;
1057     }
1058 
1059     return S_FALSE;
1060 }
1061 
_OnPopupSubMenu(IShellMenu * childShellMenu,POINTL * pAt,RECTL * pExclude,BOOL keyInitiated)1062 HRESULT CMenuBand::_OnPopupSubMenu(IShellMenu * childShellMenu, POINTL * pAt, RECTL * pExclude, BOOL keyInitiated)
1063 {
1064     HRESULT hr = 0;
1065     CComPtr<IBandSite> pBandSite;
1066     CComPtr<IDeskBar> pDeskBar;
1067 
1068     // Create the necessary objects
1069     hr = CMenuSite_CreateInstance(IID_PPV_ARG(IBandSite, &pBandSite));
1070     if (FAILED_UNEXPECTEDLY(hr))
1071         return hr;
1072 
1073     hr = CMenuDeskBar_CreateInstance(IID_PPV_ARG(IDeskBar, &pDeskBar));
1074     if (FAILED_UNEXPECTEDLY(hr))
1075         return hr;
1076 
1077     hr = pDeskBar->SetClient(pBandSite);
1078     if (FAILED_UNEXPECTEDLY(hr))
1079         return hr;
1080 
1081     hr = pBandSite->AddBand(childShellMenu);
1082     if (FAILED_UNEXPECTEDLY(hr))
1083         return hr;
1084 
1085     //
1086     CComPtr<IMenuPopup> popup;
1087     hr = pDeskBar->QueryInterface(IID_PPV_ARG(IMenuPopup, &popup));
1088     if (FAILED_UNEXPECTEDLY(hr))
1089         return hr;
1090 
1091     m_subMenuChild = popup;
1092 
1093     if (m_subMenuParent)
1094         IUnknown_SetSite(popup, m_subMenuParent);
1095     else
1096         IUnknown_SetSite(popup, m_site);
1097 
1098     DWORD flags = MPPF_RIGHT;
1099 
1100     if (keyInitiated && m_dwFlags & SMINIT_VERTICAL)
1101         flags |= MPPF_INITIALSELECT;
1102 
1103     popup->Popup(pAt, pExclude, flags);
1104 
1105     return S_OK;
1106 }
1107 
_BeforeCancelPopup()1108 HRESULT CMenuBand::_BeforeCancelPopup()
1109 {
1110     if (m_staticToolbar)
1111         m_staticToolbar->BeforeCancelPopup();
1112     if (m_SFToolbar)
1113         m_SFToolbar->BeforeCancelPopup();
1114     return S_OK;
1115 }
1116 
_DisableMouseTrack(BOOL bDisable)1117 HRESULT CMenuBand::_DisableMouseTrack(BOOL bDisable)
1118 {
1119     if (m_staticToolbar)
1120         m_staticToolbar->DisableMouseTrack(bDisable);
1121     if (m_SFToolbar)
1122         m_SFToolbar->DisableMouseTrack(bDisable);
1123     return S_OK;
1124 }
1125 
_KillPopupTimers()1126 HRESULT CMenuBand::_KillPopupTimers()
1127 {
1128     HRESULT hr = S_OK;
1129     if (m_staticToolbar)
1130         hr = m_staticToolbar->KillPopupTimer();
1131     if (FAILED(hr))
1132         return hr;
1133 
1134     if (m_SFToolbar)
1135         hr = m_SFToolbar->KillPopupTimer();
1136 
1137     return hr;
1138 }
1139 
_MenuBarMouseDown(HWND hwnd,INT item,BOOL isLButton)1140 HRESULT CMenuBand::_MenuBarMouseDown(HWND hwnd, INT item, BOOL isLButton)
1141 {
1142     if (m_staticToolbar && m_staticToolbar->IsWindowOwner(hwnd) == S_OK)
1143         m_staticToolbar->MenuBarMouseDown(item, isLButton);
1144     if (m_SFToolbar && m_SFToolbar->IsWindowOwner(hwnd) == S_OK)
1145         m_SFToolbar->MenuBarMouseDown(item, isLButton);
1146     return S_OK;
1147 }
1148 
_MenuBarMouseUp(HWND hwnd,INT item,BOOL isLButton)1149 HRESULT CMenuBand::_MenuBarMouseUp(HWND hwnd, INT item, BOOL isLButton)
1150 {
1151     if (m_staticToolbar && m_staticToolbar->IsWindowOwner(hwnd) == S_OK)
1152         m_staticToolbar->MenuBarMouseUp(item, isLButton);
1153     if (m_SFToolbar && m_SFToolbar->IsWindowOwner(hwnd) == S_OK)
1154         m_SFToolbar->MenuBarMouseUp(item, isLButton);
1155     return S_OK;
1156 }
1157 
_HasSubMenu()1158 HRESULT CMenuBand::_HasSubMenu()
1159 {
1160     return m_popupBar ? S_OK : S_FALSE;
1161 }
1162 
AdjustForTheme(BOOL bFlatStyle)1163 HRESULT CMenuBand::AdjustForTheme(BOOL bFlatStyle)
1164 {
1165     return IUnknown_QueryServiceExec(m_site, SID_SMenuPopup, &CGID_MenuDeskBar, 4, bFlatStyle, NULL, NULL);
1166 }
1167 
InvalidateItem(LPSMDATA psmd,DWORD dwFlags)1168 HRESULT STDMETHODCALLTYPE CMenuBand::InvalidateItem(LPSMDATA psmd, DWORD dwFlags)
1169 {
1170     UNIMPLEMENTED;
1171     return S_OK;
1172 }
1173 
GetState(LPSMDATA psmd)1174 HRESULT STDMETHODCALLTYPE CMenuBand::GetState(LPSMDATA psmd)
1175 {
1176     UNIMPLEMENTED;
1177     return S_OK;
1178 }
1179 
SetMenuToolbar(IUnknown * punk,DWORD dwFlags)1180 HRESULT STDMETHODCALLTYPE CMenuBand::SetMenuToolbar(IUnknown *punk, DWORD dwFlags)
1181 {
1182     UNIMPLEMENTED;
1183     return S_OK;
1184 }
1185 
ResizeBorderDW(LPCRECT prcBorder,IUnknown * punkToolbarSite,BOOL fReserved)1186 HRESULT STDMETHODCALLTYPE CMenuBand::ResizeBorderDW(LPCRECT prcBorder, IUnknown *punkToolbarSite, BOOL fReserved)
1187 {
1188     UNIMPLEMENTED;
1189     return S_OK;
1190 }
1191 
ContextSensitiveHelp(BOOL fEnterMode)1192 HRESULT STDMETHODCALLTYPE CMenuBand::ContextSensitiveHelp(BOOL fEnterMode)
1193 {
1194     UNIMPLEMENTED;
1195     return S_OK;
1196 }
1197 
GetSubMenu(THIS)1198 HRESULT STDMETHODCALLTYPE CMenuBand::GetSubMenu(THIS)
1199 {
1200     UNIMPLEMENTED;
1201     return S_OK;
1202 }
1203 
SetToolbar(THIS)1204 HRESULT STDMETHODCALLTYPE CMenuBand::SetToolbar(THIS)
1205 {
1206     UNIMPLEMENTED;
1207     return S_OK;
1208 }
1209 
SetMinWidth(THIS)1210 HRESULT STDMETHODCALLTYPE CMenuBand::SetMinWidth(THIS)
1211 {
1212     UNIMPLEMENTED;
1213     return S_OK;
1214 }
1215 
SetNoBorder(THIS)1216 HRESULT STDMETHODCALLTYPE CMenuBand::SetNoBorder(THIS)
1217 {
1218     UNIMPLEMENTED;
1219     return S_OK;
1220 }
1221 
SetTheme(THIS)1222 HRESULT STDMETHODCALLTYPE CMenuBand::SetTheme(THIS)
1223 {
1224     UNIMPLEMENTED;
1225     return S_OK;
1226 }
1227 
GetTop(THIS)1228 HRESULT STDMETHODCALLTYPE CMenuBand::GetTop(THIS)
1229 {
1230     UNIMPLEMENTED;
1231     return S_OK;
1232 }
1233 
GetBottom(THIS)1234 HRESULT STDMETHODCALLTYPE CMenuBand::GetBottom(THIS)
1235 {
1236     UNIMPLEMENTED;
1237     return S_OK;
1238 }
1239 
GetTracked(THIS)1240 HRESULT STDMETHODCALLTYPE CMenuBand::GetTracked(THIS)
1241 {
1242     UNIMPLEMENTED;
1243     return S_OK;
1244 }
1245 
GetParentSite(THIS)1246 HRESULT STDMETHODCALLTYPE CMenuBand::GetParentSite(THIS)
1247 {
1248     UNIMPLEMENTED;
1249     return S_OK;
1250 }
1251 
GetState(THIS)1252 HRESULT STDMETHODCALLTYPE CMenuBand::GetState(THIS)
1253 {
1254     UNIMPLEMENTED;
1255     return S_OK;
1256 }
1257 
DoDefaultAction(THIS)1258 HRESULT STDMETHODCALLTYPE CMenuBand::DoDefaultAction(THIS)
1259 {
1260     UNIMPLEMENTED;
1261     return S_OK;
1262 }
1263 
IsEmpty(THIS)1264 HRESULT STDMETHODCALLTYPE CMenuBand::IsEmpty(THIS)
1265 {
1266     UNIMPLEMENTED;
1267     return S_OK;
1268 }
1269 
HasFocusIO()1270 HRESULT STDMETHODCALLTYPE CMenuBand::HasFocusIO()
1271 {
1272     if (m_popupBar)
1273         return S_OK;
1274     return S_FALSE;
1275 }
1276 
TranslateAcceleratorIO(LPMSG lpMsg)1277 HRESULT STDMETHODCALLTYPE CMenuBand::TranslateAcceleratorIO(LPMSG lpMsg)
1278 {
1279     // TODO: Alt down -> toggle menu focus
1280     return S_FALSE;
1281 }
1282 
IsDirty()1283 HRESULT STDMETHODCALLTYPE CMenuBand::IsDirty()
1284 {
1285     UNIMPLEMENTED;
1286     return S_OK;
1287 }
1288 
Load(IStream * pStm)1289 HRESULT STDMETHODCALLTYPE CMenuBand::Load(IStream *pStm)
1290 {
1291     UNIMPLEMENTED;
1292     return S_OK;
1293 }
1294 
Save(IStream * pStm,BOOL fClearDirty)1295 HRESULT STDMETHODCALLTYPE CMenuBand::Save(IStream *pStm, BOOL fClearDirty)
1296 {
1297     UNIMPLEMENTED;
1298     return S_OK;
1299 }
1300 
GetSizeMax(ULARGE_INTEGER * pcbSize)1301 HRESULT STDMETHODCALLTYPE CMenuBand::GetSizeMax(ULARGE_INTEGER *pcbSize)
1302 {
1303     UNIMPLEMENTED;
1304     return S_OK;
1305 }
1306 
GetClassID(CLSID * pClassID)1307 HRESULT STDMETHODCALLTYPE CMenuBand::GetClassID(CLSID *pClassID)
1308 {
1309     UNIMPLEMENTED;
1310     return S_OK;
1311 }
1312 
QueryStatus(const GUID * pguidCmdGroup,ULONG cCmds,OLECMD prgCmds[],OLECMDTEXT * pCmdText)1313 HRESULT STDMETHODCALLTYPE CMenuBand::QueryStatus(const GUID *pguidCmdGroup, ULONG cCmds, OLECMD prgCmds [], OLECMDTEXT *pCmdText)
1314 {
1315     UNIMPLEMENTED;
1316     return S_OK;
1317 }
1318 
1319 extern "C"
RSHELL_CMenuBand_CreateInstance(REFIID riid,LPVOID * ppv)1320 HRESULT WINAPI RSHELL_CMenuBand_CreateInstance(REFIID riid, LPVOID *ppv)
1321 {
1322     return ShellObjectCreator<CMenuBand>(riid, ppv);
1323 }
1324