user32: partial implementation of GetMenuBarInfo()

Rein Klazes wijn at online.nl
Thu Jun 11 03:47:36 CDT 2009


fixes bug #18776
---
 dlls/user32/menu.c       |   52 +++++++++++++++++++-
 dlls/user32/tests/menu.c |  125 ++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 176 insertions(+), 1 deletions(-)

diff --git a/dlls/user32/menu.c b/dlls/user32/menu.c
index 335fcfa..4b3d764 100644
--- a/dlls/user32/menu.c
+++ b/dlls/user32/menu.c
@@ -4191,7 +4191,57 @@ HMENU WINAPI GetMenu( HWND hWnd )
  */
 BOOL WINAPI GetMenuBarInfo( HWND hwnd, LONG idObject, LONG idItem, PMENUBARINFO pmbi )
 {
-    FIXME( "(%p,0x%08x,0x%08x,%p)\n", hwnd, idObject, idItem, pmbi );
+    TRACE( "(%p,0x%08x,0x%08x,%p)\n", hwnd, idObject, idItem, pmbi );
+    if( !pmbi || pmbi->cbSize < sizeof(MENUBARINFO)) return FALSE;
+    switch( idObject)
+    {
+        case OBJID_MENU:
+        {
+            LPPOPUPMENU lpmenu;
+            HMENU hmenu = GetMenu( hwnd);
+            RECT rc;
+            if( !(lpmenu = MENU_GetMenu( hmenu))) return FALSE;
+            if( idItem < 0 || idItem > lpmenu->nItems) return FALSE;
+            pmbi->hMenu = hmenu;
+            /* fill in the rectangle coordinates */
+            if( !lpmenu->Height)
+                SetRectEmpty( &pmbi->rcBar);
+            else if( idItem == 0) { /* get menu rectangle */
+                GetMenuItemRect( hwnd, hmenu, 0, &rc);
+                rc.right = rc.left + lpmenu->Width;
+                rc.bottom = rc.top + lpmenu->Height;
+                pmbi->rcBar = rc;
+            } else  /* get item rectangle */
+                GetMenuItemRect( hwnd, hmenu, idItem - 1, &pmbi->rcBar);
+            /* is this menu active? */
+            pmbi->hwndMenu = 0;
+            if( top_popup_hmenu == hmenu && top_popup == hwnd) {
+                pmbi->fBarFocused = TRUE;
+                if( idItem) {
+                    if( lpmenu->FocusedItem == (UINT) idItem - 1) {
+                        pmbi->fFocused = TRUE;
+                        /* fill in the hwndMenu member if the selected item
+                         * has an open sub menu */
+                        if(  lpmenu->items[idItem - 1].fType & MF_POPUP) {
+                            HMENU hsubmenu;
+                            POPUPMENU *lpsubmenu;
+                            hsubmenu =  lpmenu->items[idItem - 1].hSubMenu;
+                            lpsubmenu = MENU_GetMenu( hsubmenu);
+                            if( lpsubmenu)
+                                pmbi->hwndMenu = lpsubmenu->hWnd;
+                        }
+                    } else
+                        pmbi->fFocused = FALSE;
+                } else
+                    pmbi->fFocused = TRUE;
+            } else {
+                pmbi->fBarFocused = FALSE;
+                pmbi->fFocused = FALSE;
+            }
+            return TRUE;
+        }
+    }
+    FIXME( "(%p,0x%08x,0x%08x,%p) Object id not supported!\n", hwnd, idObject, idItem, pmbi );
     return FALSE;
 }
 
diff --git a/dlls/user32/tests/menu.c b/dlls/user32/tests/menu.c
index 0948f69..448e04f 100644
--- a/dlls/user32/tests/menu.c
+++ b/dlls/user32/tests/menu.c
@@ -38,6 +38,7 @@
 static ATOM atomMenuCheckClass;
 
 static BOOL (WINAPI *pGetMenuInfo)(HMENU,LPCMENUINFO);
+static BOOL (WINAPI *pGetMenuBarInfo)(HWND,LONG,LONG,PMENUBARINFO);
 static UINT (WINAPI *pSendInput)(UINT, INPUT*, size_t);
 static BOOL (WINAPI *pSetMenuInfo)(HMENU,LPCMENUINFO);
 static BOOL (WINAPI *pEndMenu) (void);
@@ -52,6 +53,7 @@ static void init_function_pointers(void)
       trace("GetProcAddress(%s) failed\n", #func);
 
     GET_PROC(GetMenuInfo)
+    GET_PROC(GetMenuBarInfo)
     GET_PROC(SendInput)
     GET_PROC(SetMenuInfo)
     GET_PROC(EndMenu)
@@ -116,6 +118,7 @@ typedef struct
 /* globals to communicate between test and wndproc */
 
 static BOOL bMenuVisible;
+static HMENU popmenu;
 static BOOL got_input;
 static HMENU hMenus[4];
 
@@ -256,6 +259,92 @@ static void register_menu_check_class(void)
     atomMenuCheckClass = RegisterClass(&wc);
 }
 
+/* some tests for GetMenuBarInfo */
+void test_getmenubarinfo()
+{
+    BOOL ret;
+    HMENU hmenu;
+    MENUBARINFO mbi = { sizeof(MENUBARINFO), { -1, -1, -1, -1}, (HMENU)-2, (HWND)-3, 1, 1};
+    RECT rcw, rci;
+    HWND hwnd;
+    if( !pGetMenuBarInfo) {
+        win_skip("GetMenuBarInfo is not available\n");
+        return;
+    }
+    hwnd = CreateWindowEx(0, MAKEINTATOM(atomMenuCheckClass), NULL,
+                               WS_VISIBLE, CW_USEDEFAULT, CW_USEDEFAULT, 100, 100,
+                               NULL, NULL, NULL, NULL);
+    ok( hwnd != NULL, "CreateWindowEx failed with error %d\n", GetLastError());
+    /* no menu: getmenubar =info should fail */
+    ret = pGetMenuBarInfo( hwnd, OBJID_MENU, 0, &mbi);
+    ok( !ret, "GetMenuBarInfo should not have been successfull\n");
+    /* the MENUBARINFO members have not been changed */
+    ok( (-1 == mbi.rcBar.left && (HWND) -3 == mbi.hwndMenu && mbi.fBarFocused) ||
+            TRUE, /* win 9x,ME  */
+            "MENUBARINFO should not be changed.\n");
+    /* create menubar, no items yet */
+    hmenu = CreateMenu();
+    ok(hmenu != NULL, "CreateMenu failed with error %d\n", GetLastError());
+    ret = SetMenu( hwnd, hmenu);
+    ok( ret, "SetMenu failed with error %d\n", GetLastError());
+    /* do the tests */
+    UpdateWindow( hwnd); /* hack for wine to draw the window + menu */
+    ret = pGetMenuBarInfo( hwnd, OBJID_MENU, 0, &mbi);
+    ok( ret, "GetMenuBarInfo failed with error %d\n", GetLastError());
+    /* a menubar without items returns null rectangle */
+    ok( mbi.rcBar.left ==  0 && mbi.rcBar.top ==  0 &&
+        mbi.rcBar.bottom ==  0 && mbi.rcBar.right ==  0,
+        "GetMenuBarInfo returns unexpected menu rectangle. Got %d,%d-%d,%d instead of 0,0-0,0\n",
+        mbi.rcBar.left, mbi.rcBar.top, mbi.rcBar.right, mbi.rcBar.bottom);
+    ok( mbi.hMenu == hmenu, "GetMenuBarInfo returns unexpected menu handle. Got %p instead of %p\n",
+        mbi.hMenu, hmenu);
+    ok( mbi.fBarFocused == 0, "GetMenuBarInfo returns: menu bar has focus.\n");
+    ok( mbi.fFocused == 0, "GetMenuBarInfo returns: menu item has focus.\n");
+    /* add some items */
+    ret = AppendMenu( hmenu, MF_STRING , 100, "item 1");
+    ok( ret, "AppendMenu failed.\n");
+    ret = AppendMenu( hmenu, MF_STRING , 101, "item 2");
+    ok( ret, "AppendMenu failed.\n");
+    ret = SetMenu( hwnd, hmenu);
+    ok( ret, "SetMenu failed with error %d\n", GetLastError());
+    /* do the tests */
+    UpdateWindow( hwnd); /* hack for wine to draw the window + menu */
+    /* get info for the whole menu */
+    ret = pGetMenuBarInfo( hwnd, OBJID_MENU, 0, &mbi);
+    ok( ret, "GetMenuBarInfo failed with error %d\n", GetLastError());
+    /* calculate menu rectangle, from window rectangle and the position of the first item  */
+    ret = GetWindowRect( hwnd, &rcw);
+    ok( ret, "GetWindowRect failed.\n");
+    ret = GetMenuItemRect( hwnd, hmenu, 0, &rci);
+    ok( ret, "GetMenuItemRect failed.\n");
+todo_wine
+    ok( mbi.rcBar.left ==  rci.left && mbi.rcBar.top ==  rci.top &&
+            mbi.rcBar.bottom ==  rci.bottom && mbi.rcBar.right ==  rcw.right - rci.left + rcw.left,
+            "GetMenuBarInfo returns unexpected menu rectangle. Got %d,%d-%d,%d instead of %d,%d-%d,%d\n",
+            mbi.rcBar.left, mbi.rcBar.top, mbi.rcBar.right, mbi.rcBar.bottom,
+            rci.left, rci.top, rcw.right - rci.left + rcw.left, rci.bottom);
+    ok( mbi.hMenu == hmenu, "GetMenuBarInfo returns unexpected menu handle. Got %p instead of %p\n",
+        mbi.hMenu, hmenu);
+    ok( mbi.fBarFocused == 0, "GetMenuBarInfo returns: menu bar has focus.\n");
+    ok( mbi.fFocused == 0, "GetMenuBarInfo returns: menu item has focus.\n");
+    /* get info for item nr.2 */
+    ret = pGetMenuBarInfo( hwnd, OBJID_MENU, 2, &mbi);
+    ok( ret, "GetMenuBarInfo failed with error %d\n", GetLastError());
+    ret = GetMenuItemRect( hwnd, hmenu, 1, &rci);
+    ok( ret, "GetMenuItemRect failed.\n");
+    ok( mbi.rcBar.left ==  rci.left && mbi.rcBar.top ==  rci.top &&
+            mbi.rcBar.bottom ==  rci.bottom && mbi.rcBar.right ==  rci.right,
+            "GetMenuBarInfo returns unexpected menu rectangle. Got %d,%d-%d,%d instead of %d,%d-%d,%d\n",
+            mbi.rcBar.left, mbi.rcBar.top, mbi.rcBar.right, mbi.rcBar.bottom,
+            rci.left, rci.top, rci.right, rci.bottom);
+    ok( mbi.hMenu == hmenu, "GetMenuBarInfo returns unexpected menu handle. Got %p instead of %p\n",
+        mbi.hMenu, hmenu);
+    ok( mbi.fBarFocused == 0, "GetMenuBarInfo returns: menu bar has focus.\n");
+    ok( mbi.fFocused == 0, "GetMenuBarInfo returns: menu item has focus.\n");
+    /* clean up */
+    DestroyWindow(hwnd);
+}
+
 /* demonstrates that windows locks the menu object so that it is still valid
  * even after a client calls DestroyMenu on it */
 static void test_menu_locked_by_window(void)
@@ -1985,6 +2074,35 @@ static DWORD WINAPI test_menu_input_thread(LPVOID lpParameter)
         }
         else
             ok(menu_tests[i].bMenuVisible == bMenuVisible, "test %d\n", i);
+        /* add some GetMenuBarInfo tests */
+        if( pGetMenuBarInfo)
+        {
+            MENUBARINFO mbi = { sizeof(MENUBARINFO)};
+            HMENU hmenu;
+            UINT state;
+            /* get info for the menu */
+            pGetMenuBarInfo( hWnd, OBJID_MENU, 0, &mbi);
+            hmenu = GetMenu( hWnd);
+            ok( !mbi.hwndMenu, "test %d GetMenuBarInfo.hwndMenu wrong: %p expected NULL\n",
+                    i, mbi.hwndMenu);
+            ok( mbi.hMenu == hmenu, "test %d GetMenuBarInfo got wrong menu: %p expected %p\n",
+                    i, mbi.hMenu, hmenu);
+            ok( !bMenuVisible == !mbi.fBarFocused, "test %d GetMenuBarInfo.fBarFocused (%d) is wrong\n",
+                    i, mbi.fBarFocused != 0);
+            ok( !bMenuVisible == !mbi.fFocused, "test %d GetMenuBarInfo.fFocused (%d) is wrong\n",
+                    i, mbi.fFocused != 0);
+            /* get info for the menu's first item */
+            pGetMenuBarInfo( hWnd, OBJID_MENU, 1, &mbi);
+            state = GetMenuState( hmenu, 0, MF_BYPOSITION);
+            ok( !mbi.hwndMenu ==  !popmenu, "test %d GetMenuBarInfo.hwndMenu wrong: %p expected %sNULL\n",
+                i, mbi.hwndMenu, popmenu ? "not " : "");
+            ok( mbi.hMenu == hmenu, "test %d GetMenuBarInfo got wrong menu: %p expected %p\n",
+                    i, mbi.hMenu, hmenu);
+            ok( !bMenuVisible == !mbi.fBarFocused, "test %d GetMenuBarInfo.fBarFocused (%d) is wrong\n",
+                    i, mbi.fBarFocused != 0);
+            ok( !(bMenuVisible && (state & MF_HILITE)) == !mbi.fFocused,
+                    "test %d GetMenuBarInfo.fFocused (%d) is wrong\n", i, mbi.fFocused != 0);
+        }
     }
     return 0;
 }
@@ -1993,6 +2111,12 @@ static LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam,
         LPARAM lParam)
 {
     switch (msg) {
+        case WM_INITMENUPOPUP:
+            popmenu  = (HMENU) wParam;
+            break;
+        case WM_UNINITMENUPOPUP:
+            popmenu  = NULL;
+            break;
         case WM_ENTERMENULOOP:
             bMenuVisible = TRUE;
             break;
@@ -2954,6 +3078,7 @@ START_TEST(menu)
     test_menu_locked_by_window();
     test_subpopup_locked_by_menu();
     test_menu_ownerdraw();
+    test_getmenubarinfo();
     test_menu_bmp_and_string();
     /* test Get/SetMenuInfo if available */
     if( pGetMenuInfo && pSetMenuInfo) {
-- 
1.6.3.1




More information about the wine-patches mailing list