user32: TrackPopupMenu(Ex) fixes.

Rein Klazes wijn at online.nl
Fri Mar 6 02:27:48 CST 2009


---
 dlls/user32/menu.c       |   41 ++++++++++-------
 dlls/user32/tests/menu.c |  112 ++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 136 insertions(+), 17 deletions(-)

diff --git a/dlls/user32/menu.c b/dlls/user32/menu.c
index 8f8a7b4..db8d21e 100644
--- a/dlls/user32/menu.c
+++ b/dlls/user32/menu.c
@@ -3447,21 +3447,25 @@ track_menu:
     MENU_ExitTracking( hwnd );
 }
 
-
 /**********************************************************************
- *           TrackPopupMenu   (USER32.@)
- *
- * Like the win32 API, the function return the command ID only if the
- * flag TPM_RETURNCMD is on.
- *
+ *           TrackPopupMenuEx   (USER32.@)
  */
-BOOL WINAPI TrackPopupMenu( HMENU hMenu, UINT wFlags, INT x, INT y,
-                           INT nReserved, HWND hWnd, const RECT *lpRect )
+BOOL WINAPI TrackPopupMenuEx( HMENU hMenu, UINT wFlags, INT x, INT y,
+        HWND hWnd, LPTPMPARAMS lpTpm )
 {
     BOOL ret = FALSE;
 
-    TRACE("hmenu %p flags %04x (%d,%d) reserved %d hwnd %p rect %s\n",
-           hMenu, wFlags, x, y, nReserved, hWnd, wine_dbgstr_rect(lpRect));
+    TRACE("hmenu %p flags %04x (%d,%d) hwnd %p lpTpm %p rect %s\n",
+            hMenu, wFlags, x, y, hWnd, lpTpm,
+            lpTpm ? wine_dbgstr_rect( &lpTpm->rcExclude) : "-" );
+
+    /* Parameter check */
+    /* FIXME: this check is performed several times, here and in the called
+       functions. That could be optimized */
+    if( !hMenu || !MENU_GetMenu( hMenu )) {
+        SetLastError( ERROR_INVALID_MENU_HANDLE) ;
+        return FALSE;
+    }
 
     MENU_InitTracking(hWnd, hMenu, TRUE, wFlags);
 
@@ -3470,21 +3474,24 @@ BOOL WINAPI TrackPopupMenu( HMENU hMenu, UINT wFlags, INT x, INT y,
         SendMessageW( hWnd, WM_INITMENUPOPUP, (WPARAM)hMenu, 0);
 
     if (MENU_ShowPopup( hWnd, hMenu, 0, wFlags, x, y, 0, 0 ))
-        ret = MENU_TrackMenu( hMenu, wFlags | TPM_POPUPMENU, 0, 0, hWnd, lpRect );
+        ret = MENU_TrackMenu( hMenu, wFlags | TPM_POPUPMENU, 0, 0, hWnd,
+                lpTpm ? &lpTpm->rcExclude : NULL );
     MENU_ExitTracking(hWnd);
 
     return ret;
 }
 
 /**********************************************************************
- *           TrackPopupMenuEx   (USER32.@)
+ *           TrackPopupMenu   (USER32.@)
+ *
+ * Like the win32 API, the function return the command ID only if the
+ * flag TPM_RETURNCMD is on.
+ *
  */
-BOOL WINAPI TrackPopupMenuEx( HMENU hMenu, UINT wFlags, INT x, INT y,
-                                HWND hWnd, LPTPMPARAMS lpTpm )
+BOOL WINAPI TrackPopupMenu( HMENU hMenu, UINT wFlags, INT x, INT y,
+        INT nReserved, HWND hWnd, const RECT *lpRect )
 {
-    FIXME("not fully implemented\n" );
-    return TrackPopupMenu( hMenu, wFlags, x, y, 0, hWnd,
-                             lpTpm ? &lpTpm->rcExclude : NULL );
+    return TrackPopupMenuEx( hMenu, wFlags, x, y, hWnd, NULL);
 }
 
 /***********************************************************************
diff --git a/dlls/user32/tests/menu.c b/dlls/user32/tests/menu.c
index 747970f..f8c61d4 100644
--- a/dlls/user32/tests/menu.c
+++ b/dlls/user32/tests/menu.c
@@ -140,12 +140,25 @@ static int MOD_odheight;
 static SIZE MODsizes[MOD_NRMENUS]= { {MOD_SIZE, MOD_SIZE},{MOD_SIZE, MOD_SIZE},
     {MOD_SIZE, MOD_SIZE},{MOD_SIZE, MOD_SIZE}};
 static int MOD_GotDrawItemMsg = FALSE;
+static int  gflag_initmenupopup,
+            gflag_entermenuloop,
+            gflag_initmenu;
+
 /* wndproc used by test_menu_ownerdraw() */
 static LRESULT WINAPI menu_ownerdraw_wnd_proc(HWND hwnd, UINT msg,
         WPARAM wparam, LPARAM lparam)
 {
     switch (msg)
     {
+        case WM_INITMENUPOPUP:
+            gflag_initmenupopup++;
+            break;
+        case WM_ENTERMENULOOP:
+            gflag_entermenuloop++;
+            break;
+        case WM_INITMENU:
+            gflag_initmenu++;
+            break;
         case WM_MEASUREITEM:
             {
                 MEASUREITEMSTRUCT* pmis = (MEASUREITEMSTRUCT*)lparam;
@@ -2628,6 +2641,104 @@ static void test_menu_setmenuinfo(void)
     return;
 }
 
+/* little func to easy switch either TrackPopupMenu() or TrackPopupMenuEx() */
+static DWORD MyTrackPopupMenu( int ex, HMENU hmenu, UINT flags, INT x, INT y, HWND hwnd, LPTPMPARAMS ptpm)
+{
+    return ex
+        ? TrackPopupMenuEx( hmenu, flags, x, y, hwnd, ptpm)
+        : TrackPopupMenu( hmenu, flags, x, y, 0, hwnd, NULL);
+}
+
+/* some TrackPopupMenu and TrackPopupMenuEx tests */
+/* the LastError values differ between NO_ERROR and invalid handle */
+/* between all windows versions tested. The first value is that valid on XP  */
+/* Vista was the only that made returned different error values */
+/* between the TrackPopupMenu and TrackPopupMenuEx functions */
+static void test_menu_trackpopupmenu(void)
+{
+    BOOL ret;
+    HMENU hmenu;
+    DWORD gle;
+    int Ex;
+    HWND hwnd = CreateWindowEx(0, MAKEINTATOM(atomMenuCheckClass), NULL,
+            WS_VISIBLE, CW_USEDEFAULT, CW_USEDEFAULT, 200, 200,
+            NULL, NULL, NULL, NULL);
+    ok(hwnd != NULL, "CreateWindowEx failed with error %d\n", GetLastError());
+    if( !hwnd) return;
+    SetWindowLongPtr( hwnd, GWLP_WNDPROC, (LONG_PTR)menu_ownerdraw_wnd_proc);
+    for( Ex = 0; Ex < 2; Ex++) {
+        hmenu = CreatePopupMenu();
+        ok(hmenu != NULL, "CreateMenu failed with error %d\n", GetLastError());
+        if( !hmenu) { DestroyWindow(hwnd);return;}
+        /* display the menu */
+        /* start with an invalid menu handle */
+        gle = 0xdeadbeef;
+        gflag_initmenupopup = gflag_entermenuloop = gflag_initmenu = 0;
+        ret = MyTrackPopupMenu( Ex, NULL, 0x100, 100,100, hwnd, NULL);
+        gle = GetLastError();
+        ok( !ret, "TrackPopupMenu%s should have failed\n", Ex ? "Ex" : "");
+        ok( gle == ERROR_INVALID_MENU_HANDLE
+                || broken (gle == NO_ERROR) /* win98/ME */
+                ,"TrackPopupMenu%s error got %u expected %u\n",
+                Ex ? "Ex" : "", gle, ERROR_INVALID_MENU_HANDLE);
+        ok( !(gflag_initmenupopup || gflag_entermenuloop || gflag_initmenu),
+                "got unexpected message(s)%s%s%s\n",
+                gflag_initmenupopup ? " WM_INITMENUPOPUP ": " ",
+                gflag_entermenuloop ? "WM_INITMENULOOP ": "",
+                gflag_initmenu ? "WM_INITMENU": "");
+        /* another one but not NULL */
+        gle = 0xdeadbeef;
+        gflag_initmenupopup = gflag_entermenuloop = gflag_initmenu = 0;
+        ret = MyTrackPopupMenu( Ex, (HMENU)hwnd, 0x100, 100,100, hwnd, NULL);
+        gle = GetLastError();
+        ok( !ret, "TrackPopupMenu%s should have failed\n", Ex ? "Ex" : "");
+        ok( gle == ERROR_INVALID_MENU_HANDLE
+                || broken (gle == NO_ERROR) /* win98/ME */
+                ,"TrackPopupMenu%s error got %u expected %u\n",
+                Ex ? "Ex" : "", gle, ERROR_INVALID_MENU_HANDLE);
+        ok( !(gflag_initmenupopup || gflag_entermenuloop || gflag_initmenu),
+                "got unexpected message(s)%s%s%s\n",
+                gflag_initmenupopup ? " WM_INITMENUPOPUP ": " ",
+                gflag_entermenuloop ? "WM_INITMENULOOP ": "",
+                gflag_initmenu ? "WM_INITMENU": "");
+        /* now a somewhat successfull call */
+        gle = 0xdeadbeef;
+        gflag_initmenupopup = gflag_entermenuloop = gflag_initmenu = 0;
+        ret = MyTrackPopupMenu( Ex, hmenu, 0x100, 100,100, hwnd, NULL);
+        gle = GetLastError();
+        ok( ret == 0, "TrackPopupMenu%s returned %d expected zero\n", Ex ? "Ex" : "", ret);
+        ok( gle == NO_ERROR
+                || gle == ERROR_INVALID_MENU_HANDLE /* NT4, win2k */
+                ,"TrackPopupMenu%s error got %u expected %u or %u\n",
+                Ex ? "Ex" : "", gle, NO_ERROR, ERROR_INVALID_MENU_HANDLE);
+        ok( gflag_initmenupopup && gflag_entermenuloop && gflag_initmenu,
+                "missed expected message(s)%s%s%s\n",
+                !gflag_initmenupopup ? " WM_INITMENUPOPUP ": " ",
+                !gflag_entermenuloop ? "WM_INITMENULOOP ": "",
+                !gflag_initmenu ? "WM_INITMENU": "");
+        /* and another */
+        ret = AppendMenuA( hmenu, MF_STRING, 1, "winetest");
+        ok( ret, "AppendMenA has failed!\n");
+        gle = 0xdeadbeef;
+        gflag_initmenupopup = gflag_entermenuloop = gflag_initmenu = 0;
+        ret = MyTrackPopupMenu( Ex, hmenu, 0x100, 100,100, hwnd, NULL);
+        gle = GetLastError();
+        ok( ret == 0, "TrackPopupMenu%s returned %d expected zero\n", Ex ? "Ex" : "", ret);
+        ok( gle == NO_ERROR
+                || gle == ERROR_INVALID_MENU_HANDLE /* NT4, win2k and Vista in the TrackPopupMenuEx case */
+                ,"TrackPopupMenu%s error got %u expected %u or %u\n",
+                Ex ? "Ex" : "", gle, NO_ERROR, ERROR_INVALID_MENU_HANDLE);
+        ok( gflag_initmenupopup && gflag_entermenuloop && gflag_initmenu,
+                "missed expected message(s)%s%s%s\n",
+                !gflag_initmenupopup ? " WM_INITMENUPOPUP ": " ",
+                !gflag_entermenuloop ? "WM_INITMENULOOP ": "",
+                !gflag_initmenu ? "WM_INITMENU": "");
+        DestroyMenu(hmenu);
+    }
+    /* clean up */
+    DestroyWindow(hwnd);
+}
+
 START_TEST(menu)
 {
     init_function_pointers();
@@ -2663,4 +2774,5 @@ START_TEST(menu)
     test_menu_flags();
 
     test_menu_hilitemenuitem();
+    test_menu_trackpopupmenu();
 }
-- 
1.6.1.3


--------------050702090000080201040204--



More information about the wine-patches mailing list