[PATCH] user32: GetMenuItemRect works without draw if the menu isn't a popup (try 2)

Andy Clayton q3aiml at gmail.com
Tue Nov 22 23:28:28 CST 2011


Try 2: correctly calculate menu bar size using MENU_MenuBarCalcSize
instead of MENU_PopupMenuCalcSize, tweak test case to only check when
GetMenuItemRect should return a size, and fix a silly flag check error.

Fixes http://bugs.winehq.org/show_bug.cgi?id=27886
---
 dlls/user32/menu.c       |   31 ++++++++++++++++-----
 dlls/user32/tests/menu.c |   66 +++++++++++++++++++++++++++++----------------
 2 files changed, 65 insertions(+), 32 deletions(-)

diff --git a/dlls/user32/menu.c b/dlls/user32/menu.c
index 3ec682f..5597c0a 100644
--- a/dlls/user32/menu.c
+++ b/dlls/user32/menu.c
@@ -102,6 +102,7 @@ typedef struct {
     BOOL        bScrolling;   /* Scroll arrows are active */
     UINT        nScrollPos;   /* Current scroll position */
     UINT        nTotalHeight; /* Total height of menu items inside menu */
+    BOOL        bHasOrigin;   /* Menu item offset based on valid origin, otherwise only sizes are valid */
     /* ------------ MENUINFO members ------ */
     DWORD	dwStyle;	/* Extended menu style */
     UINT	cyMax;		/* max height of the whole menu, 0 is screen height */
@@ -1265,10 +1266,16 @@ static void MENU_MenuBarCalcSize( HDC hdc, LPRECT lprect,
     MENUITEM *lpitem;
     UINT start, i, helpPos;
     int orgX, orgY, maxY;
+    RECT zeroRect = { 0, 0, 0, 0 };
 
-    if ((lprect == NULL) || (lppop == NULL)) return;
+    if (lppop == NULL) return;
     if (lppop->nItems == 0) return;
     TRACE("lprect %p %s\n", lprect, wine_dbgstr_rect( lprect));
+    if (!lprect) {
+        lprect = &zeroRect;
+    } else {
+        lppop->bHasOrigin = TRUE;
+    }
     lppop->Width  = lprect->right - lprect->left;
     lppop->Height = 0;
     maxY = lprect->top+1;
@@ -1292,7 +1299,7 @@ static void MENU_MenuBarCalcSize( HDC hdc, LPRECT lprect,
 	    debug_print_menuitem ("  item: ", lpitem, "");
 	    MENU_CalcItemSize( hdc, lpitem, hwndOwner, orgX, orgY, TRUE, lppop );
 
-	    if (lpitem->rect.right > lprect->right)
+	    if (lpitem->rect.right > lprect->right && lppop->bHasOrigin)
 	    {
 		if (i != start) break;
 		else lpitem->rect.right = lprect->right;
@@ -1815,7 +1822,7 @@ UINT MENU_DrawMenuBar( HDC hDC, LPRECT lprect, HWND hwnd,
     {
 	hfontOld = SelectObject( hDC, get_menu_font(FALSE));
 
-	if (lppop->Height == 0)
+	if (lppop->Height == 0 || !lppop->bHasOrigin)
 		MENU_MenuBarCalcSize(hDC, lprect, lppop, hwnd);
 
 	lprect->bottom = lprect->top + lppop->Height;
@@ -4300,7 +4307,7 @@ DWORD WINAPI DrawMenuBarTemp(HWND hwnd, HDC hDC, LPRECT lprect, HMENU hMenu, HFO
 
     hfontOld = SelectObject( hDC, hFont);
 
-    if (lppop->Height == 0)
+    if (lppop->Height == 0 || !lppop->bHasOrigin)
         MENU_MenuBarCalcSize(hDC, lprect, lppop, hwnd);
 
     lprect->bottom = lprect->top + lppop->Height;
@@ -4973,6 +4980,7 @@ BOOL WINAPI CheckMenuRadioItem(HMENU hMenu,
 BOOL WINAPI GetMenuItemRect (HWND hwnd, HMENU hMenu, UINT uItem,
 				 LPRECT rect)
 {
+     HDC hdc;
      POPUPMENU *itemMenu;
      MENUITEM *item;
      HWND referenceHwnd;
@@ -4982,12 +4990,19 @@ BOOL WINAPI GetMenuItemRect (HWND hwnd, HMENU hMenu, UINT uItem,
      item = MENU_FindItem (&hMenu, &uItem, MF_BYPOSITION);
      referenceHwnd = hwnd;
 
+     itemMenu = MENU_GetMenu(hMenu);
+     if (itemMenu == NULL)
+         return FALSE;
+
+     if ((itemMenu->Height == 0 || itemMenu->Width == 0) && !(itemMenu->wFlags & MF_POPUP)) {
+         hdc = GetDCEx(hwnd, 0, DCX_CACHE | DCX_WINDOW);
+         SelectObject(hdc, get_menu_font(FALSE));
+         MENU_MenuBarCalcSize(hdc, 0, itemMenu, hwnd);
+         ReleaseDC(hwnd, hdc);
+     }
+
      if(!hwnd)
      {
-	 itemMenu = MENU_GetMenu(hMenu);
-	 if (itemMenu == NULL)
-	     return FALSE;
-
 	 if(itemMenu->hWnd == 0)
 	     return FALSE;
 	 referenceHwnd = itemMenu->hWnd;
diff --git a/dlls/user32/tests/menu.c b/dlls/user32/tests/menu.c
index ea7b5b0..61f2a51 100644
--- a/dlls/user32/tests/menu.c
+++ b/dlls/user32/tests/menu.c
@@ -512,7 +512,8 @@ static void test_menu_ownerdraw(void)
 /* helper for test_menu_bmp_and_string() */
 static void test_mbs_help( int ispop, int hassub, int mnuopt,
         HWND hwnd, int arrowwidth, int count, HBITMAP hbmp,
-        SIZE bmpsize, LPCSTR text, SIZE size, SIZE sc_size)
+        SIZE bmpsize, LPCSTR text, SIZE size, SIZE sc_size,
+        int drawmenu)
 {
     BOOL ret;
     HMENU hmenu, submenu;
@@ -522,6 +523,7 @@ static void test_mbs_help( int ispop, int hassub, int mnuopt,
     CHAR text_copy[16];
     int hastab,  expect;
     int failed = 0;
+    int hassize = drawmenu || !ispop;
 
     MOD_GotDrawItemMsg = FALSE;
     mii.fMask = MIIM_FTYPE | MIIM_DATA | MIIM_STATE;
@@ -578,16 +580,25 @@ static void test_mbs_help( int ispop, int hassub, int mnuopt,
         TextOut( hdc, 10, 50, buf, strlen( buf));
         ReleaseDC( hwnd, hdc);
     }
-    if(ispop)
-        TrackPopupMenu( hmenu, TPM_RETURNCMD, 100,100, 0, hwnd, NULL);
-    else {
-        ret = SetMenu( hwnd, hmenu);
-        ok(ret, "SetMenu failed with error %d\n", GetLastError());
-        DrawMenuBar( hwnd);
+    if(drawmenu) {
+        if(ispop)
+            TrackPopupMenu( hmenu, TPM_RETURNCMD, 100,100, 0, hwnd, NULL);
+        else {
+	    ret = SetMenu( hwnd, hmenu);
+	    ok(ret, "SetMenu failed with error %d\n", GetLastError());
+	    DrawMenuBar( hwnd);
+	}
     }
     ret = GetMenuItemRect( hwnd, hmenu, 0, &rc);
     ok(ret, "GetMenuItemRect failed with error %d\n", GetLastError());
 
+    if((text || hbmp) && hassize) {
+        ok(rc.right - rc.left > 0, "menu width wrong, got %d expected >0\n", rc.right - rc.left);
+        failed = failed || !(rc.right - rc.left > 0);
+        ok(rc.bottom - rc.top > 0, "menu height wrong, got %d expected >0\n", rc.bottom - rc.top);
+        failed = failed || !(rc.bottom - rc.top > 0);
+    }
+
     if (0)  /* comment out menu size checks, behavior is different in almost every Windows version */
             /* the tests should however succeed on win2000, XP and Wine (at least up to 1.1.15) */
             /* with a variety of dpis and desktop font sizes */
@@ -649,9 +660,9 @@ static void test_mbs_help( int ispop, int hassub, int mnuopt,
     }
     /* if there was a failure, report details */
     if( failed) {
-        trace("*** count %d %s text \"%s\" bitmap %p bmsize %d,%d textsize %d+%d,%d mnuopt %d hastab %d\n",
+        trace("*** count %d %s text \"%s\" bitmap %p bmsize %d,%d textsize %d+%d,%d mnuopt %d hastab %d drawmenu %d\n",
                 count, (ispop? "POPUP": "MENUBAR"),text ? text: "(nil)", hbmp, bmpsize.cx, bmpsize.cy,
-                size.cx, size.cy, sc_size.cx, mnuopt, hastab);
+                size.cx, size.cy, sc_size.cx, mnuopt, hastab, drawmenu);
         trace("    check %d,%d arrow %d avechar %d\n",
                 GetSystemMetrics(SM_CXMENUCHECK ),
                 GetSystemMetrics(SM_CYMENUCHECK ),arrowwidth, MOD_avec);
@@ -659,6 +670,9 @@ static void test_mbs_help( int ispop, int hassub, int mnuopt,
             trace( "    rc %d,%d-%d,%d bmp.rc %d,%d-%d,%d\n",
                 rc.left, rc.top, rc.top, rc.bottom, MOD_rc[0].left,
                 MOD_rc[0].top,MOD_rc[0].right, MOD_rc[0].bottom);
+        else
+            trace("    rc %d,%d-%d,%d\n",
+                rc.left, rc.top, rc.top, rc.bottom);
     }
     /* clean up */
     ret = DestroyMenu(submenu);
@@ -678,7 +692,7 @@ static void test_menu_bmp_and_string(void)
     HMENU hsysmenu;
     MENUINFO mi= {sizeof(MENUINFO)};
     MENUITEMINFOA mii= {sizeof(MENUITEMINFOA)};
-    int count, szidx, txtidx, bmpidx, hassub, mnuopt, ispop;
+    int count, szidx, txtidx, bmpidx, hassub, mnuopt, ispop, drawmenu;
     BOOL got;
 
     if( !pGetMenuInfo)
@@ -731,20 +745,24 @@ static void test_menu_bmp_and_string(void)
                 for( hassub = 0; hassub < 2 ; hassub++) { /* add submenu item */
                     for( mnuopt = 0; mnuopt < 3 ; mnuopt++){ /* test MNS_NOCHECK/MNS_CHECKORBMP */
                         for( bmpidx = 0; bmpidx <sizeof(bitmaps)/sizeof(HBITMAP); bmpidx++) {
-                            /* no need to test NULL bitmaps of several sizes */
-                            if( !bitmaps[bmpidx] && szidx > 0) continue;
-                            /* the HBMMENU_POPUP not to test for menu bars */
-                            if( !ispop &&
-                                bitmaps[bmpidx] >= HBMMENU_POPUP_CLOSE &&
-                                bitmaps[bmpidx] <= HBMMENU_POPUP_MINIMIZE) continue;
-                            if( !ispop && hassub) continue;
-                            test_mbs_help( ispop, hassub, mnuopt,
-                                    hwnd, arrowwidth, ++count,
-                                    bitmaps[bmpidx],
-                                    bmsizes[szidx],
-                                    MOD_txtsizes[txtidx].text,
-                                    MOD_txtsizes[txtidx].size,
-                                    MOD_txtsizes[txtidx].sc_size);
+                            /* GetMenuItemRect works without draw if not popup */
+                            for( drawmenu = 0; drawmenu < 2 ; drawmenu++) {
+                                /* no need to test NULL bitmaps of several sizes */
+                                if( !bitmaps[bmpidx] && szidx > 0) continue;
+                                /* the HBMMENU_POPUP not to test for menu bars */
+                                if( !ispop &&
+                                    bitmaps[bmpidx] >= HBMMENU_POPUP_CLOSE &&
+                                    bitmaps[bmpidx] <= HBMMENU_POPUP_MINIMIZE) continue;
+                                if( !ispop && hassub) continue;
+                                test_mbs_help( ispop, hassub, mnuopt,
+                                        hwnd, arrowwidth, ++count,
+                                        bitmaps[bmpidx],
+                                        bmsizes[szidx],
+                                        MOD_txtsizes[txtidx].text,
+                                        MOD_txtsizes[txtidx].size,
+                                        MOD_txtsizes[txtidx].sc_size,
+                                        drawmenu);
+                            }
                         }
                     }
                 }
-- 
1.7.5.4




More information about the wine-patches mailing list