In SetMenuInfo() implement the MIM_APPLYTOSUBMENUS. Also set last error if called with invalid parameters with tests.

Rein Klazes wijn at online.nl
Fri Feb 27 02:17:58 CST 2009


---
 dlls/user32/menu.c       |   57 ++++++++++-------
 dlls/user32/tests/menu.c |  162 +++++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 195 insertions(+), 24 deletions(-)

diff --git a/dlls/user32/menu.c b/dlls/user32/menu.c
index d285ef2..bb0ff39 100644
--- a/dlls/user32/menu.c
+++ b/dlls/user32/menu.c
@@ -5009,45 +5009,55 @@ BOOL WINAPI GetMenuItemRect (HWND hwnd, HMENU hMenu, UINT uItem,
      return TRUE;
 }
 
-
 /**********************************************************************
  *		SetMenuInfo    (USER32.@)
  *
  * FIXME
- *	MIM_APPLYTOSUBMENUS
  *	actually use the items to draw the menu
+ *      (recalculate and/or redraw)
  */
-BOOL WINAPI SetMenuInfo (HMENU hMenu, LPCMENUINFO lpmi)
+static BOOL menu_SetMenuInfo( HMENU hMenu, LPCMENUINFO lpmi)
 {
     POPUPMENU *menu;
+    if( !(menu = MENU_GetMenu(hMenu))) return FALSE;
 
-    TRACE("(%p %p)\n", hMenu, lpmi);
+    if (lpmi->fMask & MIM_BACKGROUND)
+        menu->hbrBack = lpmi->hbrBack;
 
-    if (lpmi && (lpmi->cbSize==sizeof(MENUINFO)) && (menu = MENU_GetMenu(hMenu)))
-    {
+    if (lpmi->fMask & MIM_HELPID)
+        menu->dwContextHelpID = lpmi->dwContextHelpID;
 
-	if (lpmi->fMask & MIM_BACKGROUND)
-	    menu->hbrBack = lpmi->hbrBack;
+    if (lpmi->fMask & MIM_MAXHEIGHT)
+        menu->cyMax = lpmi->cyMax;
 
-	if (lpmi->fMask & MIM_HELPID)
-	    menu->dwContextHelpID = lpmi->dwContextHelpID;
+    if (lpmi->fMask & MIM_MENUDATA)
+        menu->dwMenuData = lpmi->dwMenuData;
 
-	if (lpmi->fMask & MIM_MAXHEIGHT)
-	    menu->cyMax = lpmi->cyMax;
+    if (lpmi->fMask & MIM_STYLE)
+        menu->dwStyle = lpmi->dwStyle;
 
-	if (lpmi->fMask & MIM_MENUDATA)
-	    menu->dwMenuData = lpmi->dwMenuData;
+    if( lpmi->fMask & MIM_APPLYTOSUBMENUS) {
+        int i;
+        MENUITEM *item = menu->items;
+        for( i = menu->nItems; i; i--, item++)
+            if( item->fType & MF_POPUP)
+                menu_SetMenuInfo( item->hSubMenu, lpmi);
+    }
+    return TRUE;
+}
 
-	if (lpmi->fMask & MIM_STYLE)
-	{
-	    menu->dwStyle = lpmi->dwStyle;
-	    if (menu->dwStyle & MNS_AUTODISMISS) FIXME("MNS_AUTODISMISS unimplemented\n");
-	    if (menu->dwStyle & MNS_DRAGDROP) FIXME("MNS_DRAGDROP unimplemented\n");
-	    if (menu->dwStyle & MNS_MODELESS) FIXME("MNS_MODELESS unimplemented\n");
+BOOL WINAPI SetMenuInfo (HMENU hMenu, LPCMENUINFO lpmi)
+{
+    TRACE("(%p %p)\n", hMenu, lpmi);
+    if( lpmi && (lpmi->cbSize == sizeof( MENUINFO)) && (menu_SetMenuInfo( hMenu, lpmi))) {
+	if( lpmi->fMask & MIM_STYLE) {
+	    if (lpmi->dwStyle & MNS_AUTODISMISS) FIXME("MNS_AUTODISMISS unimplemented\n");
+	    if (lpmi->dwStyle & MNS_DRAGDROP) FIXME("MNS_DRAGDROP unimplemented\n");
+	    if (lpmi->dwStyle & MNS_MODELESS) FIXME("MNS_MODELESS unimplemented\n");
 	}
-
-	return TRUE;
+        return TRUE;
     }
+    SetLastError( ERROR_INVALID_PARAMETER);
     return FALSE;
 }
 
@@ -5063,7 +5073,7 @@ BOOL WINAPI GetMenuInfo (HMENU hMenu, LPMENUINFO lpmi)
 
     TRACE("(%p %p)\n", hMenu, lpmi);
 
-    if (lpmi && (menu = MENU_GetMenu(hMenu)))
+    if (lpmi && (lpmi->cbSize == sizeof( MENUINFO)) && (menu = MENU_GetMenu(hMenu)))
     {
 
 	if (lpmi->fMask & MIM_BACKGROUND)
@@ -5083,6 +5093,7 @@ BOOL WINAPI GetMenuInfo (HMENU hMenu, LPMENUINFO lpmi)
 
 	return TRUE;
     }
+    SetLastError( ERROR_INVALID_PARAMETER);
     return FALSE;
 }
 
diff --git a/dlls/user32/tests/menu.c b/dlls/user32/tests/menu.c
index f5d2bdc..1254ac7 100644
--- a/dlls/user32/tests/menu.c
+++ b/dlls/user32/tests/menu.c
@@ -2432,6 +2432,161 @@ static void test_InsertMenu(void)
 #undef compare_menu
 }
 
+static void test_menu_getmenuinfo()
+{
+    HMENU hmenu;
+    MENUINFO mi = {0};
+    BOOL ret;
+    DWORD gle;
+
+    /* create a menu */
+    hmenu = CreateMenu();
+    assert( hmenu);
+    /* test some parameter errors */
+    SetLastError(0xdeadbeef);
+    ret = pGetMenuInfo( hmenu, NULL);
+    gle= GetLastError();
+    ok( !ret, "GetMenuInfo() should have failed\n");
+    ok( gle == ERROR_INVALID_PARAMETER, "GetMenuInfo() error got %u expected %u\n", gle, ERROR_INVALID_PARAMETER);
+    SetLastError(0xdeadbeef);
+    mi.cbSize = 0;
+    ret = pGetMenuInfo( hmenu, &mi);
+    gle= GetLastError();
+    ok( !ret, "GetMenuInfo() should have failed\n");
+    ok( gle == ERROR_INVALID_PARAMETER, "GetMenuInfo() error got %u expected %u\n", gle, ERROR_INVALID_PARAMETER);
+    SetLastError(0xdeadbeef);
+    mi.cbSize = sizeof( MENUINFO);
+    ret = pGetMenuInfo( hmenu, &mi);
+    gle= GetLastError();
+    ok( ret, "GetMenuInfo() should have succeeded\n");
+    ok( gle == 0xdeadbeef, "GetMenuInfo() error got %u\n", gle);
+    SetLastError(0xdeadbeef);
+    mi.cbSize = 0;
+    ret = pGetMenuInfo( NULL, &mi);
+    gle= GetLastError();
+    ok( !ret, "GetMenuInfo() should have failed\n");
+    ok( gle == ERROR_INVALID_PARAMETER, "GetMenuInfo() error got %u expected %u\n", gle, ERROR_INVALID_PARAMETER);
+        /* clean up */
+    DestroyMenu( hmenu);
+    return;
+}
+
+static void test_menu_setmenuinfo()
+{
+    HMENU hmenu, hsubmenu;
+    MENUINFO mi = {0};
+    MENUITEMINFOA mii = {sizeof( MENUITEMINFOA)};
+    BOOL ret;
+    DWORD gle;
+
+    /* create a menu with a submenu */
+    hmenu = CreateMenu();
+    hsubmenu = CreateMenu();
+    assert( hmenu && hsubmenu);
+    mii.fMask = MIIM_SUBMENU;
+    mii.hSubMenu = hsubmenu;
+    ret = InsertMenuItem( hmenu, 0, FALSE, &mii);
+    ok( ret, "InsertMenuItem failed with error %d\n", GetLastError());
+    /* test some parameter errors */
+    SetLastError(0xdeadbeef);
+    ret = pSetMenuInfo( hmenu, NULL);
+    gle= GetLastError();
+    ok( !ret, "SetMenuInfo() should have failed\n");
+    ok( gle == ERROR_INVALID_PARAMETER, "SetMenuInfo() error got %u expected %u\n", gle, ERROR_INVALID_PARAMETER);
+    SetLastError(0xdeadbeef);
+    mi.cbSize = 0;
+    ret = pSetMenuInfo( hmenu, &mi);
+    gle= GetLastError();
+    ok( !ret, "SetMenuInfo() should have failed\n");
+    ok( gle == ERROR_INVALID_PARAMETER, "SetMenuInfo() error got %u expected %u\n", gle, ERROR_INVALID_PARAMETER);
+    SetLastError(0xdeadbeef);
+    mi.cbSize = sizeof( MENUINFO);
+    ret = pSetMenuInfo( hmenu, &mi);
+    gle= GetLastError();
+    ok( ret, "SetMenuInfo() should have succeeded\n");
+    ok( gle == 0xdeadbeef, "SetMenuInfo() error got %u\n", gle);
+    SetLastError(0xdeadbeef);
+    mi.cbSize = 0;
+    ret = pSetMenuInfo( NULL, &mi);
+    gle= GetLastError();
+    ok( !ret, "SetMenuInfo() should have failed\n");
+    ok( gle == ERROR_INVALID_PARAMETER, "SetMenuInfo() error got %u expected %u\n", gle, ERROR_INVALID_PARAMETER);
+    /* functional tests */
+    /* menu and submenu should have the CHECKORBMP style bit cleared */
+    SetLastError(0xdeadbeef);
+    mi.cbSize = sizeof( MENUINFO);
+    mi.fMask = MIM_STYLE;
+    ret = pGetMenuInfo( hmenu, &mi);
+    gle= GetLastError();
+    ok( ret, "GetMenuInfo() should have succeeded\n");
+    ok( gle == 0xdeadbeef, "GetMenuInfo() error got %u\n", gle);
+    ok( !(mi.dwStyle & MNS_CHECKORBMP), "menustyle was not expected to have the MNS_CHECKORBMP flag\n");
+    SetLastError(0xdeadbeef);
+    mi.cbSize = sizeof( MENUINFO);
+    mi.fMask = MIM_STYLE;
+    ret = pGetMenuInfo( hsubmenu, &mi);
+    gle= GetLastError();
+    ok( ret, "GetMenuInfo() should have succeeded\n");
+    ok( gle == 0xdeadbeef, "GetMenuInfo() error got %u\n", gle);
+    ok( !(mi.dwStyle & MNS_CHECKORBMP), "menustyle was not expected to have the MNS_CHECKORBMP flag\n");
+    /* SetMenuInfo() */
+    SetLastError(0xdeadbeef);
+    mi.cbSize = sizeof( MENUINFO);
+    mi.fMask = MIM_STYLE | MIM_APPLYTOSUBMENUS;
+    mi.dwStyle = MNS_CHECKORBMP;
+    ret = pSetMenuInfo( hmenu, &mi);
+    gle= GetLastError();
+    ok( ret, "SetMenuInfo() should have succeeded\n");
+    ok( gle == 0xdeadbeef, "SetMenuInfo() error got %u\n", gle);
+    /* Now both menus should have the MNS_CHECKORBMP style bit set */
+    SetLastError(0xdeadbeef);
+    mi.cbSize = sizeof( MENUINFO);
+    mi.fMask = MIM_STYLE;
+    ret = pGetMenuInfo( hmenu, &mi);
+    gle= GetLastError();
+    ok( ret, "GetMenuInfo() should have succeeded\n");
+    ok( gle == 0xdeadbeef, "GetMenuInfo() error got %u\n", gle);
+    ok( mi.dwStyle & MNS_CHECKORBMP, "menustyle was expected to have the MNS_CHECKORBMP flag\n");
+    SetLastError(0xdeadbeef);
+    mi.cbSize = sizeof( MENUINFO);
+    mi.fMask = MIM_STYLE;
+    ret = pGetMenuInfo( hsubmenu, &mi);
+    gle= GetLastError();
+    ok( ret, "GetMenuInfo() should have succeeded\n");
+    ok( gle == 0xdeadbeef, "GetMenuInfo() error got %u\n", gle);
+    ok( mi.dwStyle & MNS_CHECKORBMP, "menustyle was expected to have the MNS_CHECKORBMP flag\n");
+    /* now repeat that without the APPLYTOSUBMENUS flag and another style bit */
+    SetLastError(0xdeadbeef);
+    mi.cbSize = sizeof( MENUINFO);
+    mi.fMask = MIM_STYLE ;
+    mi.dwStyle = MNS_NOCHECK;
+    ret = pSetMenuInfo( hmenu, &mi);
+    gle= GetLastError();
+    ok( ret, "SetMenuInfo() should have succeeded\n");
+    ok( gle == 0xdeadbeef, "SetMenuInfo() error got %u\n", gle);
+    /* Now only the top menu should have the MNS_NOCHECK style bit set */
+    SetLastError(0xdeadbeef);
+    mi.cbSize = sizeof( MENUINFO);
+    mi.fMask = MIM_STYLE;
+    ret = pGetMenuInfo( hmenu, &mi);
+    gle= GetLastError();
+    ok( ret, "GetMenuInfo() should have succeeded\n");
+    ok( gle == 0xdeadbeef, "GetMenuInfo() error got %u\n", gle);
+    ok( mi.dwStyle & MNS_NOCHECK, "menustyle was expected to have the MNS_NOCHECK flag\n");
+    SetLastError(0xdeadbeef);
+    mi.cbSize = sizeof( MENUINFO);
+    mi.fMask = MIM_STYLE;
+    ret = pGetMenuInfo( hsubmenu, &mi);
+    gle= GetLastError();
+    ok( ret, "GetMenuInfo() should have succeeded\n");
+    ok( gle == 0xdeadbeef, "GetMenuInfo() error got %u\n", gle);
+    ok( !(mi.dwStyle & MNS_NOCHECK), "menustyle was not expected to have the MNS_NOCHECK flag\n");
+    /* clean up */
+    DestroyMenu( hsubmenu);
+    DestroyMenu( hmenu);
+    return;
+}
+
 START_TEST(menu)
 {
     init_function_pointers();
@@ -2454,7 +2609,12 @@ START_TEST(menu)
     test_menu_locked_by_window();
     test_menu_ownerdraw();
     test_menu_bmp_and_string();
-
+    /* test Get/SetMenuInfo if available */
+    if( pGetMenuInfo && pSetMenuInfo) {
+        test_menu_getmenuinfo();
+        test_menu_setmenuinfo();
+    } else
+        win_skip("Get/SetMenuInfo are not available\n");
     if( !pSendInput)
         win_skip("SendInput is not available\n");
     else
-- 
1.6.1.3


--------------030106070601070007080205--



More information about the wine-patches mailing list