4 * Copyright 2014 David Quintana
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.
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.
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
22 #include <commoncontrols.h>
23 #include <shlwapi_undoc.h>
25 #include "CMenuBand.h"
26 #include "CMenuToolbars.h"
27 #include "CMenuFocusManager.h"
29 WINE_DEFAULT_DEBUG_CHANNEL(CMenuBand
);
33 #define UNIMPLEMENTED TRACE("%s is UNIMPLEMENTED!\n", __FUNCTION__)
36 HRESULT WINAPI
CMenuBand_Constructor(REFIID riid
, LPVOID
*ppv
)
39 #if USE_SYSTEM_MENUBAND
40 hr
= CoCreateInstance(CLSID_MenuBand
,
47 CMenuBand
* site
= new CComObject
<CMenuBand
>();
52 hr
= site
->QueryInterface(riid
, ppv
);
54 if (FAILED_UNEXPECTEDLY(hr
))
61 CMenuBand::CMenuBand() :
62 m_staticToolbar(NULL
),
67 m_subMenuParent(NULL
),
73 m_topLevelWindow(NULL
),
81 m_focusManager
= CMenuFocusManager::AcquireManager();
84 CMenuBand::~CMenuBand()
86 CMenuFocusManager::ReleaseManager(m_focusManager
);
89 delete m_staticToolbar
;
95 HRESULT STDMETHODCALLTYPE
CMenuBand::Initialize(
96 IShellMenuCallback
*psmc
,
104 m_uIdAncestor
= uIdAncestor
;
109 _CallCB(SMC_CREATE
, 0, reinterpret_cast<LPARAM
>(&m_UserData
));
115 HRESULT STDMETHODCALLTYPE
CMenuBand::GetMenuInfo(
116 IShellMenuCallback
**ppsmc
,
121 if (!pdwFlags
) // maybe?
131 *puIdAncestor
= m_uIdAncestor
;
133 *pdwFlags
= m_dwFlags
;
138 HRESULT STDMETHODCALLTYPE
CMenuBand::SetMenu(
143 TRACE("CMenuBand::SetMenu called, hmenu=%p; hwnd=%p, flags=%x\n", hmenu
, hwnd
, dwFlags
);
145 BOOL created
= FALSE
;
147 if (m_staticToolbar
== NULL
)
149 m_staticToolbar
= new CMenuStaticToolbar(this);
155 HRESULT hr
= m_staticToolbar
->SetMenu(hmenu
, hwnd
, dwFlags
);
156 if (FAILED_UNEXPECTEDLY(hr
))
163 hr
= m_site
->GetWindow(&hwndParent
);
164 if (FAILED_UNEXPECTEDLY(hr
))
169 hr
= m_staticToolbar
->CreateToolbar(hwndParent
, m_dwFlags
);
170 if (FAILED_UNEXPECTEDLY(hr
))
173 hr
= m_staticToolbar
->FillToolbar();
177 hr
= m_staticToolbar
->FillToolbar(TRUE
);
184 HRESULT STDMETHODCALLTYPE
CMenuBand::GetMenu(
189 if (m_staticToolbar
== NULL
)
192 return m_staticToolbar
->GetMenu(phmenu
, phwnd
, pdwFlags
);
195 HRESULT STDMETHODCALLTYPE
CMenuBand::SetSite(IUnknown
*pUnkSite
)
202 if (pUnkSite
== NULL
)
206 hr
= pUnkSite
->QueryInterface(IID_PPV_ARG(IOleWindow
, &m_site
));
207 if (FAILED_UNEXPECTEDLY(hr
))
210 hr
= m_site
->GetWindow(&hwndParent
);
211 if (FAILED_UNEXPECTEDLY(hr
))
214 if (!::IsWindow(hwndParent
))
217 if (m_staticToolbar
!= NULL
)
219 hr
= m_staticToolbar
->CreateToolbar(hwndParent
, m_dwFlags
);
220 if (FAILED_UNEXPECTEDLY(hr
))
223 hr
= m_staticToolbar
->FillToolbar();
224 if (FAILED_UNEXPECTEDLY(hr
))
228 if (m_SFToolbar
!= NULL
)
230 hr
= m_SFToolbar
->CreateToolbar(hwndParent
, m_dwFlags
);
231 if (FAILED_UNEXPECTEDLY(hr
))
234 hr
= m_SFToolbar
->FillToolbar();
235 if (FAILED_UNEXPECTEDLY(hr
))
239 hr
= IUnknown_QueryService(m_site
, SID_SMenuPopup
, IID_PPV_ARG(IMenuPopup
, &m_subMenuParent
));
240 if (hr
!= E_NOINTERFACE
&& FAILED_UNEXPECTEDLY(hr
))
243 CComPtr
<IOleWindow
> pTopLevelWindow
;
244 hr
= IUnknown_QueryService(m_site
, SID_STopLevelBrowser
, IID_PPV_ARG(IOleWindow
, &pTopLevelWindow
));
245 if (FAILED_UNEXPECTEDLY(hr
))
248 return pTopLevelWindow
->GetWindow(&m_topLevelWindow
);
251 HRESULT STDMETHODCALLTYPE
CMenuBand::GetSite(REFIID riid
, PVOID
*ppvSite
)
256 return m_site
->QueryInterface(riid
, ppvSite
);
259 HRESULT STDMETHODCALLTYPE
CMenuBand::GetWindow(HWND
*phwnd
)
261 if (m_SFToolbar
!= NULL
)
262 return m_SFToolbar
->GetWindow(phwnd
);
264 if (m_staticToolbar
!= NULL
)
265 return m_staticToolbar
->GetWindow(phwnd
);
267 if (phwnd
) *phwnd
= NULL
;
272 HRESULT STDMETHODCALLTYPE
CMenuBand::OnPosRectChangeDB(RECT
*prc
)
274 SIZE maxStatic
= { 0 };
275 SIZE maxShlFld
= { 0 };
278 if (m_staticToolbar
!= NULL
)
279 hr
= m_staticToolbar
->GetSizes(NULL
, &maxStatic
, NULL
);
280 if (FAILED_UNEXPECTEDLY(hr
))
283 if (m_SFToolbar
!= NULL
)
284 hr
= m_SFToolbar
->GetSizes(NULL
, &maxShlFld
, NULL
);
285 if (FAILED_UNEXPECTEDLY(hr
))
288 if (m_staticToolbar
== NULL
&& m_SFToolbar
== NULL
)
291 int sy
= min(prc
->bottom
- prc
->top
, maxStatic
.cy
+ maxShlFld
.cy
);
293 int syStatic
= maxStatic
.cy
;
294 int syShlFld
= sy
- syStatic
;
300 m_SFToolbar
->SetPosSize(
303 prc
->right
- prc
->left
,
308 m_staticToolbar
->SetPosSize(
311 prc
->right
- prc
->left
,
315 else // shell menu on top
319 m_SFToolbar
->SetPosSize(
322 prc
->right
- prc
->left
,
327 m_staticToolbar
->SetPosSize(
330 prc
->right
- prc
->left
,
338 HRESULT STDMETHODCALLTYPE
CMenuBand::GetBandInfo(
343 SIZE minStatic
= { 0 };
344 SIZE minShlFld
= { 0 };
345 SIZE maxStatic
= { 0 };
346 SIZE maxShlFld
= { 0 };
347 SIZE intStatic
= { 0 };
348 SIZE intShlFld
= { 0 };
352 if (m_staticToolbar
!= NULL
)
353 hr
= m_staticToolbar
->GetSizes(&minStatic
, &maxStatic
, &intStatic
);
354 if (FAILED_UNEXPECTEDLY(hr
))
357 if (m_SFToolbar
!= NULL
)
358 hr
= m_SFToolbar
->GetSizes(&minShlFld
, &maxShlFld
, &intShlFld
);
359 if (FAILED_UNEXPECTEDLY(hr
))
362 if (m_staticToolbar
== NULL
&& m_SFToolbar
== NULL
)
365 if (m_dwFlags
& SMINIT_VERTICAL
)
367 pdbi
->ptMinSize
.x
= max(minStatic
.cx
, minShlFld
.cx
) + 20;
368 pdbi
->ptMinSize
.y
= minStatic
.cy
+ minShlFld
.cy
;
369 pdbi
->ptMaxSize
.x
= max(maxStatic
.cx
, maxShlFld
.cx
) + 20;
370 pdbi
->ptMaxSize
.y
= maxStatic
.cy
+ maxShlFld
.cy
;
371 pdbi
->dwModeFlags
= DBIMF_VARIABLEHEIGHT
;
375 pdbi
->ptMinSize
.x
= minStatic
.cx
+ minShlFld
.cx
;
376 pdbi
->ptMinSize
.y
= max(minStatic
.cy
, minShlFld
.cy
);
377 pdbi
->ptMaxSize
.x
= maxStatic
.cx
+ maxShlFld
.cx
;
378 pdbi
->ptMaxSize
.y
= max(maxStatic
.cy
, maxShlFld
.cy
);
380 pdbi
->ptIntegral
.x
= max(intStatic
.cx
, intShlFld
.cx
);
381 pdbi
->ptIntegral
.y
= max(intStatic
.cy
, intShlFld
.cy
);
382 pdbi
->ptActual
= pdbi
->ptMinSize
;
387 HRESULT STDMETHODCALLTYPE
CMenuBand::ShowDW(BOOL fShow
)
394 if (m_staticToolbar
!= NULL
)
396 hr
= m_staticToolbar
->ShowWindow(fShow
);
397 if (FAILED_UNEXPECTEDLY(hr
))
401 if (m_SFToolbar
!= NULL
)
403 hr
= m_SFToolbar
->ShowWindow(fShow
);
404 if (FAILED_UNEXPECTEDLY(hr
))
410 hr
= _CallCB(SMC_INITMENU
, 0, 0);
411 if (FAILED_UNEXPECTEDLY(hr
))
414 else if (m_parentBand
)
416 m_parentBand
->SetClient(NULL
);
419 if (_IsPopup() == S_OK
)
422 hr
= m_focusManager
->PushMenuPopup(this);
424 hr
= m_focusManager
->PopMenuPopup(this);
429 hr
= m_focusManager
->PushMenuBar(this);
431 hr
= m_focusManager
->PopMenuBar(this);
439 HRESULT STDMETHODCALLTYPE
CMenuBand::CloseDW(DWORD dwReserved
)
443 if (m_staticToolbar
!= NULL
)
445 m_staticToolbar
->Close();
446 delete m_staticToolbar
;
447 m_staticToolbar
= NULL
;
450 if (m_SFToolbar
!= NULL
)
452 m_SFToolbar
->Close();
453 delete m_staticToolbar
;
454 m_staticToolbar
= NULL
;
457 if (m_site
) m_site
.Release();
458 if (m_psmc
) m_psmc
.Release();
459 if (m_subMenuChild
) m_subMenuChild
.Release();
460 if (m_subMenuParent
) m_subMenuParent
.Release();
461 if (m_childBand
) m_childBand
.Release();
462 if (m_parentBand
) m_parentBand
.Release();
467 HRESULT STDMETHODCALLTYPE
CMenuBand::UIActivateIO(BOOL fActivate
, LPMSG lpMsg
)
473 hr
= m_subMenuParent
->SetSubMenu(this, fActivate
);
474 if (FAILED_UNEXPECTEDLY(hr
))
480 CComPtr
<IOleWindow
> pTopLevelWindow
;
481 hr
= IUnknown_QueryService(m_site
, SID_SMenuPopup
, IID_PPV_ARG(IOleWindow
, &pTopLevelWindow
));
482 if (FAILED_UNEXPECTEDLY(hr
))
485 hr
= pTopLevelWindow
->GetWindow(&m_topLevelWindow
);
486 if (FAILED_UNEXPECTEDLY(hr
))
491 m_topLevelWindow
= NULL
;
497 HRESULT STDMETHODCALLTYPE
CMenuBand::Exec(const GUID
*pguidCmdGroup
, DWORD nCmdID
, DWORD nCmdexecopt
, VARIANT
*pvaIn
, VARIANT
*pvaOut
)
502 if (IsEqualGUID(*pguidCmdGroup
, CLSID_MenuBand
))
504 if (nCmdID
== 16) // set (big) icon size
506 this->m_useBigIcons
= nCmdexecopt
== 2;
509 else if (nCmdID
== 19) // popup-related
513 else if (nCmdID
== 5) // select an item
515 if (nCmdexecopt
== 0) // first
517 _KeyboardItemChange(VK_HOME
);
521 _KeyboardItemChange(VK_END
);
533 HRESULT STDMETHODCALLTYPE
CMenuBand::QueryService(REFGUID guidService
, REFIID riid
, void **ppvObject
)
535 if (IsEqualIID(guidService
, SID_SMenuBandChild
) ||
536 IsEqualIID(guidService
, SID_SMenuBandBottom
) ||
537 IsEqualIID(guidService
, SID_SMenuBandBottomSelected
))
538 return this->QueryInterface(riid
, ppvObject
);
539 WARN("Unknown service requested %s\n", wine_dbgstr_guid(&guidService
));
540 return E_NOINTERFACE
;
543 HRESULT STDMETHODCALLTYPE
CMenuBand::Popup(POINTL
*ppt
, RECTL
*prcExclude
, MP_POPUPFLAGS dwFlags
)
549 HRESULT STDMETHODCALLTYPE
CMenuBand::OnSelect(DWORD dwSelectType
)
551 switch (dwSelectType
)
553 case MPOS_CHILDTRACKING
:
554 if (!m_subMenuParent
)
556 // TODO: Cancel timers?
557 return m_subMenuParent
->OnSelect(dwSelectType
);
558 case MPOS_SELECTLEFT
:
560 m_subMenuChild
->OnSelect(MPOS_CANCELLEVEL
);
561 if (!m_subMenuParent
)
563 return m_subMenuParent
->OnSelect(dwSelectType
);
564 case MPOS_SELECTRIGHT
:
565 if (!m_subMenuParent
)
567 return m_subMenuParent
->OnSelect(dwSelectType
);
569 case MPOS_FULLCANCEL
:
571 m_subMenuChild
->OnSelect(dwSelectType
);
572 if (!m_subMenuParent
)
574 return m_subMenuParent
->OnSelect(dwSelectType
);
575 case MPOS_CANCELLEVEL
:
577 m_subMenuChild
->OnSelect(dwSelectType
);
583 HRESULT STDMETHODCALLTYPE
CMenuBand::SetSubMenu(IMenuPopup
*pmp
, BOOL fSet
)
589 HRESULT
CMenuBand::_SetChildBand(CMenuBand
* child
)
594 _ChangePopupItem(NULL
, -1);
599 HRESULT
CMenuBand::_SetParentBand(CMenuBand
* parent
)
601 m_parentBand
= parent
;
605 HRESULT
CMenuBand::_IsPopup()
607 return m_subMenuParent
? S_OK
: S_FALSE
;
610 HRESULT
CMenuBand::_IsTracking()
612 return m_popupBar
!= NULL
;
615 HRESULT STDMETHODCALLTYPE
CMenuBand::SetClient(IUnknown
*punkClient
)
617 m_subMenuChild
= NULL
;
624 HRESULT hr
= punkClient
->QueryInterface(IID_PPV_ARG(IMenuPopup
, &m_subMenuChild
));
629 HRESULT STDMETHODCALLTYPE
CMenuBand::GetClient(IUnknown
**ppunkClient
)
631 // HACK, so I can test for a submenu in the DeskBar
635 *ppunkClient
= m_subMenuChild
;
642 HRESULT STDMETHODCALLTYPE
CMenuBand::IsMenuMessage(MSG
*pmsg
)
647 HRESULT STDMETHODCALLTYPE
CMenuBand::TranslateMenuMessage(MSG
*pmsg
, LRESULT
*plRet
)
652 HRESULT STDMETHODCALLTYPE
CMenuBand::SetShellFolder(IShellFolder
*psf
, LPCITEMIDLIST pidlFolder
, HKEY hKey
, DWORD dwFlags
)
654 if (m_SFToolbar
== NULL
)
656 m_SFToolbar
= new CMenuSFToolbar(this);
659 HRESULT hr
= m_SFToolbar
->SetShellFolder(psf
, pidlFolder
, hKey
, dwFlags
);
660 if (FAILED_UNEXPECTEDLY(hr
))
663 m_shellBottom
= (dwFlags
& SMSET_BOTTOM
) != 0;
669 hr
= m_site
->GetWindow(&hwndParent
);
670 if (FAILED_UNEXPECTEDLY(hr
))
673 hr
= m_SFToolbar
->CreateToolbar(hwndParent
, m_dwFlags
);
674 if (FAILED_UNEXPECTEDLY(hr
))
677 hr
= m_SFToolbar
->FillToolbar();
683 HRESULT STDMETHODCALLTYPE
CMenuBand::GetShellFolder(DWORD
*pdwFlags
, LPITEMIDLIST
*ppidl
, REFIID riid
, void **ppv
)
686 return m_SFToolbar
->GetShellFolder(pdwFlags
, ppidl
, riid
, ppv
);
690 HRESULT STDMETHODCALLTYPE
CMenuBand::OnWinEvent(HWND hWnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
, LRESULT
*theResult
)
694 if (m_staticToolbar
&& m_staticToolbar
->IsWindowOwner(hWnd
) == S_OK
)
696 return m_staticToolbar
->OnWinEvent(hWnd
, uMsg
, wParam
, lParam
, theResult
);
699 if (m_SFToolbar
&& m_SFToolbar
->IsWindowOwner(hWnd
) == S_OK
)
701 return m_SFToolbar
->OnWinEvent(hWnd
, uMsg
, wParam
, lParam
, theResult
);
707 HRESULT STDMETHODCALLTYPE
CMenuBand::IsWindowOwner(HWND hWnd
)
709 if (m_staticToolbar
&& m_staticToolbar
->IsWindowOwner(hWnd
) == S_OK
)
712 if (m_SFToolbar
&& m_SFToolbar
->IsWindowOwner(hWnd
) == S_OK
)
718 HRESULT
CMenuBand::_CallCBWithItemId(UINT id
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
720 return _CallCB(uMsg
, wParam
, lParam
, id
);
723 HRESULT
CMenuBand::_CallCBWithItemPidl(LPITEMIDLIST pidl
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
725 return _CallCB(uMsg
, wParam
, lParam
, 0, pidl
);
728 HRESULT
CMenuBand::_CallCB(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, UINT id
, LPITEMIDLIST pidl
)
736 SMDATA smData
= { 0 };
737 smData
.punk
= static_cast<IShellMenu2
*>(this);
739 smData
.uIdParent
= m_uId
;
740 smData
.uIdAncestor
= m_uIdAncestor
;
741 smData
.pidlItem
= pidl
;
744 smData
.hmenu
= m_hmenu
;
745 smData
.pvUserData
= NULL
;
747 m_SFToolbar
->GetShellFolder(NULL
, &smData
.pidlFolder
, IID_PPV_ARG(IShellFolder
, &smData
.psf
));
748 HRESULT hr
= m_psmc
->CallbackSM(&smData
, uMsg
, wParam
, lParam
);
749 ILFree(smData
.pidlFolder
);
751 smData
.psf
->Release();
755 HRESULT
CMenuBand::_TrackSubMenu(HMENU popup
, INT x
, INT y
, RECT
& rcExclude
)
757 TPMPARAMS params
= { sizeof(TPMPARAMS
), rcExclude
};
758 UINT flags
= TPM_VERPOSANIMATION
| TPM_VERTICAL
| TPM_LEFTALIGN
;
759 HWND hwnd
= m_menuOwner
? m_menuOwner
: m_topLevelWindow
;
761 m_focusManager
->PushTrackedPopup(popup
);
762 ::TrackPopupMenuEx(popup
, flags
, x
, y
, hwnd
, ¶ms
);
763 m_focusManager
->PopTrackedPopup(popup
);
765 _DisableMouseTrack(FALSE
);
770 HRESULT
CMenuBand::_TrackContextMenu(IContextMenu
* contextMenu
, INT x
, INT y
)
774 HMENU popup
= CreatePopupMenu();
779 TRACE("Before Query\n");
780 hr
= contextMenu
->QueryContextMenu(popup
, 0, 0, UINT_MAX
, CMF_NORMAL
);
781 if (FAILED_UNEXPECTEDLY(hr
))
783 TRACE("Query failed\n");
788 HWND hwnd
= m_menuOwner
? m_menuOwner
: m_topLevelWindow
;
790 m_focusManager
->PushTrackedPopup(popup
);
792 TRACE("Before Tracking\n");
793 uCommand
= ::TrackPopupMenuEx(popup
, TPM_RETURNCMD
, x
, y
, hwnd
, NULL
);
795 m_focusManager
->PopTrackedPopup(popup
);
799 TRACE("Before InvokeCommand\n");
800 CMINVOKECOMMANDINFO cmi
= { 0 };
801 cmi
.cbSize
= sizeof(cmi
);
802 cmi
.lpVerb
= MAKEINTRESOURCEA(uCommand
);
804 hr
= contextMenu
->InvokeCommand(&cmi
);
808 TRACE("TrackPopupMenu failed. Code=%d, LastError=%d\n", uCommand
, GetLastError());
816 HRESULT
CMenuBand::_GetTopLevelWindow(HWND
*topLevel
)
818 *topLevel
= m_topLevelWindow
;
822 HRESULT
CMenuBand::_ChangeHotItem(CMenuToolbarBase
* tb
, INT id
, DWORD dwFlags
)
824 if (m_hotBar
== tb
&& m_hotItem
== id
)
827 TRACE("Hot item changed from %p %p, to %p %p\n", m_hotBar
, m_hotItem
, tb
, id
);
833 if (m_staticToolbar
) m_staticToolbar
->ChangeHotItem(tb
, id
, dwFlags
);
834 if (m_SFToolbar
) m_SFToolbar
->ChangeHotItem(tb
, id
, dwFlags
);
836 _MenuItemHotTrack(MPOS_CHILDTRACKING
);
842 HRESULT
CMenuBand::_ChangePopupItem(CMenuToolbarBase
* tb
, INT id
)
844 TRACE("Popup item changed from %p %p, to %p %p\n", m_popupBar
, m_popupItem
, tb
, id
);
848 if (m_staticToolbar
) m_staticToolbar
->ChangePopupItem(tb
, id
);
849 if (m_SFToolbar
) m_SFToolbar
->ChangePopupItem(tb
, id
);
854 HRESULT
CMenuBand::_KeyboardItemChange(DWORD change
)
857 CMenuToolbarBase
*tb
= m_hotBar
;
861 // If no hot item was selected choose the appropriate toolbar
862 if (change
== VK_UP
|| change
== VK_END
)
865 tb
= m_staticToolbar
;
869 else if (change
== VK_DOWN
|| change
== VK_HOME
)
874 tb
= m_staticToolbar
;
878 // Ask the first toolbar to change
879 hr
= tb
->KeyboardItemChange(change
);
884 // Select the second toolbar based on the first
885 if (tb
== m_SFToolbar
&& m_staticToolbar
)
886 tb
= m_staticToolbar
;
887 else if (m_SFToolbar
)
893 // Ask the second toolbar to change
894 return tb
->KeyboardItemChange(change
== VK_DOWN
? VK_HOME
: VK_END
);
897 HRESULT
CMenuBand::_MenuItemHotTrack(DWORD changeType
)
901 if (m_dwFlags
& SMINIT_VERTICAL
)
907 return _KeyboardItemChange(changeType
);
909 // TODO: Left/Right across multi-column menus, if they ever work.
911 changeType
= MPOS_SELECTLEFT
;
914 changeType
= MPOS_SELECTRIGHT
;
920 // In horizontal menubars, left/right are equivalent to vertical's up/down
924 hr
= _KeyboardItemChange(VK_UP
);
928 hr
= _KeyboardItemChange(VK_DOWN
);
937 m_hotBar
->ExecuteItem(m_hotItem
);
940 case MPOS_SELECTLEFT
:
941 if (m_parentBand
&& m_parentBand
->_IsPopup()==S_FALSE
)
942 return m_parentBand
->_MenuItemHotTrack(VK_LEFT
);
944 return m_subMenuChild
->OnSelect(MPOS_CANCELLEVEL
);
945 if (!m_subMenuParent
)
947 return m_subMenuParent
->OnSelect(MPOS_CANCELLEVEL
);
949 case MPOS_SELECTRIGHT
:
950 if (m_hotBar
&& m_hotItem
>= 0 && m_hotBar
->PopupItem(m_hotItem
, TRUE
) == S_OK
)
953 return m_parentBand
->_MenuItemHotTrack(VK_RIGHT
);
954 if (!m_subMenuParent
)
956 return m_subMenuParent
->OnSelect(MPOS_SELECTRIGHT
);
959 if (!m_subMenuParent
)
961 return m_subMenuParent
->OnSelect(changeType
);
967 HRESULT
CMenuBand::_CancelCurrentPopup()
972 HRESULT hr
= m_subMenuChild
->OnSelect(MPOS_CANCELLEVEL
);
976 HRESULT
CMenuBand::_OnPopupSubMenu(IShellMenu
* childShellMenu
, POINTL
* pAt
, RECTL
* pExclude
, BOOL keyInitiated
)
979 IBandSite
* pBandSite
;
982 // Create the necessary objects
983 hr
= CMenuSite_Constructor(IID_PPV_ARG(IBandSite
, &pBandSite
));
984 if (FAILED_UNEXPECTEDLY(hr
))
987 hr
= CMenuDeskBar_Constructor(IID_PPV_ARG(IDeskBar
, &pDeskBar
));
988 if (FAILED_UNEXPECTEDLY(hr
))
991 hr
= pDeskBar
->SetClient(pBandSite
);
992 if (FAILED_UNEXPECTEDLY(hr
))
995 hr
= pBandSite
->AddBand(childShellMenu
);
996 if (FAILED_UNEXPECTEDLY(hr
))
1000 CComPtr
<IMenuPopup
> popup
;
1001 hr
= pDeskBar
->QueryInterface(IID_PPV_ARG(IMenuPopup
, &popup
));
1002 if (FAILED_UNEXPECTEDLY(hr
))
1005 m_subMenuChild
= popup
;
1007 if (m_subMenuParent
)
1008 IUnknown_SetSite(popup
, m_subMenuParent
);
1010 IUnknown_SetSite(popup
, m_site
);
1012 DWORD flags
= MPPF_RIGHT
;
1014 if (keyInitiated
&& m_dwFlags
& SMINIT_VERTICAL
)
1015 flags
|= MPPF_INITIALSELECT
;
1017 popup
->Popup(pAt
, pExclude
, flags
);
1022 HRESULT
CMenuBand::_DisableMouseTrack(BOOL bDisable
)
1024 if (m_staticToolbar
)
1025 m_staticToolbar
->DisableMouseTrack(bDisable
);
1027 m_SFToolbar
->DisableMouseTrack(bDisable
);
1031 HRESULT
CMenuBand::_KillPopupTimers()
1034 if (m_staticToolbar
)
1035 hr
= m_staticToolbar
->KillPopupTimer();
1040 hr
= m_SFToolbar
->KillPopupTimer();
1045 HRESULT
CMenuBand::_MenuBarMouseDown(HWND hwnd
, INT item
)
1047 if (m_staticToolbar
&& m_staticToolbar
->IsWindowOwner(hwnd
) == S_OK
)
1048 m_staticToolbar
->MenuBarMouseDown(item
);
1049 if (m_SFToolbar
&& m_SFToolbar
->IsWindowOwner(hwnd
) == S_OK
)
1050 m_SFToolbar
->MenuBarMouseDown(item
);
1054 HRESULT
CMenuBand::_MenuBarMouseUp(HWND hwnd
, INT item
)
1056 if (m_staticToolbar
&& m_staticToolbar
->IsWindowOwner(hwnd
) == S_OK
)
1057 m_staticToolbar
->MenuBarMouseUp(item
);
1058 if (m_SFToolbar
&& m_SFToolbar
->IsWindowOwner(hwnd
) == S_OK
)
1059 m_SFToolbar
->MenuBarMouseUp(item
);
1063 HRESULT STDMETHODCALLTYPE
CMenuBand::InvalidateItem(LPSMDATA psmd
, DWORD dwFlags
)
1069 HRESULT STDMETHODCALLTYPE
CMenuBand::GetState(LPSMDATA psmd
)
1075 HRESULT STDMETHODCALLTYPE
CMenuBand::SetMenuToolbar(IUnknown
*punk
, DWORD dwFlags
)
1081 HRESULT STDMETHODCALLTYPE
CMenuBand::ResizeBorderDW(LPCRECT prcBorder
, IUnknown
*punkToolbarSite
, BOOL fReserved
)
1087 HRESULT STDMETHODCALLTYPE
CMenuBand::ContextSensitiveHelp(BOOL fEnterMode
)
1093 HRESULT STDMETHODCALLTYPE
CMenuBand::GetSubMenu(THIS
)
1099 HRESULT STDMETHODCALLTYPE
CMenuBand::SetToolbar(THIS
)
1105 HRESULT STDMETHODCALLTYPE
CMenuBand::SetMinWidth(THIS
)
1111 HRESULT STDMETHODCALLTYPE
CMenuBand::SetNoBorder(THIS
)
1117 HRESULT STDMETHODCALLTYPE
CMenuBand::SetTheme(THIS
)
1123 HRESULT STDMETHODCALLTYPE
CMenuBand::GetTop(THIS
)
1129 HRESULT STDMETHODCALLTYPE
CMenuBand::GetBottom(THIS
)
1135 HRESULT STDMETHODCALLTYPE
CMenuBand::GetTracked(THIS
)
1141 HRESULT STDMETHODCALLTYPE
CMenuBand::GetParentSite(THIS
)
1147 HRESULT STDMETHODCALLTYPE
CMenuBand::GetState(THIS
)
1153 HRESULT STDMETHODCALLTYPE
CMenuBand::DoDefaultAction(THIS
)
1159 HRESULT STDMETHODCALLTYPE
CMenuBand::IsEmpty(THIS
)
1165 HRESULT STDMETHODCALLTYPE
CMenuBand::HasFocusIO()
1172 HRESULT STDMETHODCALLTYPE
CMenuBand::TranslateAcceleratorIO(LPMSG lpMsg
)
1174 // TODO: Alt down -> toggle menu focus
1178 HRESULT STDMETHODCALLTYPE
CMenuBand::IsDirty()
1184 HRESULT STDMETHODCALLTYPE
CMenuBand::Load(IStream
*pStm
)
1190 HRESULT STDMETHODCALLTYPE
CMenuBand::Save(IStream
*pStm
, BOOL fClearDirty
)
1196 HRESULT STDMETHODCALLTYPE
CMenuBand::GetSizeMax(ULARGE_INTEGER
*pcbSize
)
1202 HRESULT STDMETHODCALLTYPE
CMenuBand::GetClassID(CLSID
*pClassID
)
1208 HRESULT STDMETHODCALLTYPE
CMenuBand::QueryStatus(const GUID
*pguidCmdGroup
, ULONG cCmds
, OLECMD prgCmds
[], OLECMDTEXT
*pCmdText
)