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 This file implements the CMenuFocusManager class.
24 This class manages the shell menus, by overriding the hot-tracking behaviour.
26 For the shell menus, it uses a GetMessage hook,
27 where it intercepts messages directed to the menu windows.
29 In order to show submenus using system popups, it also has a MessageFilter hook.
31 The menu is tracked using a stack structure. When a CMenuBand wants to open a submenu,
32 it pushes the submenu band, or HMENU to track in case of system popups,
33 and when the menu has closed, it pops the same pointer or handle.
35 While a shell menu is open, it overrides the menu toolbar's hottracking behaviour,
36 using its own logic to track both the active menu item, and the opened submenu's parent item.
38 While a system popup is open, it tracks the mouse movements so that it can cancel the popup,
39 and switch to another submenu when the mouse goes over another item from the parent.
42 #include "shellmenu.h"
44 #include <commoncontrols.h>
45 #include <shlwapi_undoc.h>
47 #include "CMenuFocusManager.h"
48 #include "CMenuToolbars.h"
49 #include "CMenuBand.h"
53 # define _ASSERT(x) DbgAssert(!!(x), __FILE__, __LINE__, #x)
55 bool DbgAssert(bool x
, const char * filename
, int line
, const char * expr
)
62 fname
= strrchr(filename
, '\\');
65 fname
= strrchr(filename
, '/');
73 sprintf(szMsg
, "%s:%d: Assertion failed: %s\n", fname
, line
, expr
);
75 OutputDebugStringA(szMsg
);
83 # define _ASSERT(x) (!!(x))
86 WINE_DEFAULT_DEBUG_CHANNEL(CMenuFocus
);
88 DWORD
CMenuFocusManager::TlsIndex
= 0;
90 // Gets the thread's assigned manager without refcounting
91 CMenuFocusManager
* CMenuFocusManager::GetManager()
93 return reinterpret_cast<CMenuFocusManager
*>(TlsGetValue(TlsIndex
));
96 // Obtains a manager for the thread, with refcounting
97 CMenuFocusManager
* CMenuFocusManager::AcquireManager()
99 CMenuFocusManager
* obj
= NULL
;
103 if ((TlsIndex
= TlsAlloc()) == TLS_OUT_OF_INDEXES
)
111 obj
= new CComObject
<CMenuFocusManager
>();
112 TlsSetValue(TlsIndex
, obj
);
120 // Releases a previously acquired manager, and deletes it if the refcount reaches 0
121 void CMenuFocusManager::ReleaseManager(CMenuFocusManager
* obj
)
125 TlsSetValue(TlsIndex
, NULL
);
129 LRESULT CALLBACK
CMenuFocusManager::s_MsgFilterHook(INT nCode
, WPARAM wParam
, LPARAM lParam
)
131 return GetManager()->MsgFilterHook(nCode
, wParam
, lParam
);
134 LRESULT CALLBACK
CMenuFocusManager::s_GetMsgHook(INT nCode
, WPARAM wParam
, LPARAM lParam
)
136 return GetManager()->GetMsgHook(nCode
, wParam
, lParam
);
139 HRESULT
CMenuFocusManager::PushToArray(StackEntryType type
, CMenuBand
* mb
, HMENU hmenu
)
141 if (m_bandCount
>= MAX_RECURSE
)
142 return E_OUTOFMEMORY
;
144 m_bandStack
[m_bandCount
].type
= type
;
145 m_bandStack
[m_bandCount
].mb
= mb
;
146 m_bandStack
[m_bandCount
].hmenu
= hmenu
;
152 HRESULT
CMenuFocusManager::PopFromArray(StackEntryType
* pType
, CMenuBand
** pMb
, HMENU
* pHmenu
)
154 if (pType
) *pType
= NoEntry
;
155 if (pMb
) *pMb
= NULL
;
156 if (pHmenu
) *pHmenu
= NULL
;
158 if (m_bandCount
<= 0)
163 if (pType
) *pType
= m_bandStack
[m_bandCount
].type
;
164 if (*pType
== TrackedMenuEntry
)
166 if (pHmenu
) *pHmenu
= m_bandStack
[m_bandCount
].hmenu
;
170 if (pMb
) *pMb
= m_bandStack
[m_bandCount
].mb
;
176 CMenuFocusManager::CMenuFocusManager() :
179 m_hMsgFilterHook(NULL
),
181 m_mouseTrackDisabled(FALSE
),
183 m_hwndUnderMouse(NULL
),
184 m_entryUnderMouse(NULL
),
185 m_selectedMenu(NULL
),
187 m_selectedItemFlags(0),
188 m_movedSinceDown(FALSE
),
189 m_windowAtDown(NULL
),
190 m_PreviousForeground(NULL
),
196 m_threadId
= GetCurrentThreadId();
199 CMenuFocusManager::~CMenuFocusManager()
203 // Used so that the toolbar can properly ignore mouse events, when the menu is being used with the keyboard
204 void CMenuFocusManager::DisableMouseTrack(HWND parent
, BOOL disableThis
)
206 BOOL bDisable
= FALSE
;
207 BOOL lastDisable
= FALSE
;
212 StackEntry
& entry
= m_bandStack
[i
];
214 if (entry
.type
!= TrackedMenuEntry
)
217 HRESULT hr
= entry
.mb
->_GetTopLevelWindow(&hwnd
);
218 if (FAILED_UNEXPECTEDLY(hr
))
223 lastDisable
= disableThis
;
224 entry
.mb
->_DisableMouseTrack(disableThis
);
229 lastDisable
= bDisable
;
230 entry
.mb
->_DisableMouseTrack(bDisable
);
234 m_mouseTrackDisabled
= lastDisable
;
237 void CMenuFocusManager::SetMenuCapture(HWND child
)
239 if (m_captureHwnd
!= child
)
244 m_captureHwnd
= child
;
245 TRACE("Capturing %p\n", child
);
250 m_captureHwnd
= NULL
;
251 TRACE("Capture is now off\n");
257 HRESULT
CMenuFocusManager::IsTrackedWindow(HWND hWnd
, StackEntry
** pentry
)
262 for (int i
= m_bandCount
; --i
>= 0;)
264 StackEntry
& entry
= m_bandStack
[i
];
266 if (entry
.type
!= TrackedMenuEntry
)
268 HRESULT hr
= entry
.mb
->IsWindowOwner(hWnd
);
269 if (FAILED_UNEXPECTEDLY(hr
))
283 HRESULT
CMenuFocusManager::IsTrackedWindowOrParent(HWND hWnd
)
285 for (int i
= m_bandCount
; --i
>= 0;)
287 StackEntry
& entry
= m_bandStack
[i
];
289 if (entry
.type
!= TrackedMenuEntry
)
291 HRESULT hr
= entry
.mb
->IsWindowOwner(hWnd
);
292 if (FAILED_UNEXPECTEDLY(hr
))
296 if (entry
.mb
->_IsPopup() == S_OK
)
298 CComPtr
<IUnknown
> site
;
299 CComPtr
<IOleWindow
> pw
;
300 hr
= entry
.mb
->GetSite(IID_PPV_ARG(IUnknown
, &site
));
301 if (FAILED_UNEXPECTEDLY(hr
))
303 hr
= IUnknown_QueryService(site
, SID_SMenuBandParent
, IID_PPV_ARG(IOleWindow
, &pw
));
304 if (FAILED_UNEXPECTEDLY(hr
))
308 if (pw
->GetWindow(&hParent
) == S_OK
&& hParent
== hWnd
)
317 LRESULT
CMenuFocusManager::ProcessMouseMove(MSG
* msg
)
320 int iHitTestResult
= -1;
322 POINT pt2
= { GET_X_LPARAM(msg
->lParam
), GET_Y_LPARAM(msg
->lParam
) };
323 ClientToScreen(msg
->hwnd
, &pt2
);
327 // Don't do anything if another window is capturing the mouse.
328 HWND cCapture
= ::GetCapture();
329 if (cCapture
&& cCapture
!= m_captureHwnd
&& m_current
->type
!= TrackedMenuEntry
)
332 m_movedSinceDown
= TRUE
;
336 child
= WindowFromPoint(pt
);
338 StackEntry
* entry
= NULL
;
339 if (IsTrackedWindow(child
, &entry
) == S_OK
)
344 BOOL isTracking
= FALSE
;
345 if (entry
&& (entry
->type
== MenuBarEntry
|| m_current
->type
!= TrackedMenuEntry
))
347 ScreenToClient(child
, &pt
);
348 iHitTestResult
= SendMessageW(child
, TB_HITTEST
, 0, (LPARAM
) &pt
);
349 isTracking
= entry
->mb
->_IsTracking();
351 if (SendMessage(child
, WM_USER_ISTRACKEDITEM
, iHitTestResult
, 0) == S_FALSE
)
353 // The current tracked item has changed, notify the toolbar
355 TRACE("Hot item tracking detected a change (capture=%p / cCapture=%p)...\n", m_captureHwnd
, cCapture
);
356 DisableMouseTrack(NULL
, FALSE
);
357 if (isTracking
&& iHitTestResult
>= 0 && m_current
->type
== TrackedMenuEntry
)
358 SendMessage(entry
->hwnd
, WM_CANCELMODE
, 0, 0);
359 PostMessage(child
, WM_USER_CHANGETRACKEDITEM
, iHitTestResult
, MAKELPARAM(isTracking
, TRUE
));
360 if (m_current
->type
== TrackedMenuEntry
)
365 if (m_entryUnderMouse
!= entry
)
367 // Mouse moved away from a tracked window
368 if (m_entryUnderMouse
)
370 m_entryUnderMouse
->mb
->_ChangeHotItem(NULL
, -1, HICF_MOUSE
);
374 if (m_hwndUnderMouse
!= child
)
378 // Mouse moved to a tracked window
379 if (m_current
->type
== MenuPopupEntry
)
381 ScreenToClient(child
, &pt2
);
382 SendMessage(child
, WM_MOUSEMOVE
, msg
->wParam
, MAKELPARAM(pt2
.x
, pt2
.y
));
386 m_hwndUnderMouse
= child
;
387 m_entryUnderMouse
= entry
;
390 if (m_current
->type
== MenuPopupEntry
)
392 HWND parent
= GetAncestor(child
, GA_ROOT
);
393 DisableMouseTrack(parent
, FALSE
);
399 LRESULT
CMenuFocusManager::ProcessMouseDown(MSG
* msg
, BOOL isLButton
)
402 int iHitTestResult
= -1;
404 TRACE("ProcessMouseDown %d %d %d\n", msg
->message
, msg
->wParam
, msg
->lParam
);
406 // Don't do anything if another window is capturing the mouse.
407 HWND cCapture
= ::GetCapture();
408 if (cCapture
&& cCapture
!= m_captureHwnd
&& m_current
->type
!= TrackedMenuEntry
)
410 TRACE("Foreign capture active.\n");
416 child
= WindowFromPoint(pt
);
418 StackEntry
* entry
= NULL
;
419 if (IsTrackedWindow(child
, &entry
) != S_OK
)
421 TRACE("Foreign window detected.\n");
425 if (entry
->type
== MenuBarEntry
)
427 if (entry
!= m_current
)
429 TRACE("Menubar with popup active.\n");
436 ScreenToClient(child
, &pt
);
437 iHitTestResult
= SendMessageW(child
, TB_HITTEST
, 0, (LPARAM
) &pt
);
439 if (iHitTestResult
>= 0)
441 TRACE("MouseDown send %d\n", iHitTestResult
);
442 entry
->mb
->_MenuBarMouseDown(child
, iHitTestResult
, isLButton
);
446 msg
->message
= WM_NULL
;
448 m_movedSinceDown
= FALSE
;
449 m_windowAtDown
= child
;
451 TRACE("MouseDown end\n");
456 LRESULT
CMenuFocusManager::ProcessMouseUp(MSG
* msg
, BOOL isLButton
)
459 int iHitTestResult
= -1;
461 TRACE("ProcessMouseUp %d %d %d\n", msg
->message
, msg
->wParam
, msg
->lParam
);
463 // Don't do anything if another window is capturing the mouse.
464 HWND cCapture
= ::GetCapture();
465 if (cCapture
&& cCapture
!= m_captureHwnd
&& m_current
->type
!= TrackedMenuEntry
)
470 child
= WindowFromPoint(pt
);
472 StackEntry
* entry
= NULL
;
473 if (IsTrackedWindow(child
, &entry
) != S_OK
)
478 ScreenToClient(child
, &pt
);
479 iHitTestResult
= SendMessageW(child
, TB_HITTEST
, 0, (LPARAM
) &pt
);
481 if (iHitTestResult
>= 0)
483 TRACE("MouseUp send %d\n", iHitTestResult
);
484 entry
->mb
->_MenuBarMouseUp(child
, iHitTestResult
, isLButton
);
491 LRESULT
CMenuFocusManager::MsgFilterHook(INT nCode
, WPARAM hookWParam
, LPARAM hookLParam
)
494 return CallNextHookEx(m_hMsgFilterHook
, nCode
, hookWParam
, hookLParam
);
496 if (nCode
== MSGF_MENU
)
498 BOOL callNext
= TRUE
;
499 MSG
* msg
= reinterpret_cast<MSG
*>(hookLParam
);
501 switch (msg
->message
)
505 if (m_menuBar
&& m_current
->type
== TrackedMenuEntry
)
508 HWND child
= WindowFromPoint(pt
);
509 BOOL hoveringMenuBar
= m_menuBar
->mb
->IsWindowOwner(child
) == S_OK
;
512 m_menuBar
->mb
->_BeforeCancelPopup();
517 callNext
= ProcessMouseMove(msg
);
519 case WM_INITMENUPOPUP
:
520 TRACE("WM_INITMENUPOPUP %p %p\n", msg
->wParam
, msg
->lParam
);
521 m_selectedMenu
= reinterpret_cast<HMENU
>(msg
->lParam
);
523 m_selectedItemFlags
= 0;
526 TRACE("WM_MENUSELECT %p %p\n", msg
->wParam
, msg
->lParam
);
527 m_selectedMenu
= reinterpret_cast<HMENU
>(msg
->lParam
);
528 m_selectedItem
= GET_X_LPARAM(msg
->wParam
);
529 m_selectedItemFlags
= HIWORD(msg
->wParam
);
535 if (m_current
->hmenu
== m_selectedMenu
)
537 m_parent
->mb
->_MenuItemSelect(VK_LEFT
);
541 if (m_selectedItem
< 0 || !(m_selectedItemFlags
& MF_POPUP
))
543 m_parent
->mb
->_MenuItemSelect(VK_RIGHT
);
554 return CallNextHookEx(m_hMsgFilterHook
, nCode
, hookWParam
, hookLParam
);
557 LRESULT
CMenuFocusManager::GetMsgHook(INT nCode
, WPARAM hookWParam
, LPARAM hookLParam
)
559 BOOL isLButton
= FALSE
;
561 return CallNextHookEx(m_hGetMsgHook
, nCode
, hookWParam
, hookLParam
);
563 if (nCode
== HC_ACTION
)
565 BOOL callNext
= TRUE
;
566 MSG
* msg
= reinterpret_cast<MSG
*>(hookLParam
);
569 switch (msg
->message
)
571 case WM_CAPTURECHANGED
:
574 TRACE("Capture lost.\n");
575 m_captureHwnd
= NULL
;
579 case WM_NCLBUTTONDOWN
:
584 if (m_menuBar
&& m_current
->type
== MenuPopupEntry
)
587 HWND child
= WindowFromPoint(pt
);
588 BOOL hoveringMenuBar
= m_menuBar
->mb
->IsWindowOwner(child
) == S_OK
;
591 m_current
->mb
->_MenuItemSelect(MPOS_FULLCANCEL
);
596 if (m_current
->type
== MenuPopupEntry
)
598 HWND child
= WindowFromPoint(pt
);
600 if (IsTrackedWindowOrParent(child
) != S_OK
)
602 m_current
->mb
->_MenuItemSelect(MPOS_FULLCANCEL
);
607 ProcessMouseDown(msg
, isLButton
);
612 ProcessMouseUp(msg
, isLButton
);
617 ProcessMouseUp(msg
, isLButton
);
620 callNext
= ProcessMouseMove(msg
);
623 callNext
= ProcessMouseMove(msg
);
624 //callNext = ProcessMouseLeave(msg);
628 if (m_current
->type
== MenuPopupEntry
)
630 DisableMouseTrack(m_current
->hwnd
, TRUE
);
637 m_current
->mb
->_MenuItemSelect(MPOS_FULLCANCEL
);
640 m_current
->mb
->_MenuItemSelect(MPOS_EXECUTE
);
643 m_current
->mb
->_MenuItemSelect(VK_LEFT
);
646 m_current
->mb
->_MenuItemSelect(VK_RIGHT
);
649 m_current
->mb
->_MenuItemSelect(VK_UP
);
652 m_current
->mb
->_MenuItemSelect(VK_DOWN
);
655 msg
->message
= WM_NULL
;
666 return CallNextHookEx(m_hGetMsgHook
, nCode
, hookWParam
, hookLParam
);
669 HRESULT
CMenuFocusManager::PlaceHooks()
673 WARN("GETMESSAGE hook already placed!\n");
676 if (m_hMsgFilterHook
)
678 WARN("MSGFILTER hook already placed!\n");
681 if (m_current
->type
== TrackedMenuEntry
)
683 TRACE("Entering MSGFILTER hook...\n");
684 m_hMsgFilterHook
= SetWindowsHookEx(WH_MSGFILTER
, s_MsgFilterHook
, NULL
, m_threadId
);
688 TRACE("Entering GETMESSAGE hook...\n");
689 m_hGetMsgHook
= SetWindowsHookEx(WH_GETMESSAGE
, s_GetMsgHook
, NULL
, m_threadId
);
694 HRESULT
CMenuFocusManager::RemoveHooks()
696 if (m_hMsgFilterHook
)
698 TRACE("Removing MSGFILTER hook...\n");
699 UnhookWindowsHookEx(m_hMsgFilterHook
);
700 m_hMsgFilterHook
= NULL
;
704 TRACE("Removing GETMESSAGE hook...\n");
705 UnhookWindowsHookEx(m_hGetMsgHook
);
706 m_hGetMsgHook
= NULL
;
711 // Used to update the tracking info to account for a change in the top-level menu
712 HRESULT
CMenuFocusManager::UpdateFocus()
715 StackEntry
* old
= m_current
;
717 TRACE("UpdateFocus\n");
719 // Assign the new current item
721 m_current
= &(m_bandStack
[m_bandCount
- 1]);
725 // Remove the menu capture if necesary
726 if (!m_current
|| m_current
->type
!= MenuPopupEntry
)
728 SetMenuCapture(NULL
);
729 if (old
&& old
->type
== MenuPopupEntry
&& m_PreviousForeground
)
731 ::SetForegroundWindow(m_PreviousForeground
);
732 m_PreviousForeground
= NULL
;
736 // Obtain the top-level window for the new active menu
737 if (m_current
&& m_current
->type
!= TrackedMenuEntry
)
739 hr
= m_current
->mb
->_GetTopLevelWindow(&(m_current
->hwnd
));
740 if (FAILED_UNEXPECTEDLY(hr
))
744 // Refresh the parent pointer
745 if (m_bandCount
>= 2)
747 m_parent
= &(m_bandStack
[m_bandCount
- 2]);
748 _ASSERT(m_parent
->type
!= TrackedMenuEntry
);
755 // Refresh the menubar pointer, if applicable
756 if (m_bandCount
>= 1 && m_bandStack
[0].type
== MenuBarEntry
)
758 m_menuBar
= &(m_bandStack
[0]);
765 // Remove the old hooks if the menu type changed, or we don't have a menu anymore
766 if (old
&& (!m_current
|| old
->type
!= m_current
->type
))
768 if (m_current
&& m_current
->type
!= TrackedMenuEntry
)
770 DisableMouseTrack(m_current
->hwnd
, FALSE
);
774 if (FAILED_UNEXPECTEDLY(hr
))
778 // And place new ones if necessary
779 if (m_current
&& (!old
|| old
->type
!= m_current
->type
))
782 if (FAILED_UNEXPECTEDLY(hr
))
786 // Give the user a chance to move the mouse to the new menu
789 DisableMouseTrack(m_parent
->hwnd
, TRUE
);
792 if (m_current
&& m_current
->type
== MenuPopupEntry
)
794 if (m_captureHwnd
== NULL
)
796 // We need to restore the capture after a non-shell submenu or context menu is shown
797 StackEntry
* topMenu
= m_bandStack
;
798 if (topMenu
->type
== MenuBarEntry
)
801 // Get the top-level window from the top popup
802 CComPtr
<IServiceProvider
> bandSite
;
803 CComPtr
<IOleWindow
> deskBar
;
804 hr
= topMenu
->mb
->GetSite(IID_PPV_ARG(IServiceProvider
, &bandSite
));
807 hr
= bandSite
->QueryService(SID_SMenuPopup
, IID_PPV_ARG(IOleWindow
, &deskBar
));
811 CComPtr
<IOleWindow
> deskBarSite
;
812 hr
= IUnknown_GetSite(deskBar
, IID_PPV_ARG(IOleWindow
, &deskBarSite
));
816 // FIXME: Find the correct place for this
818 hr
= deskBarSite
->GetWindow(&hWndOwner
);
822 m_PreviousForeground
= ::GetForegroundWindow();
823 if (m_PreviousForeground
!= hWndOwner
)
824 ::SetForegroundWindow(hWndOwner
);
826 m_PreviousForeground
= NULL
;
828 // Get the HWND of the top-level window
830 hr
= deskBar
->GetWindow(&hWndSite
);
833 SetMenuCapture(hWndSite
);
837 if (!m_parent
|| m_parent
->type
== MenuBarEntry
)
839 if (old
&& old
->type
== TrackedMenuEntry
)
841 // FIXME: Debugging code, probably not right
845 ScreenToClient(m_current
->hwnd
, &pt2
);
846 GetClientRect(m_current
->hwnd
, &rc2
);
847 if (PtInRect(&rc2
, pt2
))
848 SendMessage(m_current
->hwnd
, WM_MOUSEMOVE
, 0, MAKELPARAM(pt2
.x
, pt2
.y
));
850 SendMessage(m_current
->hwnd
, WM_MOUSELEAVE
, 0, 0);
855 _ASSERT(!m_parent
|| m_parent
->type
!= TrackedMenuEntry
);
860 // Begin tracking top-level menu bar (for file browser windows)
861 HRESULT
CMenuFocusManager::PushMenuBar(CMenuBand
* mb
)
863 TRACE("PushMenuBar %p\n", mb
);
867 _ASSERT(m_bandCount
== 0);
869 HRESULT hr
= PushToArray(MenuBarEntry
, mb
, NULL
);
870 if (FAILED_UNEXPECTEDLY(hr
))
873 return UpdateFocus();
876 // Begin tracking a shell menu popup (start menu or submenus)
877 HRESULT
CMenuFocusManager::PushMenuPopup(CMenuBand
* mb
)
879 TRACE("PushTrackedPopup %p\n", mb
);
883 _ASSERT(!m_current
|| m_current
->type
!= TrackedMenuEntry
);
885 HRESULT hr
= PushToArray(MenuPopupEntry
, mb
, NULL
);
886 if (FAILED_UNEXPECTEDLY(hr
))
893 if (m_parent
&& m_parent
->type
!= TrackedMenuEntry
)
895 m_parent
->mb
->_SetChildBand(mb
);
896 mb
->_SetParentBand(m_parent
->mb
);
902 // Begin tracking a system popup submenu (submenu of the file browser windows)
903 HRESULT
CMenuFocusManager::PushTrackedPopup(HMENU popup
)
905 TRACE("PushTrackedPopup %p\n", popup
);
907 _ASSERT(m_bandCount
> 0);
908 _ASSERT(!m_current
|| m_current
->type
!= TrackedMenuEntry
);
910 HRESULT hr
= PushToArray(TrackedMenuEntry
, NULL
, popup
);
911 if (FAILED_UNEXPECTEDLY(hr
))
914 TRACE("PushTrackedPopup %p\n", popup
);
915 m_selectedMenu
= popup
;
917 m_selectedItemFlags
= 0;
919 return UpdateFocus();
922 // Stop tracking the menubar
923 HRESULT
CMenuFocusManager::PopMenuBar(CMenuBand
* mb
)
929 TRACE("PopMenuBar %p\n", mb
);
931 if (m_current
== m_entryUnderMouse
)
933 m_entryUnderMouse
= NULL
;
936 hr
= PopFromArray(&type
, &mbc
, NULL
);
937 if (FAILED_UNEXPECTEDLY(hr
))
943 _ASSERT(type
== MenuBarEntry
);
944 if (type
!= MenuBarEntry
)
950 mbc
->_SetParentBand(NULL
);
955 if (FAILED_UNEXPECTEDLY(hr
))
960 _ASSERT(m_current
->type
!= TrackedMenuEntry
);
961 m_current
->mb
->_SetChildBand(NULL
);
967 // Stop tracking a shell menu
968 HRESULT
CMenuFocusManager::PopMenuPopup(CMenuBand
* mb
)
974 TRACE("PopMenuPopup %p\n", mb
);
976 if (m_current
== m_entryUnderMouse
)
978 m_entryUnderMouse
= NULL
;
983 hr
= PopFromArray(&type
, &mbc
, NULL
);
984 if (FAILED_UNEXPECTEDLY(hr
))
990 _ASSERT(type
== MenuPopupEntry
);
991 if (type
!= MenuPopupEntry
)
997 mbc
->_SetParentBand(NULL
);
1002 if (FAILED_UNEXPECTEDLY(hr
))
1007 _ASSERT(m_current
->type
!= TrackedMenuEntry
);
1008 m_current
->mb
->_SetChildBand(NULL
);
1014 // Stop tracking a system popup submenu
1015 HRESULT
CMenuFocusManager::PopTrackedPopup(HMENU popup
)
1017 StackEntryType type
;
1021 TRACE("PopTrackedPopup %p\n", popup
);
1023 hr
= PopFromArray(&type
, NULL
, &hmenu
);
1024 if (FAILED_UNEXPECTEDLY(hr
))
1030 _ASSERT(type
== TrackedMenuEntry
);
1031 if (type
!= TrackedMenuEntry
)
1038 if (FAILED_UNEXPECTEDLY(hr
))