[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