ReactOS  0.4.15-dev-4936-gc06ccce
CMenuFocusManager.cpp
Go to the documentation of this file.
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 
21 /*
22 This file implements the CMenuFocusManager class.
23 
24 This class manages the shell menus, by overriding the hot-tracking behaviour.
25 
26 For the shell menus, it uses a GetMessage hook,
27 where it intercepts messages directed to the menu windows.
28 
29 In order to show submenus using system popups, it also has a MessageFilter hook.
30 
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.
34 
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.
37 
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.
40 
41 */
42 #include "shellmenu.h"
43 #include <windowsx.h>
44 #include <commoncontrols.h>
45 #include <shlwapi_undoc.h>
46 
47 #include "CMenuFocusManager.h"
48 #include "CMenuToolbars.h"
49 #include "CMenuBand.h"
50 
51 #if DBG
52 # undef _ASSERT
53 # define _ASSERT(x) DbgAssert(!!(x), __FILE__, __LINE__, #x)
54 
55 bool DbgAssert(bool x, const char * filename, int line, const char * expr)
56 {
57  if (!x)
58  {
59  char szMsg[512];
60  const char *fname;
61 
62  fname = strrchr(filename, '\\');
63  if (fname == NULL)
64  {
65  fname = strrchr(filename, '/');
66  }
67 
68  if (fname == NULL)
69  fname = filename;
70  else
71  fname++;
72 
73  sprintf(szMsg, "%s:%d: Assertion failed: %s\n", fname, line, expr);
74 
75  OutputDebugStringA(szMsg);
76 
77  __debugbreak();
78  }
79  return x;
80 }
81 #else
82 # undef _ASSERT
83 # define _ASSERT(x) (!!(x))
84 #endif
85 
86 WINE_DEFAULT_DEBUG_CHANNEL(CMenuFocus);
87 
89 
90 // Gets the thread's assigned manager without refcounting
92 {
93  return reinterpret_cast<CMenuFocusManager *>(TlsGetValue(TlsIndex));
94 }
95 
96 // Obtains a manager for the thread, with refcounting
98 {
100 
101  if (!TlsIndex)
102  {
103  if ((TlsIndex = TlsAlloc()) == TLS_OUT_OF_INDEXES)
104  return NULL;
105  }
106 
107  obj = GetManager();
108 
109  if (!obj)
110  {
111  obj = new CComObject<CMenuFocusManager>();
113  }
114 
115  obj->AddRef();
116 
117  return obj;
118 }
119 
120 // Releases a previously acquired manager, and deletes it if the refcount reaches 0
122 {
123  if (!obj->Release())
124  {
126  }
127 }
128 
130 {
131  return GetManager()->MsgFilterHook(nCode, wParam, lParam);
132 }
133 
135 {
136  return GetManager()->GetMsgHook(nCode, wParam, lParam);
137 }
138 
140 {
141  if (m_bandCount >= MAX_RECURSE)
142  return E_OUTOFMEMORY;
143 
145  m_bandStack[m_bandCount].mb = mb;
147  m_bandCount++;
148 
149  return S_OK;
150 }
151 
153 {
154  if (pType) *pType = NoEntry;
155  if (pMb) *pMb = NULL;
156  if (pHmenu) *pHmenu = NULL;
157 
158  if (m_bandCount <= 0)
159  return S_FALSE;
160 
161  m_bandCount--;
162 
163  if (pType) *pType = m_bandStack[m_bandCount].type;
164  if (*pType == TrackedMenuEntry)
165  {
166  if (pHmenu) *pHmenu = m_bandStack[m_bandCount].hmenu;
167  }
168  else
169  {
170  if (pMb) *pMb = m_bandStack[m_bandCount].mb;
171  }
172 
173  return S_OK;
174 }
175 
177  m_current(NULL),
178  m_parent(NULL),
179  m_hMsgFilterHook(NULL),
180  m_hGetMsgHook(NULL),
181  m_mouseTrackDisabled(FALSE),
182  m_captureHwnd(0),
183  m_hwndUnderMouse(NULL),
184  m_entryUnderMouse(NULL),
185  m_selectedMenu(NULL),
186  m_selectedItem(0),
187  m_selectedItemFlags(0),
188  m_movedSinceDown(FALSE),
189  m_windowAtDown(NULL),
190  m_PreviousForeground(NULL),
191  m_bandCount(0),
192  m_menuDepth(0)
193 {
194  m_ptPrev.x = 0;
195  m_ptPrev.y = 0;
197 }
198 
200 {
201 }
202 
203 // Used so that the toolbar can properly ignore mouse events, when the menu is being used with the keyboard
205 {
206  BOOL bDisable = FALSE;
207  BOOL lastDisable = FALSE;
208 
209  int i = m_bandCount;
210  while (--i >= 0)
211  {
213 
214  if (entry.type != TrackedMenuEntry)
215  {
216  HWND hwnd;
217  HRESULT hr = entry.mb->_GetTopLevelWindow(&hwnd);
218  if (FAILED_UNEXPECTEDLY(hr))
219  break;
220 
221  if (hwnd == parent)
222  {
223  lastDisable = disableThis;
224  entry.mb->_DisableMouseTrack(disableThis);
225  bDisable = TRUE;
226  }
227  else
228  {
229  lastDisable = bDisable;
230  entry.mb->_DisableMouseTrack(bDisable);
231  }
232  }
233  }
234  m_mouseTrackDisabled = lastDisable;
235 }
236 
238 {
239  if (m_captureHwnd != child)
240  {
241  if (child)
242  {
245  TRACE("Capturing %p\n", child);
246  }
247  else
248  {
251  TRACE("Capture is now off\n");
252  }
253 
254  }
255 }
256 
258 {
259  if (pentry)
260  *pentry = NULL;
261 
262  for (int i = m_bandCount; --i >= 0;)
263  {
265 
266  if (entry.type != TrackedMenuEntry)
267  {
268  HRESULT hr = entry.mb->IsWindowOwner(hWnd);
269  if (FAILED_UNEXPECTEDLY(hr))
270  return hr;
271  if (hr == S_OK)
272  {
273  if (pentry)
274  *pentry = &entry;
275  return S_OK;
276  }
277  }
278  }
279 
280  return S_FALSE;
281 }
282 
284 {
285  for (int i = m_bandCount; --i >= 0;)
286  {
288 
289  if (entry.type != TrackedMenuEntry)
290  {
291  HRESULT hr = entry.mb->IsWindowOwner(hWnd);
292  if (FAILED_UNEXPECTEDLY(hr))
293  return hr;
294  if (hr == S_OK)
295  return S_OK;
296  if (entry.mb->_IsPopup() == S_OK)
297  {
298  CComPtr<IUnknown> site;
299  CComPtr<IOleWindow> pw;
300  hr = entry.mb->GetSite(IID_PPV_ARG(IUnknown, &site));
301  if (FAILED_UNEXPECTEDLY(hr))
302  continue;
303  hr = IUnknown_QueryService(site, SID_SMenuBandParent, IID_PPV_ARG(IOleWindow, &pw));
304  if (FAILED_UNEXPECTEDLY(hr))
305  continue;
306 
307  HWND hParent;
308  if (pw->GetWindow(&hParent) == S_OK && hParent == hWnd)
309  return S_OK;
310  }
311  }
312  }
313 
314  return S_FALSE;
315 }
316 
318 {
319  HWND child;
320  int iHitTestResult = -1;
321 
322  POINT pt2 = { GET_X_LPARAM(msg->lParam), GET_Y_LPARAM(msg->lParam) };
323  ClientToScreen(msg->hwnd, &pt2);
324 
325  POINT pt = msg->pt;
326 
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)
330  return TRUE;
331 
333 
334  m_ptPrev = pt;
335 
337 
338  StackEntry * entry = NULL;
339  if (IsTrackedWindow(child, &entry) == S_OK)
340  {
341  TRACE("MouseMove\n");
342  }
343 
344  BOOL isTracking = FALSE;
345  if (entry && (entry->type == MenuBarEntry || m_current->type != TrackedMenuEntry))
346  {
348  iHitTestResult = SendMessageW(child, TB_HITTEST, 0, (LPARAM) &pt);
349  isTracking = entry->mb->_IsTracking();
350 
351  if (SendMessage(child, WM_USER_ISTRACKEDITEM, iHitTestResult, 0) == S_FALSE)
352  {
353  // The current tracked item has changed, notify the toolbar
354 
355  TRACE("Hot item tracking detected a change (capture=%p / cCapture=%p)...\n", m_captureHwnd, cCapture);
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));
361  return FALSE;
362  }
363  }
364 
365  if (m_entryUnderMouse != entry)
366  {
367  // Mouse moved away from a tracked window
368  if (m_entryUnderMouse)
369  {
371  }
372  }
373 
374  if (m_hwndUnderMouse != child)
375  {
376  if (entry)
377  {
378  // Mouse moved to a tracked window
379  if (m_current->type == MenuPopupEntry)
380  {
381  ScreenToClient(child, &pt2);
382  SendMessage(child, WM_MOUSEMOVE, msg->wParam, MAKELPARAM(pt2.x, pt2.y));
383  }
384  }
385 
388  }
389 
390  if (m_current->type == MenuPopupEntry)
391  {
394  }
395 
396  return TRUE;
397 }
398 
400 {
401  HWND child;
402  int iHitTestResult = -1;
403 
404  TRACE("ProcessMouseDown %d %d %d\n", msg->message, msg->wParam, msg->lParam);
405 
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)
409  {
410  TRACE("Foreign capture active.\n");
411  return TRUE;
412  }
413 
414  POINT pt = msg->pt;
415 
417 
418  StackEntry * entry = NULL;
419  if (IsTrackedWindow(child, &entry) != S_OK)
420  {
421  TRACE("Foreign window detected.\n");
422  return TRUE;
423  }
424 
425  if (entry->type == MenuBarEntry)
426  {
427  if (entry != m_current)
428  {
429  TRACE("Menubar with popup active.\n");
430  return TRUE;
431  }
432  }
433 
434  if (entry)
435  {
437  iHitTestResult = SendMessageW(child, TB_HITTEST, 0, (LPARAM) &pt);
438 
439  if (iHitTestResult >= 0)
440  {
441  TRACE("MouseDown send %d\n", iHitTestResult);
442  entry->mb->_MenuBarMouseDown(child, iHitTestResult, isLButton);
443  }
444  }
445 
446  msg->message = WM_NULL;
447 
450 
451  TRACE("MouseDown end\n");
452 
453  return TRUE;
454 }
455 
457 {
458  HWND child;
459  int iHitTestResult = -1;
460 
461  TRACE("ProcessMouseUp %d %d %d\n", msg->message, msg->wParam, msg->lParam);
462 
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)
466  return TRUE;
467 
468  POINT pt = msg->pt;
469 
471 
472  StackEntry * entry = NULL;
473  if (IsTrackedWindow(child, &entry) != S_OK)
474  return TRUE;
475 
476  if (entry)
477  {
479  iHitTestResult = SendMessageW(child, TB_HITTEST, 0, (LPARAM) &pt);
480 
481  if (iHitTestResult >= 0)
482  {
483  TRACE("MouseUp send %d\n", iHitTestResult);
484  entry->mb->_MenuBarMouseUp(child, iHitTestResult, isLButton);
485  }
486  }
487 
488  return TRUE;
489 }
490 
492 {
493  if (nCode < 0)
494  return CallNextHookEx(m_hMsgFilterHook, nCode, hookWParam, hookLParam);
495 
496  if (nCode == MSGF_MENU)
497  {
498  BOOL callNext = TRUE;
499  MSG* msg = reinterpret_cast<MSG*>(hookLParam);
500 
501  switch (msg->message)
502  {
503  case WM_LBUTTONDOWN:
504  case WM_RBUTTONDOWN:
506  {
507  POINT pt = msg->pt;
509  BOOL hoveringMenuBar = m_menuBar->mb->IsWindowOwner(child) == S_OK;
510  if (hoveringMenuBar)
511  {
513  }
514  }
515  break;
516  case WM_MOUSEMOVE:
517  callNext = ProcessMouseMove(msg);
518  break;
519  case WM_INITMENUPOPUP:
520  TRACE("WM_INITMENUPOPUP %p %p\n", msg->wParam, msg->lParam);
521  m_selectedMenu = reinterpret_cast<HMENU>(msg->lParam);
522  m_selectedItem = -1;
524  break;
525  case WM_MENUSELECT:
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);
530  break;
531  case WM_KEYDOWN:
532  switch (msg->wParam)
533  {
534  case VK_LEFT:
536  {
538  }
539  break;
540  case VK_RIGHT:
542  {
544  }
545  break;
546  }
547  break;
548  }
549 
550  if (!callNext)
551  return 1;
552  }
553 
554  return CallNextHookEx(m_hMsgFilterHook, nCode, hookWParam, hookLParam);
555 }
556 
557 LRESULT CMenuFocusManager::GetMsgHook(INT nCode, WPARAM hookWParam, LPARAM hookLParam)
558 {
559  BOOL isLButton = FALSE;
560  if (nCode < 0)
561  return CallNextHookEx(m_hGetMsgHook, nCode, hookWParam, hookLParam);
562 
563  if (nCode == HC_ACTION)
564  {
565  BOOL callNext = TRUE;
566  MSG* msg = reinterpret_cast<MSG*>(hookLParam);
567  POINT pt = msg->pt;
568 
569  switch (msg->message)
570  {
571  case WM_CAPTURECHANGED:
572  if (m_captureHwnd)
573  {
574  TRACE("Capture lost.\n");
576  }
577  break;
578 
579  case WM_NCLBUTTONDOWN:
580  case WM_LBUTTONDBLCLK:
581  case WM_LBUTTONDOWN:
582  isLButton = TRUE;
583  TRACE("LB\n");
584 
586  {
587  POINT pt = msg->pt;
589  BOOL hoveringMenuBar = m_menuBar->mb->IsWindowOwner(child) == S_OK;
590  if (hoveringMenuBar)
591  {
592  m_current->mb->_MenuItemSelect(MPOS_FULLCANCEL);
593  break;
594  }
595  }
596 
597  if (m_current->type == MenuPopupEntry)
598  {
600 
602  {
603  m_current->mb->_MenuItemSelect(MPOS_FULLCANCEL);
604  break;
605  }
606  }
607 
608  ProcessMouseDown(msg, isLButton);
609 
610  break;
611  case WM_NCRBUTTONUP:
612  case WM_RBUTTONUP:
613  ProcessMouseUp(msg, isLButton);
614  break;
615  case WM_NCLBUTTONUP:
616  case WM_LBUTTONUP:
617  isLButton = TRUE;
618  ProcessMouseUp(msg, isLButton);
619  break;
620  case WM_MOUSEMOVE:
621  callNext = ProcessMouseMove(msg);
622  break;
623  case WM_MOUSELEAVE:
624  callNext = ProcessMouseMove(msg);
625  //callNext = ProcessMouseLeave(msg);
626  break;
627  case WM_SYSKEYDOWN:
628  case WM_KEYDOWN:
629  if (m_current->type == MenuPopupEntry)
630  {
632  switch (msg->wParam)
633  {
634  case VK_ESCAPE:
635  case VK_MENU:
636  case VK_LMENU:
637  case VK_RMENU:
638  m_current->mb->_MenuItemSelect(MPOS_FULLCANCEL);
639  break;
640  case VK_RETURN:
641  m_current->mb->_MenuItemSelect(MPOS_EXECUTE);
642  break;
643  case VK_LEFT:
645  break;
646  case VK_RIGHT:
648  break;
649  case VK_UP:
651  break;
652  case VK_DOWN:
654  break;
655  }
656  msg->message = WM_NULL;
657  msg->lParam = 0;
658  msg->wParam = 0;
659  }
660  break;
661  }
662 
663  if (!callNext)
664  return 1;
665  }
666 
667  return CallNextHookEx(m_hGetMsgHook, nCode, hookWParam, hookLParam);
668 }
669 
671 {
672  if (m_hGetMsgHook)
673  {
674  WARN("GETMESSAGE hook already placed!\n");
675  return S_OK;
676  }
677  if (m_hMsgFilterHook)
678  {
679  WARN("MSGFILTER hook already placed!\n");
680  return S_OK;
681  }
683  {
684  TRACE("Entering MSGFILTER hook...\n");
686  }
687  else
688  {
689  TRACE("Entering GETMESSAGE hook...\n");
691  }
692  return S_OK;
693 }
694 
696 {
697  if (m_hMsgFilterHook)
698  {
699  TRACE("Removing MSGFILTER hook...\n");
702  }
703  if (m_hGetMsgHook)
704  {
705  TRACE("Removing GETMESSAGE hook...\n");
708  }
709  return S_OK;
710 }
711 
712 // Used to update the tracking info to account for a change in the top-level menu
714 {
715  HRESULT hr;
716  StackEntry * old = m_current;
717 
718  TRACE("UpdateFocus\n");
719 
720  // Assign the new current item
721  if (m_bandCount > 0)
723  else
724  m_current = NULL;
725 
726  // Remove the menu capture if necesary
728  {
730  if (old && old->type == MenuPopupEntry && m_PreviousForeground)
731  {
734  }
735  }
736 
737  // Obtain the top-level window for the new active menu
739  {
741  if (FAILED_UNEXPECTEDLY(hr))
742  return hr;
743  }
744 
745  // Refresh the parent pointer
746  if (m_bandCount >= 2)
747  {
748  m_parent = &(m_bandStack[m_bandCount - 2]);
750  }
751  else
752  {
753  m_parent = NULL;
754  }
755 
756  // Refresh the menubar pointer, if applicable
757  if (m_bandCount >= 1 && m_bandStack[0].type == MenuBarEntry)
758  {
759  m_menuBar = &(m_bandStack[0]);
760  }
761  else
762  {
763  m_menuBar = NULL;
764  }
765 
766  // Remove the old hooks if the menu type changed, or we don't have a menu anymore
767  if (old && (!m_current || old->type != m_current->type))
768  {
770  {
772  }
773 
774  hr = RemoveHooks();
775  if (FAILED_UNEXPECTEDLY(hr))
776  return hr;
777  }
778 
779  // And place new ones if necessary
780  if (m_current && (!old || old->type != m_current->type))
781  {
782  hr = PlaceHooks();
783  if (FAILED_UNEXPECTEDLY(hr))
784  return hr;
785  }
786 
787  // Give the user a chance to move the mouse to the new menu
788  if (m_parent)
789  {
791  }
792 
794  {
795  if (m_captureHwnd == NULL)
796  {
797  // We need to restore the capture after a non-shell submenu or context menu is shown
798  StackEntry * topMenu = m_bandStack;
799  if (topMenu->type == MenuBarEntry)
800  topMenu++;
801 
802  // Get the top-level window from the top popup
803  CComPtr<IServiceProvider> bandSite;
804  CComPtr<IOleWindow> deskBar;
805  hr = topMenu->mb->GetSite(IID_PPV_ARG(IServiceProvider, &bandSite));
806  if (FAILED(hr))
807  goto NoCapture;
808  hr = bandSite->QueryService(SID_SMenuPopup, IID_PPV_ARG(IOleWindow, &deskBar));
809  if (FAILED(hr))
810  goto NoCapture;
811 
812  CComPtr<IOleWindow> deskBarSite;
813  hr = IUnknown_GetSite(deskBar, IID_PPV_ARG(IOleWindow, &deskBarSite));
814  if (FAILED(hr))
815  goto NoCapture;
816 
817  // FIXME: Find the correct place for this
818  HWND hWndOwner;
819  hr = deskBarSite->GetWindow(&hWndOwner);
820  if (FAILED(hr))
821  goto NoCapture;
822 
824  if (m_PreviousForeground != hWndOwner)
825  ::SetForegroundWindow(hWndOwner);
826  else
828 
829  // Get the HWND of the top-level window
830  HWND hWndSite;
831  hr = deskBar->GetWindow(&hWndSite);
832  if (FAILED(hr))
833  goto NoCapture;
834  SetMenuCapture(hWndSite);
835  }
836 NoCapture:
837 
838  if (!m_parent || m_parent->type == MenuBarEntry)
839  {
840  if (old && old->type == TrackedMenuEntry)
841  {
842  // FIXME: Debugging code, probably not right
843  POINT pt2;
844  RECT rc2;
845  GetCursorPos(&pt2);
846  ScreenToClient(m_current->hwnd, &pt2);
848  if (PtInRect(&rc2, pt2))
850  else
852  }
853  }
854  }
855 
857 
858  return S_OK;
859 }
860 
861 // Begin tracking top-level menu bar (for file browser windows)
863 {
864  TRACE("PushMenuBar %p\n", mb);
865 
866  mb->AddRef();
867 
868  _ASSERT(m_bandCount == 0);
869 
871  if (FAILED_UNEXPECTEDLY(hr))
872  return hr;
873 
874  return UpdateFocus();
875 }
876 
877 // Begin tracking a shell menu popup (start menu or submenus)
879 {
880  TRACE("PushTrackedPopup %p\n", mb);
881 
882  mb->AddRef();
883 
885 
887  if (FAILED_UNEXPECTEDLY(hr))
888  return hr;
889 
890  hr = UpdateFocus();
891 
892  m_menuDepth++;
893 
895  {
896  m_parent->mb->_SetChildBand(mb);
897  mb->_SetParentBand(m_parent->mb);
898  }
899 
900  return hr;
901 }
902 
903 // Begin tracking a system popup submenu (submenu of the file browser windows)
905 {
906  TRACE("PushTrackedPopup %p\n", popup);
907 
908  _ASSERT(m_bandCount > 0);
910 
912  if (FAILED_UNEXPECTEDLY(hr))
913  return hr;
914 
915  TRACE("PushTrackedPopup %p\n", popup);
916  m_selectedMenu = popup;
917  m_selectedItem = -1;
919 
920  return UpdateFocus();
921 }
922 
923 // Stop tracking the menubar
925 {
927  CMenuBand * mbc;
928  HRESULT hr;
929 
930  TRACE("PopMenuBar %p\n", mb);
931 
933  {
935  }
936 
937  hr = PopFromArray(&type, &mbc, NULL);
938  if (FAILED_UNEXPECTEDLY(hr))
939  {
940  UpdateFocus();
941  return hr;
942  }
943 
945  if (type != MenuBarEntry)
946  return E_FAIL;
947 
948  if (!mbc)
949  return E_FAIL;
950 
951  mbc->_SetParentBand(NULL);
952 
953  mbc->Release();
954 
955  hr = UpdateFocus();
956  if (FAILED_UNEXPECTEDLY(hr))
957  return hr;
958 
959  if (m_current)
960  {
963  }
964 
965  return S_OK;
966 }
967 
968 // Stop tracking a shell menu
970 {
972  CMenuBand * mbc;
973  HRESULT hr;
974 
975  TRACE("PopMenuPopup %p\n", mb);
976 
978  {
980  }
981 
982  m_menuDepth--;
983 
984  hr = PopFromArray(&type, &mbc, NULL);
985  if (FAILED_UNEXPECTEDLY(hr))
986  {
987  UpdateFocus();
988  return hr;
989  }
990 
992  if (type != MenuPopupEntry)
993  return E_FAIL;
994 
995  if (!mbc)
996  return E_FAIL;
997 
998  mbc->_SetParentBand(NULL);
999 
1000  mbc->Release();
1001 
1002  hr = UpdateFocus();
1003  if (FAILED_UNEXPECTEDLY(hr))
1004  return hr;
1005 
1006  if (m_current)
1007  {
1010  }
1011 
1012  return S_OK;
1013 }
1014 
1015 // Stop tracking a system popup submenu
1017 {
1019  HMENU hmenu;
1020  HRESULT hr;
1021 
1022  TRACE("PopTrackedPopup %p\n", popup);
1023 
1024  hr = PopFromArray(&type, NULL, &hmenu);
1025  if (FAILED_UNEXPECTEDLY(hr))
1026  {
1027  UpdateFocus();
1028  return hr;
1029  }
1030 
1032  if (type != TrackedMenuEntry)
1033  return E_FAIL;
1034 
1035  if (hmenu != popup)
1036  return E_FAIL;
1037 
1038  hr = UpdateFocus();
1039  if (FAILED_UNEXPECTEDLY(hr))
1040  return hr;
1041 
1042  return S_OK;
1043 }
#define WM_NCLBUTTONDOWN
Definition: winuser.h:1679
#define WM_NULL
Definition: winuser.h:1594
#define WM_USER_ISTRACKEDITEM
Definition: CMenuToolbars.h:25
HRESULT _BeforeCancelPopup()
Definition: CMenuBand.cpp:1101
#define GA_ROOT
Definition: winuser.h:2769
#define TB_HITTEST
Definition: commctrl.h:1268
HWND WINAPI GetAncestor(_In_ HWND, _In_ UINT)
HRESULT IsTrackedWindowOrParent(HWND hWnd)
#define WH_GETMESSAGE
Definition: winuser.h:33
StackEntry * m_current
static CMenuFocusManager * AcquireManager()
StackEntry * m_parent
long y
Definition: polytest.cpp:48
HRESULT WINAPI IUnknown_GetSite(LPUNKNOWN lpUnknown, REFIID iid, PVOID *lppSite)
Definition: ordinal.c:2593
BOOL WINAPI ClientToScreen(_In_ HWND, _Inout_ LPPOINT)
#define WM_LBUTTONDOWN
Definition: winuser.h:1763
HRESULT hr
Definition: shlfolder.c:183
static HMENU hmenu
Definition: win.c:66
HRESULT PushToArray(StackEntryType type, CMenuBand *mb, HMENU hmenu)
virtual HRESULT STDMETHODCALLTYPE GetSite(REFIID riid, PVOID *ppvSite)
Definition: CMenuBand.cpp:251
static IActiveScriptSite * site
Definition: script.c:149
long x
Definition: polytest.cpp:48
BOOL WINAPI TlsSetValue(IN DWORD Index, IN LPVOID Value)
Definition: thread.c:1276
#define TRUE
Definition: types.h:120
#define pt(x, y)
Definition: drawing.c:79
#define WM_INITMENUPOPUP
Definition: winuser.h:1733
#define VK_RMENU
Definition: winuser.h:2267
HRESULT PopTrackedPopup(HMENU popup)
HRESULT _GetTopLevelWindow(HWND *topLevel)
Definition: CMenuBand.cpp:874
TW_UINT32 TW_UINT16 TW_UINT16 MSG
Definition: twain.h:1827
#define WH_MSGFILTER
Definition: winuser.h:29
#define WARN(fmt,...)
Definition: debug.h:112
#define MAKELPARAM(l, h)
Definition: winuser.h:3988
#define WM_CAPTURECHANGED
Definition: winuser.h:1795
#define CALLBACK
Definition: compat.h:35
HWND hWnd
Definition: settings.c:17
#define GET_X_LPARAM(lp)
Definition: windowsx.h:274
#define VK_LEFT
Definition: winuser.h:2204
GLint GLint GLint GLint GLint x
Definition: gl.h:1548
static LRESULT CALLBACK s_GetMsgHook(INT nCode, WPARAM wParam, LPARAM lParam)
UINT_PTR WPARAM
Definition: windef.h:207
#define MSGF_MENU
Definition: winuser.h:1165
#define VK_DOWN
Definition: winuser.h:2207
HRESULT PushTrackedPopup(HMENU popup)
#define VK_MENU
Definition: winuser.h:2184
_Check_return_ _CRTIMP _CONST_RETURN char *__cdecl strrchr(_In_z_ const char *_Str, _In_ int _Ch)
#define VK_ESCAPE
Definition: winuser.h:2194
BOOL WINAPI GetCursorPos(_Out_ LPPOINT)
Definition: cursoricon.c:2639
const char * filename
Definition: ioapi.h:135
#define IID_PPV_ARG(Itype, ppType)
#define E_FAIL
Definition: ddrawi.h:102
void __cdecl __debugbreak(void)
Definition: intrin_ppc.h:698
int32_t INT
Definition: typedefs.h:58
Definition: query.h:86
HRESULT WINAPI IUnknown_QueryService(IUnknown *, REFGUID, REFIID, LPVOID *)
Definition: ordinal.c:1494
#define VK_RETURN
Definition: winuser.h:2181
static HWND child
Definition: cursoricon.c:298
WPARAM wParam
Definition: combotst.c:138
StackEntry * m_entryUnderMouse
GLsizei GLsizei GLuint * obj
Definition: glext.h:6042
#define WM_USER_CHANGETRACKEDITEM
Definition: CMenuToolbars.h:26
#define sprintf(buf, format,...)
Definition: sprintf.c:55
HRESULT PopMenuBar(CMenuBand *mb)
#define E_OUTOFMEMORY
Definition: ddrawi.h:100
#define VK_UP
Definition: winuser.h:2205
#define FALSE
Definition: types.h:117
HRESULT PushMenuBar(CMenuBand *mb)
unsigned int BOOL
Definition: ntddk_ex.h:94
#define WM_NCRBUTTONUP
Definition: winuser.h:1683
HRESULT _ChangeHotItem(CMenuToolbarBase *tb, INT id, DWORD dwFlags)
Definition: CMenuBand.cpp:880
HWND WINAPI GetCapture(void)
Definition: message.c:2881
#define WM_MOUSELEAVE
Definition: commctrl.h:4975
HRESULT PopMenuPopup(CMenuBand *mb)
#define WM_MENUSELECT
Definition: winuser.h:1734
#define S_FALSE
Definition: winerror.h:2357
#define HICF_MOUSE
Definition: commctrl.h:1326
HRESULT IsTrackedWindow(HWND hWnd, StackEntry **pentry=NULL)
#define WM_KEYDOWN
Definition: winuser.h:1702
LONG_PTR LPARAM
Definition: windef.h:208
Definition: parser.c:48
HRESULT _SetChildBand(CMenuBand *child)
Definition: CMenuBand.cpp:603
DWORD WINAPI GetCurrentThreadId(VOID)
Definition: thread.c:459
#define WM_RBUTTONDOWN
Definition: winuser.h:1766
#define PostMessage
Definition: winuser.h:5812
StackEntry * m_menuBar
LRESULT GetMsgHook(INT nCode, WPARAM wParam, LPARAM lParam)
#define TRACE(s)
Definition: solgame.cpp:4
LRESULT ProcessMouseUp(MSG *msg, BOOL isLButton)
#define MAX_RECURSE
r parent
Definition: btrfs.c:2979
LONG HRESULT
Definition: typedefs.h:79
virtual HRESULT STDMETHODCALLTYPE IsWindowOwner(HWND hWnd)
Definition: CMenuBand.cpp:757
#define FAILED_UNEXPECTEDLY(hr)
Definition: shellutils.h:82
#define SetWindowsHookEx
Definition: winuser.h:5836
unsigned long DWORD
Definition: ntddk_ex.h:95
#define _ASSERT(x)
#define WM_RBUTTONUP
Definition: winuser.h:1767
ULONG AddRef()
#define MF_POPUP
Definition: winuser.h:136
HRESULT _SetParentBand(CMenuBand *parent)
Definition: CMenuBand.cpp:614
#define VK_LMENU
Definition: winuser.h:2266
LRESULT MsgFilterHook(INT nCode, WPARAM wParam, LPARAM lParam)
WINE_DEFAULT_DEBUG_CHANNEL(CMenuFocus)
#define WM_CANCELMODE
Definition: winuser.h:1622
uint32_t entry
Definition: isohybrid.c:63
#define WM_LBUTTONDBLCLK
Definition: winuser.h:1765
DWORD WINAPI TlsAlloc(VOID)
Definition: thread.c:1100
#define TLS_OUT_OF_INDEXES
Definition: winbase.h:546
BOOL WINAPI UnhookWindowsHookEx(_In_ HHOOK)
#define VK_RIGHT
Definition: winuser.h:2206
static LRESULT CALLBACK s_MsgFilterHook(INT nCode, WPARAM wParam, LPARAM lParam)
BOOL WINAPI GetClientRect(_In_ HWND, _Out_ LPRECT)
HWND WINAPI SetCapture(_In_ HWND hWnd)
#define S_OK
Definition: intsafe.h:52
LRESULT WINAPI CallNextHookEx(_In_opt_ HHOOK, _In_ int, _In_ WPARAM, _In_ LPARAM)
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
#define HC_ACTION
Definition: winuser.h:48
LRESULT WINAPI SendMessageW(_In_ HWND, _In_ UINT, _In_ WPARAM, _In_ LPARAM)
#define WM_LBUTTONUP
Definition: winuser.h:1764
#define WM_MOUSEMOVE
Definition: winuser.h:1762
#define NULL
Definition: types.h:112
HWND WINAPI GetForegroundWindow(void)
Definition: ntwrapper.h:392
HWND WINAPI WindowFromPoint(_In_ POINT)
LRESULT ProcessMouseDown(MSG *msg, BOOL isLButton)
char mbc
static void ReleaseManager(CMenuFocusManager *obj)
#define GET_Y_LPARAM(lp)
Definition: windowsx.h:275
LPVOID WINAPI TlsGetValue(IN DWORD Index)
Definition: thread.c:1240
BOOL WINAPI PtInRect(_In_ LPCRECT, _In_ POINT)
#define msg(x)
Definition: auth_time.c:54
static CMenuFocusManager * GetManager()
BOOL WINAPI ReleaseCapture(void)
Definition: message.c:2890
#define SendMessage
Definition: winuser.h:5823
void SetMenuCapture(HWND child)
#define WM_SYSKEYDOWN
Definition: winuser.h:1706
#define WM_NCLBUTTONUP
Definition: winuser.h:1680
#define HIWORD(l)
Definition: typedefs.h:247
static DWORD TlsIndex
BOOL WINAPI SetForegroundWindow(_In_ HWND)
HRESULT PushMenuPopup(CMenuBand *mb)
static const WCHAR rc2[]
Definition: oid.c:1216
GLuint GLuint GLsizei GLenum type
Definition: gl.h:1545
BOOL WINAPI ScreenToClient(_In_ HWND, _Inout_ LPPOINT)
LONG_PTR LRESULT
Definition: windef.h:209
_In_ LONG _In_ HWND hwnd
Definition: winddi.h:4022
LRESULT ProcessMouseMove(MSG *msg)
StackEntry m_bandStack[MAX_RECURSE]
static const CLSID *static CLSID *static const GUID VARIANT VARIANT *static IServiceProvider DWORD *static HMENU
Definition: ordinal.c:60
HRESULT PopFromArray(StackEntryType *pType, CMenuBand **pMb, HMENU *pHmenu)
LPARAM lParam
Definition: combotst.c:139
void WINAPI SHIM_OBJ_NAME() OutputDebugStringA(LPCSTR lpOutputString)
Definition: ignoredbgout.c:18
void DisableMouseTrack(HWND parent, BOOL disableThis)
HRESULT _MenuItemSelect(DWORD changeType)
Definition: CMenuBand.cpp:954