user32: fix for the ending of menu tracking in the default handler of WM_CANCELMODE message.

Rein Klazes wijn at online.nl
Mon Mar 9 06:55:18 CDT 2009


---
 dlls/user32/controls.h   |    1 +
 dlls/user32/defwnd.c     |    2 +-
 dlls/user32/menu.c       |   32 ++++++++++++++++++++++++++++----
 dlls/user32/tests/menu.c |    6 ++----
 4 files changed, 32 insertions(+), 9 deletions(-)

diff --git a/dlls/user32/controls.h b/dlls/user32/controls.h
index 974cf5b..23d0959 100644
--- a/dlls/user32/controls.h
+++ b/dlls/user32/controls.h
@@ -88,6 +88,7 @@ extern void MENU_TrackKbdMenuBar( HWND hwnd, UINT wParam, WCHAR wChar ) DECLSPEC
 extern UINT MENU_DrawMenuBar( HDC hDC, LPRECT lprect,
                                 HWND hwnd, BOOL suppress_draw ) DECLSPEC_HIDDEN;
 extern UINT MENU_FindSubMenu( HMENU *hmenu, HMENU hSubTarget ) DECLSPEC_HIDDEN;
+extern void MENU_EndMenu( HWND) DECLSPEC_HIDDEN;
 
 /* nonclient area */
 extern LRESULT NC_HandleNCPaint( HWND hwnd , HRGN clip) DECLSPEC_HIDDEN;
diff --git a/dlls/user32/defwnd.c b/dlls/user32/defwnd.c
index 38d8def..6800a5a 100644
--- a/dlls/user32/defwnd.c
+++ b/dlls/user32/defwnd.c
@@ -618,7 +618,7 @@ static LRESULT DEFWND_DefWinProc( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lPa
 
     case WM_CANCELMODE:
         iMenuSysKey = 0;
-        if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD)) EndMenu();
+        MENU_EndMenu( hwnd);
         if (GetCapture() == hwnd) ReleaseCapture();
         break;
 
diff --git a/dlls/user32/menu.c b/dlls/user32/menu.c
index fc6f981..fda5965 100644
--- a/dlls/user32/menu.c
+++ b/dlls/user32/menu.c
@@ -176,6 +176,7 @@ static UINT     ODitemheight; /* default owner drawn item height */
 /* Use global popup window because there's no way 2 menus can
  * be tracked at the same time.  */
 static HWND top_popup;
+static HMENU top_popup_hmenu;
 
   /* Flag set by EndMenu() to force an exit from menu tracking */
 static BOOL fEndMenu = FALSE;
@@ -1884,8 +1885,10 @@ static BOOL MENU_ShowPopup( HWND hwndOwner, HMENU hmenu, UINT id, UINT flags,
                                 hwndOwner, 0, (HINSTANCE)GetWindowLongPtrW(hwndOwner, GWLP_HINSTANCE),
                                 (LPVOID)hmenu );
     if( !menu->hWnd ) return FALSE;
-    if (!top_popup) top_popup = menu->hWnd;
-
+    if (!top_popup) {
+        top_popup = menu->hWnd;
+        top_popup_hmenu = hmenu;
+    }
     /* Display the window */
 
     SetWindowPos( menu->hWnd, HWND_TOPMOST, 0, 0, 0, 0,
@@ -1953,7 +1956,10 @@ static void MENU_SelectItem( HWND hwndOwner, HMENU hmenu, UINT wIndex,
     if (lppop->FocusedItem == wIndex) return;
     if (lppop->wFlags & MF_POPUP) hdc = GetDC( lppop->hWnd );
     else hdc = GetDCEx( lppop->hWnd, 0, DCX_CACHE | DCX_WINDOW);
-    if (!top_popup) top_popup = lppop->hWnd;
+    if (!top_popup) {
+        top_popup = lppop->hWnd;
+        top_popup_hmenu = hmenu;
+    }
 
     SelectObject( hdc, get_menu_font(FALSE));
 
@@ -2462,6 +2468,20 @@ HWND MENU_IsMenuActive(void)
     return top_popup;
 }
 
+/**********************************************************************
+ *         MENU_EndMenu
+ *
+ * Calls EndMenu() if the hwnd parameter belongs to the menu owner
+ *
+ * Does the (menu stuff) of the default window handling of WM_CANCELMODE 
+ */
+void MENU_EndMenu( HWND hwnd)
+{
+    POPUPMENU *menu;
+    menu = top_popup_hmenu ? MENU_GetMenu( top_popup_hmenu) : NULL;
+    if( menu && hwnd == menu->hwndOwner) EndMenu();
+}
+
 /***********************************************************************
  *           MENU_PtMenu
  *
@@ -3363,6 +3383,7 @@ static BOOL MENU_ExitTracking(HWND hWnd)
     SendMessageW( hWnd, WM_EXITMENULOOP, 0, 0 );
     ShowCaret(0);
     top_popup = 0;
+    top_popup_hmenu = NULL;
     return TRUE;
 }
 
@@ -3530,7 +3551,10 @@ static LRESULT WINAPI PopupMenuWndProc( HWND hwnd, UINT message, WPARAM wParam,
 
     case WM_DESTROY:
         /* zero out global pointer in case resident popup window was destroyed. */
-        if (hwnd == top_popup) top_popup = 0;
+        if (hwnd == top_popup) {
+            top_popup = 0;
+            top_popup_hmenu = NULL;
+        }
         break;
 
     case WM_SHOWWINDOW:
diff --git a/dlls/user32/tests/menu.c b/dlls/user32/tests/menu.c
index f1240b0..67e6b8b 100644
--- a/dlls/user32/tests/menu.c
+++ b/dlls/user32/tests/menu.c
@@ -2820,15 +2820,13 @@ void test_menu_cancelmode()
     ret = TrackPopupMenu( menu, 0x100, 100,100, 0, hwndchild, NULL);
     todo_wine {
         ok(g_got_enteridle == 0, "received %d WM_ENTERIDLE messages, none expected\n", g_got_enteridle);
-        ok(g_got_enteridle < 2, "received %d WM_ENTERIDLE messages, should be less then 2\n", g_got_enteridle);
     }
+    ok(g_got_enteridle < 2, "received %d WM_ENTERIDLE messages, should be less then 2\n", g_got_enteridle);
     /* now send the WM_CANCELMODE messages to the WRONG window */
     /* those should fail ( to have any effect) */
     g_hwndtosend = hwnd;
     ret = TrackPopupMenu( menu, 0x100, 100,100, 0, hwndchild, NULL);
-    todo_wine {
-        ok( g_got_enteridle == 2, "received %d WM_ENTERIDLE messages, should be 2\n", g_got_enteridle);
-    }
+    ok( g_got_enteridle == 2, "received %d WM_ENTERIDLE messages, should be 2\n", g_got_enteridle);
     /* cleanup */
     DestroyMenu( menu);
     DestroyWindow( hwndchild);
-- 
1.6.1.3


--------------040600050906040003080607--



More information about the wine-patches mailing list