menu drawing fixes
Rein Klazes
wijn at wanadoo.nl
Sat Feb 4 05:31:42 CST 2006
Hi,
Changelog:
dlls/user : menu.c
dlls/user/tests : menu.c
Updating drawing of menu items with bitmaps and/or strings:
- implemented MNS_NOCHECK menu style;
- support HBMMENU_CALLBACK bitmaps in menu bars;
- replaced some #defined constants by values calculated from windows
metrics;
- added a lot of tests on menu item sizes and the position of the bitmap
and making them pass on Wine.
Rein.
-------------- next part --------------
--- wine/dlls/user/menu.c 2006-01-25 14:28:21.000000000 +0100
+++ mywine/dlls/user/menu.c 2006-02-02 16:44:35.000000000 +0100
@@ -26,12 +26,16 @@
* have been selected, i.e. their popup menu is currently displayed.
* This is probably not the meaning this style has in MS-Windows.
*
+ * Note 2: where there is a difference, these menu API's are according
+ * the behavior of Windows 2k and Windows XP. Known differences with
+ * Windows 9x/ME are documented in the comments, in case an application
+ * is found to depend on the old behavior.
+ *
* TODO:
* implements styles :
* - MNS_AUTODISMISS
* - MNS_DRAGDROP
* - MNS_MODELESS
- * - MNS_NOCHECK
* - MNS_NOTIFYBYPOS
*/
@@ -79,6 +83,8 @@ typedef struct {
/* ----------- Wine stuff ----------- */
RECT rect; /* Item area (relative to menu window) */
UINT xTab; /* X position of text after Tab */
+ SIZE bmpsize; /* size needed for the HBMMENU_CALLBACK
+ * bitmap */
} MENUITEM;
/* Popup menu structure */
@@ -100,7 +106,7 @@ typedef struct {
DWORD dwContextHelpID;
DWORD dwMenuData; /* application defined value */
HMENU hSysMenuOwner; /* Handle to the dummy sys menu holder */
- SIZE maxBmpSize; /* Maximum size of the bitmap items in MIIM_BITMAP state */
+ SIZE maxBmpSize; /* Maximum size of the bitmap items */
} POPUPMENU, *LPPOPUPMENU;
/* internal flags for menu tracking */
@@ -129,15 +135,6 @@ typedef struct
#define TPM_BUTTONDOWN 0x40000000 /* menu was clicked before tracking */
#define TPM_POPUPMENU 0x20000000 /* menu is a popup menu */
- /* Space between 2 menu bar items */
-#define MENU_BAR_ITEMS_SPACE 12
-
- /* Minimum width of a tab character */
-#define MENU_TAB_SPACE 8
-
- /* Height of a separator item */
-#define SEPARATOR_HEIGHT 5
-
/* Space between 2 columns */
#define MENU_COL_SPACE 4
@@ -147,6 +144,7 @@ typedef struct
#define MENU_ITEM_TYPE(flags) \
((flags) & (MF_STRING | MF_BITMAP | MF_OWNERDRAW | MF_SEPARATOR))
+/* macro to test that flags do not indicate bitmap, ownerdraw or separator */
#define IS_STRING_ITEM(flags) (MENU_ITEM_TYPE ((flags)) == MF_STRING)
#define IS_MAGIC_BITMAP(id) ((id) && ((INT_PTR)(id) < 12) && ((INT_PTR)(id) >= -1))
@@ -688,19 +686,36 @@ static UINT MENU_FindItemByKey( HWND hwn
*
* Get the size of a bitmap item.
*/
-static void MENU_GetBitmapItemSize( HBITMAP bmp, DWORD data, SIZE *size )
+static void MENU_GetBitmapItemSize( MENUITEM *lpitem, SIZE *size,
+ HWND hwndOwner)
{
BITMAP bm;
+ HBITMAP bmp = lpitem->hbmpItem;
size->cx = size->cy = 0;
/* check if there is a magic menu item associated with this item */
- switch( (INT_PTR)bmp )
+ switch( (INT_PTR) bmp )
{
+ case (INT_PTR)HBMMENU_CALLBACK:
+ {
+ MEASUREITEMSTRUCT measItem;
+ measItem.CtlType = ODT_MENU;
+ measItem.CtlID = 0;
+ measItem.itemID = lpitem->wID;
+ measItem.itemWidth = lpitem->rect.right - lpitem->rect.left;
+ measItem.itemHeight = lpitem->rect.bottom - lpitem->rect.top;
+ measItem.itemData = lpitem->dwItemData;
+ SendMessageW( hwndOwner, WM_MEASUREITEM, lpitem->wID, (LPARAM)&measItem);
+ size->cx = measItem.itemWidth;
+ size->cy = measItem.itemHeight;
+ return;
+ }
+ break;
case (INT_PTR)HBMMENU_SYSTEM:
- if (data)
+ if (lpitem->dwItemData)
{
- bmp = (HBITMAP)data;
+ bmp = (HBITMAP)lpitem->dwItemData;
break;
}
/* fall through */
@@ -712,7 +727,6 @@ static void MENU_GetBitmapItemSize( HBIT
size->cx = GetSystemMetrics( SM_CYMENU ) - 4;
size->cy = size->cx;
return;
- case (INT_PTR)HBMMENU_CALLBACK:
case (INT_PTR)HBMMENU_POPUP_CLOSE:
case (INT_PTR)HBMMENU_POPUP_RESTORE:
case (INT_PTR)HBMMENU_POPUP_MAXIMIZE:
@@ -732,7 +746,8 @@ static void MENU_GetBitmapItemSize( HBIT
*
* Draw a bitmap item.
*/
-static void MENU_DrawBitmapItem( HDC hdc, MENUITEM *lpitem, const RECT *rect, BOOL menuBar)
+static void MENU_DrawBitmapItem( HDC hdc, MENUITEM *lpitem, const RECT *rect,
+ HMENU hmenu, HWND hwndOwner, UINT odaction, BOOL menuBar)
{
BITMAP bm;
DWORD rop;
@@ -787,6 +802,25 @@ static void MENU_DrawBitmapItem( HDC hdc
flags = DFCS_CAPTIONCLOSE | DFCS_INACTIVE;
break;
case (INT_PTR)HBMMENU_CALLBACK:
+ {
+ DRAWITEMSTRUCT drawItem;
+ drawItem.CtlType = ODT_MENU;
+ drawItem.CtlID = 0;
+ drawItem.itemID = lpitem->wID;
+ drawItem.itemAction = odaction;
+ drawItem.itemState = (lpitem->fState & MF_CHECKED)?ODS_CHECKED:0;
+ drawItem.itemState |= (lpitem->fState & MF_DEFAULT)?ODS_DEFAULT:0;
+ drawItem.itemState |= (lpitem->fState & MF_DISABLED)?ODS_DISABLED:0;
+ drawItem.itemState |= (lpitem->fState & MF_GRAYED)?ODS_GRAYED|ODS_DISABLED:0;
+ drawItem.itemState |= (lpitem->fState & MF_HILITE)?ODS_SELECTED:0;
+ drawItem.hwndItem = (HWND)hmenu;
+ drawItem.hDC = hdc;
+ drawItem.itemData = lpitem->dwItemData;
+ drawItem.rcItem = *rect;
+ SendMessageW( hwndOwner, WM_DRAWITEM, 0, (LPARAM)&drawItem);
+ return;
+ }
+ break;
case (INT_PTR)HBMMENU_POPUP_CLOSE:
case (INT_PTR)HBMMENU_POPUP_RESTORE:
case (INT_PTR)HBMMENU_POPUP_MAXIMIZE:
@@ -831,6 +865,7 @@ static void MENU_CalcItemSize( HDC hdc,
UINT check_bitmap_width = GetSystemMetrics( SM_CXMENUCHECK );
UINT arrow_bitmap_width;
BITMAP bm;
+ INT itemheight;
TRACE("dc=%p owner=%p (%d,%d)\n", hdc, hwndOwner, orgX, orgY);
debug_print_menuitem("MENU_CalcItemSize: menuitem:", lpitem,
@@ -839,18 +874,19 @@ static void MENU_CalcItemSize( HDC hdc,
GetObjectW( get_arrow_bitmap(), sizeof(bm), &bm );
arrow_bitmap_width = bm.bmWidth;
+ /* not done in Menu_Init: GetDialogBaseUnits() breaks there */
+ if( !menucharsize.cx ) {
+ menucharsize.cx = GdiGetCharDimensions( hdc, NULL, &menucharsize.cy );
+ /* Win95/98/ME will use menucharsize.cy here. Testing is possible
+ * but it is unlikely an application will depend on that */
+ ODitemheight = HIWORD( GetDialogBaseUnits());
+ }
+
SetRect( &lpitem->rect, orgX, orgY, orgX, orgY );
if (lpitem->fType & MF_OWNERDRAW)
{
MEASUREITEMSTRUCT mis;
- /* not done in Menu_Init: GetDialogBaseUnits() breaks there */
- if( !menucharsize.cx ) {
- menucharsize.cx = GdiGetCharDimensions( hdc, NULL, &menucharsize.cy );
- /* Win95/98/ME will use menucharsize.cy here. Testing is possible
- * but it is unlikely an application will depend on that */
- ODitemheight = HIWORD( GetDialogBaseUnits());
- }
mis.CtlType = ODT_MENU;
mis.CtlID = 0;
mis.itemID = lpitem->wID;
@@ -877,87 +913,92 @@ static void MENU_CalcItemSize( HDC hdc,
if (lpitem->fType & MF_SEPARATOR)
{
- lpitem->rect.bottom += SEPARATOR_HEIGHT;
- return;
+ lpitem->rect.bottom += GetSystemMetrics( SM_CYMENUSIZE)/2;
+ if( !menuBar)
+ lpitem->rect.right += arrow_bitmap_width + menucharsize.cx;
+ return;
}
- if (!menuBar)
- {
- if (lpitem->hbmpItem)
- {
- if (lpitem->hbmpItem == HBMMENU_CALLBACK)
- {
- MEASUREITEMSTRUCT measItem;
- measItem.CtlType = ODT_MENU;
- measItem.CtlID = 0;
- measItem.itemID = lpitem->wID;
- measItem.itemWidth = lpitem->rect.right - lpitem->rect.left;
- measItem.itemHeight = lpitem->rect.bottom - lpitem->rect.top;
- measItem.itemData = lpitem->dwItemData;
-
- SendMessageW( hwndOwner, WM_MEASUREITEM, lpitem->wID, (LPARAM)&measItem);
-
- /* Keep the size of the bitmap in callback mode to be able to draw it correctly */
- lppop->maxBmpSize.cx = max(lppop->maxBmpSize.cx, measItem.itemWidth - (lpitem->rect.right - lpitem->rect.left));
- lppop->maxBmpSize.cy = max(lppop->maxBmpSize.cy, measItem.itemHeight - (lpitem->rect.bottom - lpitem->rect.top));
- lpitem->rect.right = lpitem->rect.left + measItem.itemWidth;
- } else {
- SIZE size;
- MENU_GetBitmapItemSize(lpitem->hbmpItem, lpitem->dwItemData, &size);
- lppop->maxBmpSize.cx = max(lppop->maxBmpSize.cx, size.cx);
- lppop->maxBmpSize.cy = max(lppop->maxBmpSize.cy, size.cy);
- lpitem->rect.right += size.cx;
- lpitem->rect.bottom += size.cy;
- }
- if (lppop->dwStyle & MNS_CHECKORBMP)
- lpitem->rect.right += check_bitmap_width;
- else
- lpitem->rect.right += 2 * check_bitmap_width;
- } else
- lpitem->rect.right += 2 * check_bitmap_width;
- if (lpitem->fType & MF_POPUP)
- lpitem->rect.right += arrow_bitmap_width;
- } else if (lpitem->hbmpItem)
- {
+ itemheight = 0;
+
+ if (!menuBar) {
+ if (lpitem->hbmpItem) {
+ SIZE size;
+
+ MENU_GetBitmapItemSize(lpitem, &size, hwndOwner);
+ /* Keep the size of the bitmap in callback mode to be able
+ * to draw it correctly */
+ lpitem->bmpsize = size;
+ lppop->maxBmpSize.cx = max( lppop->maxBmpSize.cx, size.cx);
+ lppop->maxBmpSize.cy = max( lppop->maxBmpSize.cy, size.cy);
+ lpitem->rect.right += size.cx + 2;
+ itemheight = size.cy + 2;
+ }
+ lpitem->rect.right += 4 + arrow_bitmap_width + menucharsize.cx;
+ if( !(lppop->dwStyle & MNS_NOCHECK))
+ lpitem->rect.right += check_bitmap_width;
+ } else if (lpitem->hbmpItem) { /* menuBar */
SIZE size;
- MENU_GetBitmapItemSize( (HBITMAP) lpitem->hbmpItem, lpitem->dwItemData, &size );
+ MENU_GetBitmapItemSize( lpitem, &size, hwndOwner );
+ lpitem->bmpsize = size;
lpitem->rect.right += size.cx;
- lpitem->rect.bottom += size.cy;
- /* Leave space for the sunken border */
- lpitem->rect.right += 2;
- lpitem->rect.bottom += 2;
+ if( lpitem->text) lpitem->rect.right += 2;
+ itemheight = size.cy;
}
/* it must be a text item - unless it's the system menu */
- if (!(lpitem->fType & MF_SYSMENU) && lpitem->text)
- { SIZE size;
-
- GetTextExtentPoint32W(hdc, lpitem->text, strlenW(lpitem->text), &size);
-
- lpitem->rect.right += size.cx;
- lpitem->rect.bottom += max(max(size.cy, GetSystemMetrics(SM_CYMENU)-1), lppop->maxBmpSize.cy);
- lpitem->xTab = 0;
-
- if (menuBar)
- {
- lpitem->rect.right += MENU_BAR_ITEMS_SPACE;
- }
- else if ((p = strchrW( lpitem->text, '\t' )) != NULL)
- {
- /* Item contains a tab (only meaningful in popup menus) */
- GetTextExtentPoint32W(hdc, lpitem->text, (int)(p - lpitem->text) , &size);
- lpitem->xTab = check_bitmap_width + MENU_TAB_SPACE + size.cx;
- lpitem->rect.right += MENU_TAB_SPACE;
- }
- else
- {
- if (strchrW( lpitem->text, '\b' ))
- lpitem->rect.right += MENU_TAB_SPACE;
- lpitem->xTab = lpitem->rect.right - check_bitmap_width
- - arrow_bitmap_width;
- }
+ if (!(lpitem->fType & MF_SYSMENU) && lpitem->text) {
+ RECT rc = lpitem->rect;
+ LONG txtheight, txtwidth;
+ lpitem->xTab = 0;
+ if (menuBar) {
+ txtheight = DrawTextW( hdc, lpitem->text, -1, &rc,
+ DT_SINGLELINE|DT_CALCRECT);
+ lpitem->rect.right += rc.right - rc.left;
+ itemheight = max( max( itemheight, txtheight),
+ GetSystemMetrics( SM_CYMENU) - 1);
+ lpitem->rect.right += 2 * menucharsize.cx;
+ } else {
+ if ((p = strchrW( lpitem->text, '\t' )) != NULL) {
+ RECT tmprc = rc;
+ LONG tmpheight;
+ int n = (int)( p - lpitem->text);
+ /* Item contains a tab (only meaningful in popup menus) */
+ /* get text size before the tab */
+ txtheight = DrawTextW( hdc, lpitem->text, n, &rc,
+ DT_SINGLELINE|DT_CALCRECT);
+ txtwidth = rc.right - rc.left;
+ p += 1; /* advance past the Tab */
+ tmpheight = DrawTextW( hdc, p, -1, &tmprc,
+ DT_SINGLELINE|DT_CALCRECT);
+ lpitem->xTab = menucharsize.cx +
+ 4 + check_bitmap_width + lpitem->bmpsize.cx + txtwidth;
+ txtheight = max( txtheight, tmpheight);
+ txtwidth += menucharsize.cx + /* space for the tab */
+ tmprc.right - tmprc.left; /* space for the short cut */
+ } else {
+ txtheight = DrawTextW( hdc, lpitem->text, -1, &rc,
+ DT_SINGLELINE|DT_CALCRECT);
+ txtwidth = rc.right - rc.left;
+ if (strchrW( lpitem->text, '\b' ))
+ lpitem->rect.right += menucharsize.cx;
+ lpitem->xTab = 4 + check_bitmap_width + lpitem->bmpsize.cx +
+ txtwidth;
+ }
+ if( (lppop->dwStyle & MNS_NOCHECK))
+ lpitem->xTab -= check_bitmap_width;
+ lpitem->rect.right += 2 + txtwidth;
+ itemheight = max( itemheight,
+ max( txtheight + 2, menucharsize.cy + 4));
+ }
+ } else if( menuBar) {
+ if( itemheight)
+ itemheight = max( itemheight, GetSystemMetrics(SM_CYMENU)-1);
+ else
+ itemheight = GetSystemMetrics( SM_CYMENUSIZE)/2;
}
+ lpitem->rect.bottom += itemheight;
TRACE("%s\n", wine_dbgstr_rect( &lpitem->rect));
}
@@ -1110,6 +1151,25 @@ static void MENU_MenuBarCalcSize( HDC hd
}
/***********************************************************************
+ * draw_popup_arrow
+ *
+ * Draws the popup-menu arrow.
+ */
+static void draw_popup_arrow( HDC hdc, RECT rect, UINT arrow_bitmap_width,
+ UINT arrow_bitmap_height)
+{
+ HDC hdcMem = CreateCompatibleDC( hdc );
+ HBITMAP hOrigBitmap;
+
+ hOrigBitmap = SelectObject( hdcMem, get_arrow_bitmap() );
+ BitBlt( hdc, rect.right - arrow_bitmap_width - 1,
+ (rect.top + rect.bottom - arrow_bitmap_height) / 2,
+ arrow_bitmap_width, arrow_bitmap_height,
+ hdcMem, 0, 0, SRCCOPY );
+ SelectObject( hdcMem, hOrigBitmap );
+ DeleteDC( hdcMem );
+}
+/***********************************************************************
* MENU_DrawMenuItem
*
* Draw a single menu item.
@@ -1120,9 +1180,19 @@ static void MENU_DrawMenuItem( HWND hwnd
RECT rect;
BOOL flat_menu = FALSE;
int bkgnd;
+ POPUPMENU *menu = MENU_GetMenu(hmenu);
+ UINT arrow_bitmap_width = 0, arrow_bitmap_height = 0;
+ RECT bmprc;
debug_print_menuitem("MENU_DrawMenuItem: ", lpitem, "");
+ if (!menuBar) {
+ BITMAP bmp;
+ GetObjectW( get_arrow_bitmap(), sizeof(bmp), &bmp );
+ arrow_bitmap_width = bmp.bmWidth;
+ arrow_bitmap_height = bmp.bmHeight;
+ }
+
if (lpitem->fType & MF_SYSMENU)
{
if( !IsIconic(hwnd) )
@@ -1187,7 +1257,11 @@ static void MENU_DrawMenuItem( HWND hwnd
dis.itemID, dis.itemState, dis.itemAction, dis.hwndItem,
dis.hDC, wine_dbgstr_rect( &dis.rcItem));
SendMessageW( hwndOwner, WM_DRAWITEM, 0, (LPARAM)&dis );
- /* Fall through to draw popup-menu arrow */
+ /* Draw the popup-menu arrow */
+ if (lpitem->fType & MF_POPUP)
+ draw_popup_arrow( hdc, rect, arrow_bitmap_width,
+ arrow_bitmap_height);
+ return;
}
TRACE("rect=%s\n", wine_dbgstr_rect( &lpitem->rect));
@@ -1196,70 +1270,66 @@ static void MENU_DrawMenuItem( HWND hwnd
rect = lpitem->rect;
- if (!(lpitem->fType & MF_OWNERDRAW))
+ if (lpitem->fState & MF_HILITE)
{
- if (lpitem->fState & MF_HILITE)
- {
- if (flat_menu)
- {
- InflateRect (&rect, -1, -1);
- FillRect(hdc, &rect, GetSysColorBrush(COLOR_MENUHILIGHT));
- InflateRect (&rect, 1, 1);
- FrameRect(hdc, &rect, GetSysColorBrush(COLOR_HIGHLIGHT));
- }
- else
- {
- if(menuBar)
- DrawEdge(hdc, &rect, BDR_SUNKENOUTER, BF_RECT);
- else
- FillRect(hdc, &rect, GetSysColorBrush(COLOR_HIGHLIGHT));
- }
- }
+ if (flat_menu)
+ {
+ InflateRect (&rect, -1, -1);
+ FillRect(hdc, &rect, GetSysColorBrush(COLOR_MENUHILIGHT));
+ InflateRect (&rect, 1, 1);
+ FrameRect(hdc, &rect, GetSysColorBrush(COLOR_HIGHLIGHT));
+ }
else
- FillRect( hdc, &rect, GetSysColorBrush(bkgnd) );
+ {
+ if(menuBar)
+ DrawEdge(hdc, &rect, BDR_SUNKENOUTER, BF_RECT);
+ else
+ FillRect(hdc, &rect, GetSysColorBrush(COLOR_HIGHLIGHT));
+ }
}
+ else
+ FillRect( hdc, &rect, GetSysColorBrush(bkgnd) );
SetBkMode( hdc, TRANSPARENT );
- if (!(lpitem->fType & MF_OWNERDRAW))
+ /* vertical separator */
+ if (!menuBar && (lpitem->fType & MF_MENUBARBREAK))
{
- HPEN oldPen;
-
- /* vertical separator */
- if (!menuBar && (lpitem->fType & MF_MENUBARBREAK))
+ HPEN oldPen;
+ RECT rc = rect;
+
+ rc.top = 3;
+ rc.bottom = height - 3;
+ if (flat_menu)
{
- RECT rc = rect;
- rc.top = 3;
- rc.bottom = height - 3;
- if (flat_menu)
- {
- oldPen = SelectObject( hdc, SYSCOLOR_GetPen(COLOR_BTNSHADOW) );
- MoveToEx( hdc, rc.left, rc.top, NULL );
- LineTo( hdc, rc.left, rc.bottom );
- SelectObject( hdc, oldPen );
- }
- else
- DrawEdge (hdc, &rc, EDGE_ETCHED, BF_LEFT);
+ oldPen = SelectObject( hdc, SYSCOLOR_GetPen(COLOR_BTNSHADOW) );
+ MoveToEx( hdc, rc.left, rc.top, NULL );
+ LineTo( hdc, rc.left, rc.bottom );
+ SelectObject( hdc, oldPen );
}
+ else
+ DrawEdge (hdc, &rc, EDGE_ETCHED, BF_LEFT);
+ }
- /* horizontal separator */
- if (lpitem->fType & MF_SEPARATOR)
+ /* horizontal separator */
+ if (lpitem->fType & MF_SEPARATOR)
+ {
+ HPEN oldPen;
+ RECT rc = rect;
+
+ rc.left++;
+ rc.right--;
+ rc.top = ( rc.top + rc.bottom) / 2;
+ if (flat_menu)
{
- RECT rc = rect;
- rc.left++;
- rc.right--;
- rc.top += SEPARATOR_HEIGHT / 2;
- if (flat_menu)
- {
- oldPen = SelectObject( hdc, SYSCOLOR_GetPen(COLOR_BTNSHADOW) );
- MoveToEx( hdc, rc.left, rc.top, NULL );
- LineTo( hdc, rc.right, rc.top );
- SelectObject( hdc, oldPen );
- }
- else
- DrawEdge (hdc, &rc, EDGE_ETCHED, BF_TOP);
- return;
+ oldPen = SelectObject( hdc, SYSCOLOR_GetPen(COLOR_BTNSHADOW) );
+ MoveToEx( hdc, rc.left, rc.top, NULL );
+ LineTo( hdc, rc.right, rc.top );
+ SelectObject( hdc, oldPen );
}
+ else
+ DrawEdge (hdc, &rc, EDGE_ETCHED, BF_TOP);
+ return;
}
/* helper lines for debugging */
@@ -1269,119 +1339,97 @@ static void MENU_DrawMenuItem( HWND hwnd
LineTo( hdc, rect.right, (rect.top + rect.bottom)/2 );
*/
+ if (lpitem->hbmpItem) {
+ /* calculate the bitmap rectangle in coordinates relative
+ * to the item rectangle */
+ if( menuBar) {
+ if( lpitem->hbmpItem == HBMMENU_CALLBACK)
+ bmprc.left = 3;
+ else
+ bmprc.left = lpitem->text ? menucharsize.cx : 0;
+ } else {
+ bmprc.left = 4;
+ if( !(menu->dwStyle & ( MNS_CHECKORBMP | MNS_NOCHECK)))
+ bmprc.left += GetSystemMetrics( SM_CXMENUCHECK);
+ }
+ bmprc.right = bmprc.left + lpitem->bmpsize.cx;
+ if( menuBar && !(lpitem->hbmpItem == HBMMENU_CALLBACK))
+ bmprc.top = 0;
+ else
+ bmprc.top = (lpitem->rect.bottom - lpitem->rect.top -
+ lpitem->bmpsize.cy) / 2;
+ bmprc.bottom = bmprc.top + lpitem->bmpsize.cy;
+ }
+
if (!menuBar)
{
HBITMAP bm;
INT y = rect.top + rect.bottom;
+ RECT rc = rect;
+ int checked = FALSE;
UINT check_bitmap_width = GetSystemMetrics( SM_CXMENUCHECK );
UINT check_bitmap_height = GetSystemMetrics( SM_CYMENUCHECK );
- UINT arrow_bitmap_width, arrow_bitmap_height;
- BITMAP bmp;
-
- GetObjectW( get_arrow_bitmap(), sizeof(bmp), &bmp );
- arrow_bitmap_width = bmp.bmWidth;
- arrow_bitmap_height = bmp.bmHeight;
-
- if (!(lpitem->fType & MF_OWNERDRAW))
- {
- RECT rc;
- rc = rect;
- if (lpitem->hbmpItem)
- {
- POPUPMENU *menu = MENU_GetMenu(hmenu);
- if (menu->dwStyle & MNS_CHECKORBMP)
- rc.left += menu->maxBmpSize.cx - check_bitmap_width;
- else
- rc.left += menu->maxBmpSize.cx;
- }
- /* Draw the check mark
- *
- * FIXME:
- * Custom checkmark bitmaps are monochrome but not always 1bpp.
- */
- bm = (lpitem->fState & MF_CHECKED) ? lpitem->hCheckBit : lpitem->hUnCheckBit;
- if (bm) /* we have a custom bitmap */
- {
+ /* Draw the check mark
+ *
+ * FIXME:
+ * Custom checkmark bitmaps are monochrome but not always 1bpp.
+ */
+ if( !(menu->dwStyle & MNS_NOCHECK)) {
+ bm = (lpitem->fState & MF_CHECKED) ? lpitem->hCheckBit :
+ lpitem->hUnCheckBit;
+ if (bm) {/* we have a custom bitmap */
HDC hdcMem = CreateCompatibleDC( hdc );
+
SelectObject( hdcMem, bm );
BitBlt( hdc, rc.left, (y - check_bitmap_height) / 2,
check_bitmap_width, check_bitmap_height,
hdcMem, 0, 0, SRCCOPY );
DeleteDC( hdcMem );
- }
- else if (lpitem->fState & MF_CHECKED) /* standard bitmaps */
- {
+ checked = TRUE;
+ } else if (lpitem->fState & MF_CHECKED) {/* standard bitmaps */
RECT r;
- HBITMAP bm = CreateBitmap( check_bitmap_width, check_bitmap_height, 1, 1, NULL );
+ HBITMAP bm = CreateBitmap( check_bitmap_width,
+ check_bitmap_height, 1, 1, NULL );
HDC hdcMem = CreateCompatibleDC( hdc );
+
SelectObject( hdcMem, bm );
- SetRect( &r, 0, 0, check_bitmap_width, check_bitmap_height );
+ SetRect( &r, 0, 0, check_bitmap_width, check_bitmap_height);
DrawFrameControl( hdcMem, &r, DFC_MENU,
- (lpitem->fType & MFT_RADIOCHECK) ?
- DFCS_MENUBULLET : DFCS_MENUCHECK );
+ (lpitem->fType & MFT_RADIOCHECK) ?
+ DFCS_MENUBULLET : DFCS_MENUCHECK );
BitBlt( hdc, rc.left, (y - r.bottom) / 2, r.right, r.bottom,
hdcMem, 0, 0, SRCCOPY );
DeleteDC( hdcMem );
DeleteObject( bm );
- }
- if (lpitem->hbmpItem)
- {
- HBITMAP hbm = lpitem->hbmpItem;
-
- if (hbm == HBMMENU_CALLBACK)
- {
- DRAWITEMSTRUCT drawItem;
- POINT origorg;
- drawItem.CtlType = ODT_MENU;
- drawItem.CtlID = 0;
- drawItem.itemID = lpitem->wID;
- drawItem.itemAction = odaction;
- drawItem.itemState = (lpitem->fState & MF_CHECKED)?ODS_CHECKED:0;
- drawItem.itemState |= (lpitem->fState & MF_DEFAULT)?ODS_DEFAULT:0;
- drawItem.itemState |= (lpitem->fState & MF_DISABLED)?ODS_DISABLED:0;
- drawItem.itemState |= (lpitem->fState & MF_GRAYED)?ODS_GRAYED|ODS_DISABLED:0;
- drawItem.itemState |= (lpitem->fState & MF_HILITE)?ODS_SELECTED:0;
- drawItem.hwndItem = (HWND)hmenu;
- drawItem.hDC = hdc;
- drawItem.rcItem = lpitem->rect;
- drawItem.itemData = lpitem->dwItemData;
- /* some applications make this assumption on the DC's origin */
- SetViewportOrgEx( hdc, lpitem->rect.left, lpitem->rect.top, &origorg);
- OffsetRect( &drawItem.rcItem, - lpitem->rect.left, - lpitem->rect.top);
- SendMessageW( hwndOwner, WM_DRAWITEM, 0, (LPARAM)&drawItem);
- SetViewportOrgEx( hdc, origorg.x, origorg.y, NULL);
-
- } else {
- MENU_DrawBitmapItem(hdc, lpitem, &rect, FALSE);
- }
+ checked = TRUE;
}
}
-
- /* Draw the popup-menu arrow */
- if (lpitem->fType & MF_POPUP)
- {
- HDC hdcMem = CreateCompatibleDC( hdc );
- HBITMAP hOrigBitmap;
-
- hOrigBitmap = SelectObject( hdcMem, get_arrow_bitmap() );
- BitBlt( hdc, rect.right - arrow_bitmap_width - 1,
- (y - arrow_bitmap_height) / 2,
- arrow_bitmap_width, arrow_bitmap_height,
- hdcMem, 0, 0, SRCCOPY );
- SelectObject( hdcMem, hOrigBitmap );
- DeleteDC( hdcMem );
- }
-
- rect.left += check_bitmap_width;
+ if( lpitem->hbmpItem &&
+ !( checked && (menu->dwStyle & MNS_CHECKORBMP))) {
+ POINT origorg;
+ /* some applications make this assumption on the DC's origin */
+ SetViewportOrgEx( hdc, lpitem->rect.left, lpitem->rect.top, &origorg);
+ MENU_DrawBitmapItem(hdc, lpitem, &bmprc, hmenu, hwndOwner,
+ odaction, FALSE);
+ SetViewportOrgEx( hdc, origorg.x, origorg.y, NULL);
+ }
+ /* Draw the popup-menu arrow */
+ if (lpitem->fType & MF_POPUP)
+ draw_popup_arrow( hdc, rect, arrow_bitmap_width,
+ arrow_bitmap_height);
+ rect.left += 4;
+ if( !(menu->dwStyle & MNS_NOCHECK)) rect.left += check_bitmap_width;
rect.right -= arrow_bitmap_width;
}
- else if( lpitem->hbmpItem && !(lpitem->fType & MF_OWNERDRAW))
+ else if( lpitem->hbmpItem)
{ /* Draw the bitmap */
- MENU_DrawBitmapItem( hdc, lpitem, &rect, menuBar);
+ POINT origorg;
+
+ SetViewportOrgEx( hdc, lpitem->rect.left, lpitem->rect.top, &origorg);
+ MENU_DrawBitmapItem( hdc, lpitem, &bmprc, hmenu, hwndOwner,
+ odaction, menuBar);
+ SetViewportOrgEx( hdc, origorg.x, origorg.y, NULL);
}
- /* Done for owner-drawn */
- if (lpitem->fType & MF_OWNERDRAW)
- return;
/* process text if present */
if (lpitem->text)
{
@@ -1392,15 +1440,20 @@ static void MENU_DrawMenuItem( HWND hwnd
DT_CENTER | DT_VCENTER | DT_SINGLELINE :
DT_LEFT | DT_VCENTER | DT_SINGLELINE;
+ if( !(menu->dwStyle & MNS_CHECKORBMP))
+ rect.left += menu->maxBmpSize.cx;
+
if ( lpitem->fState & MFS_DEFAULT )
{
hfontOld = SelectObject( hdc, get_menu_font(TRUE) );
}
- if (menuBar)
- {
- rect.left += MENU_BAR_ITEMS_SPACE / 2;
- rect.right -= MENU_BAR_ITEMS_SPACE / 2;
+ if (menuBar) {
+ if( lpitem->hbmpItem)
+ rect.left += lpitem->bmpsize.cx;
+ if( !(lpitem->hbmpItem == HBMMENU_CALLBACK))
+ rect.left += menucharsize.cx;
+ rect.right -= menucharsize.cx;
}
for (i = 0; lpitem->text[i]; i++)
@@ -1451,6 +1504,7 @@ static void MENU_DrawMenuItem( HWND hwnd
if (hfontOld)
SelectObject (hdc, hfontOld);
}
+ return;
}
@@ -4079,16 +4133,19 @@ static BOOL GetMenuItemInfo_common ( HME
if( lpmii->fMask & MIIM_TYPE) {
if( lpmii->fMask & ( MIIM_STRING | MIIM_FTYPE | MIIM_BITMAP)) {
+ WARN("invalid combination of fMask bits used\n");
+ /* this does not happen on Win9x/ME */
SetLastError( ERROR_INVALID_PARAMETER);
return FALSE;
}
lpmii->fType = menu->fType & ~MF_POPUP;
if( menu->hbmpItem) lpmii->fType |= MFT_BITMAP;
- lpmii->hbmpItem = menu->hbmpItem;
+ lpmii->hbmpItem = menu->hbmpItem; /* not on Win9x/ME */
if( lpmii->fType & MFT_BITMAP) {
lpmii->dwTypeData = (LPWSTR) menu->hbmpItem;
lpmii->cch = 0;
} else if( lpmii->fType & (MFT_OWNERDRAW | MFT_SEPARATOR)) {
+ /* this does not happen on Win9x/ME */
lpmii->dwTypeData = 0;
lpmii->cch = 0;
}
@@ -4127,8 +4184,11 @@ static BOOL GetMenuItemInfo_common ( HME
lpmii->cch--;
else
lpmii->cch = len;
- else /* return length of string */
+ else {
+ /* return length of string */
+ /* not on Win9x/ME if fType & MFT_BITMAP */
lpmii->cch = len;
+ }
}
}
@@ -4146,8 +4206,11 @@ static BOOL GetMenuItemInfo_common ( HME
if (lpmii->fMask & MIIM_SUBMENU)
lpmii->hSubMenu = menu->hSubMenu;
- else
- lpmii->hSubMenu = 0; /* hSubMenu is always cleared */
+ else {
+ /* hSubMenu is always cleared
+ * (not on Win9x/ME ) */
+ lpmii->hSubMenu = 0;
+ }
if (lpmii->fMask & MIIM_CHECKMARKS) {
lpmii->hbmpChecked = menu->hCheckBit;
@@ -4233,10 +4296,12 @@ static BOOL SetMenuItemInfo_common(MENUI
{
if (!menu) return FALSE;
- debug_print_menuitem("MENU_SetItemInfo_common from: ", menu, "");
+ debug_print_menuitem("SetmenuItemInfo_common from: ", menu, "");
if (lpmii->fMask & MIIM_TYPE ) {
if( lpmii->fMask & ( MIIM_STRING | MIIM_FTYPE | MIIM_BITMAP)) {
+ WARN("invalid combination of fMask bits used\n");
+ /* this does not happen on Win9x/ME */
SetLastError( ERROR_INVALID_PARAMETER);
return FALSE;
}
@@ -4603,7 +4668,6 @@ BOOL WINAPI SetMenuInfo (HMENU hMenu, LP
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");
- if (menu->dwStyle & MNS_NOCHECK) FIXME("MNS_NOCHECK unimplemented\n");
if (menu->dwStyle & MNS_NOTIFYBYPOS) FIXME("MNS_NOTIFYBYPOS unimplemented\n");
}
--- wine/dlls/user/tests/menu.c 2006-02-03 11:24:11.000000000 +0100
+++ mywine/dlls/user/tests/menu.c 2006-02-03 20:32:29.000000000 +0100
@@ -23,6 +23,7 @@
#include <stdlib.h>
#include <stdarg.h>
+#include <stdio.h>
#include <assert.h>
#include "windef.h"
@@ -34,6 +35,9 @@
static ATOM atomMenuCheckClass;
+static BOOL (WINAPI *pSetMenuInfo)(HMENU,LPCMENUINFO);
+static BOOL (WINAPI *pGetMenuInfo)(HMENU,LPCMENUINFO);
+
static LRESULT WINAPI menu_check_wnd_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
{
switch (msg)
@@ -49,11 +53,30 @@ static LRESULT WINAPI menu_check_wnd_pro
}
/* globals to communicate between test and wndproc */
+
+#define MOD_SIZE 10
+#define MOD_NRMENUS 8
+
+ /* menu texts with their sizes */
+static struct {
+ char *text;
+ SIZE size; /* size of text upto any \t */
+ SIZE sc_size; /* size of the short-cut */
+} MOD_txtsizes[] = {
+ { "Pinot &Noir" },
+ { "&Merlot\t" },
+ { "Shira&z\tAlt+S" },
+ { "" },
+ { NULL }
+};
+
unsigned int MOD_maxid;
-RECT MOD_rc[4];
+RECT MOD_rc[MOD_NRMENUS];
int MOD_avec, MOD_hic;
int MOD_odheight;
-#define MOD_SIZE 10
+SIZE MODsizes[MOD_NRMENUS]= { {MOD_SIZE, MOD_SIZE},{MOD_SIZE, MOD_SIZE},
+ {MOD_SIZE, MOD_SIZE},{MOD_SIZE, MOD_SIZE}};
+int MOD_GotDrawItemMsg = FALSE;
/* wndproc used by test_menu_ownerdraw() */
static LRESULT WINAPI menu_ownerdraw_wnd_proc(HWND hwnd, UINT msg,
WPARAM wparam, LPARAM lparam)
@@ -64,11 +87,11 @@ static LRESULT WINAPI menu_ownerdraw_wnd
{
MEASUREITEMSTRUCT* pmis = (MEASUREITEMSTRUCT*)lparam;
if( winetest_debug)
- trace("WM_MEASUREITEM received %d,%d\n",
- pmis->itemWidth, pmis->itemHeight);
+ trace("WM_MEASUREITEM received data %lx size %dx%d\n",
+ pmis->itemData, pmis->itemWidth, pmis->itemHeight);
MOD_odheight = pmis->itemHeight;
- pmis->itemWidth = MOD_SIZE;
- pmis->itemHeight = MOD_SIZE;
+ pmis->itemWidth = MODsizes[pmis->itemData].cx;
+ pmis->itemHeight = MODsizes[pmis->itemData].cy;
return TRUE;
}
case WM_DRAWITEM:
@@ -78,18 +101,41 @@ static LRESULT WINAPI menu_ownerdraw_wnd
HPEN oldpen;
char chrs[]="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
SIZE sz;
+ int i;
pdis = (DRAWITEMSTRUCT *) lparam;
if( winetest_debug) {
- trace("WM_DRAWITEM received itemdata %ld item %d rc %ld,%ld-%ld,%ld\n",
- pdis->itemData,
+ RECT rc;
+ GetMenuItemRect( hwnd, (HMENU)pdis->hwndItem, pdis->itemData ,&rc);
+ trace("WM_DRAWITEM received hwnd %p hmenu %p itemdata %ld item %d rc %ld,%ld-%ld,%ld itemrc: %ld,%ld-%ld,%ld\n",
+ hwnd, (HMENU)pdis->hwndItem, pdis->itemData,
pdis->itemID, pdis->rcItem.left, pdis->rcItem.top,
- pdis->rcItem.right,pdis->rcItem.bottom );
+ pdis->rcItem.right,pdis->rcItem.bottom,
+ rc.left,rc.top,rc.right,rc.bottom);
oldpen=SelectObject( pdis->hDC, GetStockObject(
pdis->itemState & ODS_SELECTED ? WHITE_PEN :BLACK_PEN));
Rectangle( pdis->hDC, pdis->rcItem.left,pdis->rcItem.top,
pdis->rcItem.right,pdis->rcItem.bottom );
SelectObject( pdis->hDC, oldpen);
}
+ /* calculate widths of some menu texts */
+ if( ! MOD_txtsizes[0].size.cx)
+ for(i = 0; MOD_txtsizes[i].text; i++) {
+ char buf[100], *p;
+ RECT rc={0,0,0,0};
+ strcpy( buf, MOD_txtsizes[i].text);
+ if( ( p = strchr( buf, '\t'))) {
+ *p = '\0';
+ DrawText( pdis->hDC, p + 1, -1, &rc,
+ DT_SINGLELINE|DT_CALCRECT);
+ MOD_txtsizes[i].sc_size.cx= rc.right - rc.left;
+ MOD_txtsizes[i].sc_size.cy= rc.bottom - rc.top;
+ }
+ DrawText( pdis->hDC, buf, -1, &rc,
+ DT_SINGLELINE|DT_CALCRECT);
+ MOD_txtsizes[i].size.cx= rc.right - rc.left;
+ MOD_txtsizes[i].size.cy= rc.bottom - rc.top;
+ }
+
if( pdis->itemData > MOD_maxid) return TRUE;
/* store the rectangl */
MOD_rc[pdis->itemData] = pdis->rcItem;
@@ -98,7 +144,12 @@ static LRESULT WINAPI menu_ownerdraw_wnd
MOD_avec = (sz.cx + 26)/52;
GetTextMetrics( pdis->hDC, &tm);
MOD_hic = tm.tmHeight;
- if( pdis->itemData == MOD_maxid) PostMessage(hwnd, WM_CANCELMODE, 0, 0);
+ MOD_GotDrawItemMsg = TRUE;
+ return TRUE;
+ }
+ case WM_ENTERIDLE:
+ {
+ PostMessage(hwnd, WM_CANCELMODE, 0, 0);
return TRUE;
}
@@ -236,7 +287,7 @@ static void test_menu_ownerdraw(void)
ret = AppendMenu( hmenu, MF_OWNERDRAW , i, 0);
ok( ret, "AppendMenu failed for %d\n", i);
}
- SetMenu( hwnd, hmenu);
+ ret = SetMenu( hwnd, hmenu);
UpdateWindow( hwnd); /* hack for wine to draw the window + menu */
ok(ret, "SetMenu failed with error %ld\n", GetLastError());
/* test width */
@@ -247,6 +298,207 @@ static void test_menu_ownerdraw(void)
ok( MOD_rc[0].bottom - MOD_rc[0].top == GetSystemMetrics( SM_CYMENU) - 1,
"Height of owner drawn menu item is wrong. Got %ld expected %d\n",
MOD_rc[0].bottom - MOD_rc[0].top, GetSystemMetrics( SM_CYMENU) - 1);
+
+ /* clean up */
+ ret = DestroyMenu(hmenu);
+ ok(ret, "DestroyMenu failed with error %ld\n", GetLastError());
+ DestroyWindow(hwnd);
+}
+
+/* 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, char *text, SIZE size, SIZE sc_size)
+{
+ BOOL ret;
+ HMENU hmenu, submenu;
+ MENUITEMINFO mii={ sizeof( MENUITEMINFO )};
+ MENUINFO mi;
+ RECT rc;
+ int hastab, expect;
+ int failed = 0;
+
+ MOD_GotDrawItemMsg = FALSE;
+ mii.fMask = MIIM_FTYPE | MIIM_DATA | MIIM_STATE;
+ mii.fType = 0;
+ mii.fState = MF_CHECKED;
+ mii.dwItemData =0;
+ MODsizes[0] = bmpsize;
+ hastab = 0;
+ if( text ) {
+ char *p;
+ mii.fMask |= MIIM_STRING;
+ mii.dwTypeData = text;
+ if( ( p = strchr( text, '\t'))) {
+ hastab = *(p + 1) ? 2 : 1;
+ }
+ }
+ /* tabs don't make sense in menubars */
+ if(hastab && !ispop) return;
+ if( hbmp) {
+ mii.fMask |= MIIM_BITMAP;
+ mii.hbmpItem = hbmp;
+ }
+ submenu = CreateMenu();
+ ok( submenu != 0, "CreateMenu failed with error %ld\n", GetLastError());
+ if( ispop)
+ hmenu = CreatePopupMenu();
+ else
+ hmenu = CreateMenu();
+ ok( hmenu != 0, "Create{Popup}Menu failed with error %ld\n", GetLastError());
+ if( hassub) {
+ mii.fMask |= MIIM_SUBMENU;
+ mii.hSubMenu = submenu;
+ }
+ if( mnuopt) {
+ mi.cbSize = sizeof(mi);
+ mi.fMask = MIM_STYLE;
+ pGetMenuInfo( hmenu, &mi);
+ mi.dwStyle |= mnuopt == 1 ? MNS_NOCHECK : MNS_CHECKORBMP;
+ ret = pSetMenuInfo( hmenu, &mi);
+ ok( ret, "SetMenuInfo failed with error %ld\n", GetLastError());
+ }
+ ret = InsertMenuItem( hmenu, 0, FALSE, &mii);
+ ok( ret, "InsertMenuItem failed with error %ld\n", GetLastError());
+ failed = !ret;
+ if( winetest_debug) {
+ HDC hdc=GetDC(hwnd);
+ RECT rc = {100, 50, 400, 70};
+ char buf[100];
+
+ sprintf( buf,"%d text \"%s\" mnuopt %d", count, text ? text: "(nil)", mnuopt);
+ FillRect( hdc, &rc, (HBRUSH) COLOR_WINDOW);
+ TextOut( hdc, 100, 50, buf, strlen( buf));
+ ReleaseDC( hwnd, hdc);
+ }
+ if(ispop)
+ ret = TrackPopupMenu( hmenu, 0x100, 100,100, 0, hwnd, NULL);
+ else {
+ ret = SetMenu( hwnd, hmenu);
+ ok(ret, "SetMenu failed with error %ld\n", GetLastError());
+ DrawMenuBar( hwnd);
+ }
+ ret = GetMenuItemRect( hwnd, hmenu, 0, &rc);
+ /* check menu width */
+ if( ispop)
+ expect = ( text || hbmp ?
+ 4 + (mnuopt != 1 ? GetSystemMetrics(SM_CXMENUCHECK) : 0)
+ : 0) +
+ arrowwidth + MOD_avec + (hbmp ? bmpsize.cx + 2 : 0) +
+ (text && hastab ? /* TAB space */
+ MOD_avec + ( hastab==2 ? sc_size.cx : 0) : 0) +
+ (text ? 2 + (text[0] ? size.cx :0): 0) ;
+ else
+ expect = !(text || hbmp) ? 0 :
+ ( hbmp ? (text ? 2:0) + bmpsize.cx : 0 ) +
+ (text ? 2 * MOD_avec + (text[0] ? size.cx :0): 0) ;
+ ok( rc.right - rc.left == expect,
+ "menu width wrong, got %ld expected %d\n", rc.right - rc.left, expect);
+ failed = failed || !(rc.right - rc.left == expect);
+ /* check menu height */
+ if( ispop)
+ expect = max( ( !(text || hbmp) ? GetSystemMetrics( SM_CYMENUSIZE)/2 : 0),
+ max( (text ? max( 2 + size.cy, MOD_hic + 4) : 0),
+ (hbmp ? bmpsize.cy + 2 : 0)));
+ else
+ expect = ( !(text || hbmp) ? GetSystemMetrics( SM_CYMENUSIZE)/2 :
+ max( GetSystemMetrics( SM_CYMENU) - 1, (hbmp ? bmpsize.cy : 0)));
+ ok( rc.bottom - rc.top == expect,
+ "menu height wrong, got %ld expected %d (%d)\n",
+ rc.bottom - rc.top, expect, GetSystemMetrics( SM_CYMENU));
+ failed = failed || !(rc.bottom - rc.top == expect);
+ if( hbmp == HBMMENU_CALLBACK && MOD_GotDrawItemMsg) {
+ /* check the position of the bitmap */
+ /* horizontal */
+ expect = ispop ? (4 + ( mnuopt ? 0 : GetSystemMetrics(SM_CXMENUCHECK)))
+ : 3;
+ ok( expect == MOD_rc[0].left,
+ "bitmap left is %ld expected %d\n", MOD_rc[0].left, expect);
+ failed = failed || !(expect == MOD_rc[0].left);
+ /* vertical */
+ expect = (rc.bottom - rc.top - MOD_rc[0].bottom + MOD_rc[0].top) / 2;
+ ok( expect == MOD_rc[0].top,
+ "bitmap top is %ld expected %d\n", MOD_rc[0].top, expect);
+ failed = failed || !(expect == MOD_rc[0].top);
+ }
+ /* if there was a failure, report details */
+ if( failed) {
+ trace("*** count %d text \"%s\" bitmap %p bmsize %ld,%ld textsize %ld+%ld,%ld mnuopt %d hastab %d\n",
+ count, text ? text: "(nil)", hbmp, bmpsize.cx, bmpsize.cy,
+ size.cx, size.cy, sc_size.cx, mnuopt, hastab);
+ trace(" check %d,%d arrow %d avechar %d\n",
+ GetSystemMetrics(SM_CXMENUCHECK ),
+ GetSystemMetrics(SM_CYMENUCHECK ),arrowwidth, MOD_avec);
+ if( hbmp == HBMMENU_CALLBACK)
+ trace( " rc %ld,%ld-%ld,%ld bmp.rc %ld,%ld-%ld,%ld\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);
+ }
+ /* clean up */
+ ret = DestroyMenu(submenu);
+ ok(ret, "DestroyMenu failed with error %ld\n", GetLastError());
+ ret = DestroyMenu(hmenu);
+ ok(ret, "DestroyMenu failed with error %ld\n", GetLastError());
+}
+
+
+static void test_menu_bmp_and_string(void)
+{
+ BYTE bmfill[300];
+ HBITMAP hbm_arrow;
+ BITMAP bm;
+ INT arrowwidth;
+ HWND hwnd;
+ int count, szidx, txtidx, bmpidx, hassub, mnuopt, ispop;
+
+ if( !pGetMenuInfo) return;
+
+ memset( bmfill, 0x55, sizeof( bmfill));
+ hwnd = CreateWindowEx(0, MAKEINTATOM(atomMenuCheckClass), NULL,
+ WS_VISIBLE, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
+ NULL, NULL, NULL, NULL);
+ hbm_arrow=LoadBitmap( 0, (CHAR*)OBM_MNARROW);
+ GetObject( hbm_arrow, sizeof(bm), &bm);
+ arrowwidth = bm.bmWidth;
+
+ ok(hwnd != NULL, "CreateWindowEx failed with error %ld\n", GetLastError());
+ if( !hwnd) return;
+ SetWindowLongPtr( hwnd, GWLP_WNDPROC, (LONG)menu_ownerdraw_wnd_proc);
+
+ if( winetest_debug)
+ trace(" check %d,%d arrow %d avechar %d\n",
+ GetSystemMetrics(SM_CXMENUCHECK ),
+ GetSystemMetrics(SM_CYMENUCHECK ),arrowwidth, MOD_avec);
+ count = 0;
+ MOD_maxid = 0;
+ for( ispop=1; ispop >= 0; ispop--){
+ static SIZE bmsizes[]= {
+ {10,10},{38,38},{1,30},{55,5}};
+ for( szidx=0; szidx < sizeof( bmsizes) / sizeof( SIZE); szidx++) {
+ HBITMAP hbm = CreateBitmap( bmsizes[szidx].cx, bmsizes[szidx].cy,1,1,bmfill);
+ HBITMAP bitmaps[] = { HBMMENU_CALLBACK, hbm, NULL };
+ ok( (int)hbm, "CreateBitmap failed err %ld\n", GetLastError());
+ for( txtidx = 0; txtidx < sizeof(MOD_txtsizes)/sizeof(MOD_txtsizes[0]); txtidx++) {
+ 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;
+ 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);
+ }
+ }
+ }
+ }
+ DeleteObject( hbm);
+ }
+ }
/* clean up */
DestroyWindow(hwnd);
}
@@ -256,7 +508,7 @@ static void test_menu_add_string( void )
HMENU hmenu;
MENUITEMINFO info;
BOOL rc;
-
+
char string[0x80];
char string2[0x80];
@@ -880,9 +1132,22 @@ static void test_menu_iteminfo( )
{, S, MIIM_TYPE, MFT_STRING, -9, -9, 0, -9, -9, -9, string, 4, 0, },
txt, OK, OK )
TMII_DONE
+ /* MFT_SEPARATOR bit is kept when the text is added */
+ TMII_INSMI( {, S, MIIM_STRING|MIIM_FTYPE, MFT_STRING, -1, -1, -1, -1, -1, -1, NULL, 0, -1, }, OK)
+ TMII_SMII( {, S, MIIM_STRING, -1, -1, -1, -1, -1, -1, -1, txt, -1, -1, }, OK)
+ TMII_GMII ( {, S, MIIM_STRING|MIIM_FTYPE, -9, -9, -9, -9, -9, -9, -9, string, 80, -9, },
+ {, S, MIIM_STRING|MIIM_FTYPE, MFT_SEPARATOR, -9, -9, 0, -9, -9, -9, string, 4, -9, },
+ txt, OK, OK )
+ TMII_DONE
+ /* MFT_SEPARATOR bit is kept when bitmap is added */
+ TMII_INSMI( {, S, MIIM_STRING|MIIM_FTYPE, MFT_STRING, -1, -1, -1, -1, -1, -1, NULL, 0, -1, }, OK)
+ TMII_SMII( {, S, MIIM_BITMAP, -1, -1, -1, -1, -1, -1, -1, -1, -1, hbm, }, OK)
+ TMII_GMII ( {, S, MIIM_BITMAP|MIIM_FTYPE, -9, -9, -9, -9, -9, -9, -9, string, 80, -9, },
+ {, S, MIIM_BITMAP|MIIM_FTYPE, MFT_SEPARATOR, -9, -9, 0, -9, -9, -9, string, 80, hbm, },
+ init, OK, ER )
+ TMII_DONE
- ansi = !ansi;
- } while( !ansi);
+ } while( !(ansi = !ansi) );
DeleteObject( hbm);
}
@@ -1149,6 +1414,11 @@ void test_menu_search_bycommand( void )
START_TEST(menu)
{
+ pSetMenuInfo =
+ (void *)GetProcAddress( GetModuleHandleA("user32.dll"), "SetMenuInfo" );
+ pGetMenuInfo =
+ (void *)GetProcAddress( GetModuleHandleA("user32.dll"), "GetMenuInfo" );
+
register_menu_check_class();
test_menu_locked_by_window();
@@ -1156,4 +1426,5 @@ START_TEST(menu)
test_menu_add_string();
test_menu_iteminfo();
test_menu_search_bycommand();
+ test_menu_bmp_and_string();
}
More information about the wine-patches
mailing list