From cbd3a53d4bf9cfa94ddddfe3b77533c9c587069e Mon Sep 17 00:00:00 2001 From: =?utf8?q?Maxime=20Belleng=C3=A9?= Date: Wed, 9 Mar 2005 12:39:01 +0000 Subject: [PATCH] Implemented MIIM_BITMAP state. Handle MNS_CHECKORBMP style. --- dlls/user/menu.c | 132 +++++++++++++++++++++++++++++++++++++++++++++--------- include/winuser.h | 7 +++ 2 files changed, 119 insertions(+), 20 deletions(-) diff --git a/dlls/user/menu.c b/dlls/user/menu.c index 56564d795ce..2d6593eada6 100644 --- a/dlls/user/menu.c +++ b/dlls/user/menu.c @@ -4,6 +4,7 @@ * Copyright 1993 Martin Ayotte * Copyright 1994 Alexandre Julliard * Copyright 1997 Morten Welinder + * Copyright 2005 Maxime Bellengé * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -24,6 +25,14 @@ * Note: the style MF_MOUSESELECT is used to mark popup items that * have been selected, i.e. their popup menu is currently displayed. * This is probably not the meaning this style has in MS-Windows. + * + * TODO: + * implements styles : + * - MNS_AUTODISMISS + * - MNS_DRAGDROP + * - MNS_MODELESS + * - MNS_NOCHECK + * - MNS_NOTIFYBYPOS */ #include "config.h" @@ -91,6 +100,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 */ } POPUPMENU, *LPPOPUPMENU; /* internal flags for menu tracking */ @@ -751,8 +761,9 @@ static void MENU_GetBitmapItemSize( UINT id, DWORD data, SIZE *size ) * MENU_DrawBitmapItem * * Draw a bitmap item. + * drawhbmbitmap : True to draw the hbmbitmap(MIIM_BITMAP)/False to draw the MF_BITMAP */ -static void MENU_DrawBitmapItem( HDC hdc, MENUITEM *lpitem, const RECT *rect, BOOL menuBar ) +static void MENU_DrawBitmapItem( HDC hdc, MENUITEM *lpitem, const RECT *rect, BOOL menuBar, BOOL drawhbmbitmap ) { BITMAP bm; DWORD rop; @@ -762,14 +773,15 @@ static void MENU_DrawBitmapItem( HDC hdc, MENUITEM *lpitem, const RECT *rect, BO int h = rect->bottom - rect->top; int bmp_xoffset = 0; int left, top; + HBITMAP hbmToDraw = (drawhbmbitmap)?lpitem->hbmpItem:(HBITMAP)lpitem->text; /* Check if there is a magic menu item associated with this item */ - if (lpitem->text && IS_MAGIC_ITEM(lpitem->text)) + if (hbmToDraw && IS_MAGIC_ITEM(hbmToDraw)) { UINT flags = 0; RECT r; - switch(LOWORD(lpitem->text)) + switch(LOWORD(hbmToDraw)) { case (INT_PTR)HBMMENU_SYSTEM: if (lpitem->dwItemData) @@ -807,7 +819,7 @@ static void MENU_DrawBitmapItem( HDC hdc, MENUITEM *lpitem, const RECT *rect, BO case (INT_PTR)HBMMENU_POPUP_MAXIMIZE: case (INT_PTR)HBMMENU_POPUP_MINIMIZE: default: - FIXME("Magic 0x%08x not implemented\n", LOWORD(lpitem->text)); + FIXME("Magic 0x%08x not implemented\n", LOWORD(hbmToDraw)); return; } r = *rect; @@ -826,7 +838,7 @@ static void MENU_DrawBitmapItem( HDC hdc, MENUITEM *lpitem, const RECT *rect, BO /* handle fontsize > bitmap_height */ top = (h>bm.bmHeight) ? rect->top+(h-bm.bmHeight)/2 : rect->top; left=rect->left; - rop=((lpitem->fState & MF_HILITE) && !IS_MAGIC_ITEM(lpitem->text)) ? NOTSRCCOPY : SRCCOPY; + rop=((lpitem->fState & MF_HILITE) && !IS_MAGIC_ITEM(hbmToDraw)) ? NOTSRCCOPY : SRCCOPY; if ((lpitem->fState & MF_HILITE) && IS_BITMAP_ITEM(lpitem->fType)) SetBkColor(hdc, GetSysColor(COLOR_HIGHLIGHT)); BitBlt( hdc, left, top, w, h, hdcMem, bmp_xoffset, 0, rop ); @@ -840,7 +852,7 @@ static void MENU_DrawBitmapItem( HDC hdc, MENUITEM *lpitem, const RECT *rect, BO * Calculate the size of the menu item and store it in lpitem->rect. */ static void MENU_CalcItemSize( HDC hdc, MENUITEM *lpitem, HWND hwndOwner, - INT orgX, INT orgY, BOOL menuBar ) + INT orgX, INT orgY, BOOL menuBar, POPUPMENU* lppop ) { WCHAR *p; UINT check_bitmap_width = GetSystemMetrics( SM_CXMENUCHECK ); @@ -895,7 +907,39 @@ static void MENU_CalcItemSize( HDC hdc, MENUITEM *lpitem, HWND hwndOwner, if (!menuBar) { - lpitem->rect.right += 2 * check_bitmap_width; + /* New style MIIM_BITMAP */ + 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((UINT)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; } @@ -923,7 +967,7 @@ static void MENU_CalcItemSize( HDC hdc, MENUITEM *lpitem, HWND hwndOwner, GetTextExtentPoint32W(hdc, lpitem->text, strlenW(lpitem->text), &size); lpitem->rect.right += size.cx; - lpitem->rect.bottom += max(size.cy, GetSystemMetrics(SM_CYMENU)-1); + lpitem->rect.bottom += max(max(size.cy, GetSystemMetrics(SM_CYMENU)-1), lppop->maxBmpSize.cy); lpitem->xTab = 0; if (menuBar) @@ -970,6 +1014,9 @@ static void MENU_PopupMenuCalcSize( LPPOPUPMENU lppop, HWND hwndOwner ) start = 0; maxX = 2 + 1; + lppop->maxBmpSize.cx = 0; + lppop->maxBmpSize.cy = 0; + while (start < lppop->nItems) { lpitem = &lppop->items[start]; @@ -977,14 +1024,13 @@ static void MENU_PopupMenuCalcSize( LPPOPUPMENU lppop, HWND hwndOwner ) orgY = 3; maxTab = maxTabWidth = 0; - /* Parse items until column break or end of menu */ for (i = start; i < lppop->nItems; i++, lpitem++) { if ((i != start) && (lpitem->fType & (MF_MENUBREAK | MF_MENUBARBREAK))) break; - MENU_CalcItemSize( hdc, lpitem, hwndOwner, orgX, orgY, FALSE ); + MENU_CalcItemSize( hdc, lpitem, hwndOwner, orgX, orgY, FALSE, lppop ); if (lpitem->fType & MF_MENUBARBREAK) orgX++; maxX = max( maxX, lpitem->rect.right ); @@ -1042,6 +1088,8 @@ static void MENU_MenuBarCalcSize( HDC hdc, LPRECT lprect, maxY = lprect->top+1; start = 0; helpPos = -1; + lppop->maxBmpSize.cx = 0; + lppop->maxBmpSize.cy = 0; while (start < lppop->nItems) { lpitem = &lppop->items[start]; @@ -1058,7 +1106,7 @@ static void MENU_MenuBarCalcSize( HDC hdc, LPRECT lprect, TRACE("calling MENU_CalcItemSize org=(%d, %d)\n", orgX, orgY ); debug_print_menuitem (" item: ", lpitem, ""); - MENU_CalcItemSize( hdc, lpitem, hwndOwner, orgX, orgY, TRUE ); + MENU_CalcItemSize( hdc, lpitem, hwndOwner, orgX, orgY, TRUE, lppop ); if (lpitem->rect.right > lprect->right) { @@ -1223,18 +1271,53 @@ static void MENU_DrawMenuItem( HWND hwnd, HMENU hmenu, HWND hwndOwner, HDC hdc, if (!menuBar) { - INT y = rect.top + rect.bottom; + HBITMAP bm; + INT y = rect.top + rect.bottom; UINT check_bitmap_width = GetSystemMetrics( SM_CXMENUCHECK ); UINT check_bitmap_height = GetSystemMetrics( SM_CYMENUCHECK ); if (!(lpitem->fType & MF_OWNERDRAW)) { - /* Draw the check mark - * - * FIXME: - * Custom checkmark bitmaps are monochrome but not always 1bpp. - */ - HBITMAP bm = (lpitem->fState & MF_CHECKED) ? lpitem->hCheckBit : lpitem->hUnCheckBit; + /* New style MIIM_BITMAP */ + if (lpitem->hbmpItem) + { + POPUPMENU *menu = MENU_GetMenu(hmenu); + HBITMAP hbm = lpitem->hbmpItem; + + if (hbm == 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.rcItem = lpitem->rect; + drawItem.itemData = lpitem->dwItemData; + + if (!(lpitem->fState & MF_CHECKED)) + SendMessageW( hwndOwner, WM_DRAWITEM, 0, (LPARAM)&drawItem); + + } else { + MENU_DrawBitmapItem(hdc, lpitem, &rect, FALSE, TRUE); + } + if (menu->dwStyle & MNS_CHECKORBMP) + rect.left += menu->maxBmpSize.cx - check_bitmap_width; + else + rect.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 */ { HDC hdcMem = CreateCompatibleDC( hdc ); @@ -1287,9 +1370,8 @@ static void MENU_DrawMenuItem( HWND hwnd, HMENU hmenu, HWND hwndOwner, HDC hdc, /* Draw the item text or bitmap */ if (IS_BITMAP_ITEM(lpitem->fType)) { - MENU_DrawBitmapItem( hdc, lpitem, &rect, menuBar ); + MENU_DrawBitmapItem( hdc, lpitem, &rect, menuBar, FALSE); return; - } /* No bitmap - process text if present */ else if (IS_STRING_ITEM(lpitem->fType)) @@ -4178,6 +4260,9 @@ static BOOL SetMenuItemInfo_common(MENUITEM * menu, if (lpmii->fMask & MIIM_DATA) menu->dwItemData = lpmii->dwItemData; + if (lpmii->fMask & MIIM_BITMAP) + menu->hbmpItem = lpmii->hbmpItem; + debug_print_menuitem("SetMenuItemInfo_common to : ", menu, ""); return TRUE; } @@ -4424,7 +4509,14 @@ BOOL WINAPI SetMenuInfo (HMENU hMenu, LPCMENUINFO lpmi) menu->dwMenuData = lpmi->dwMenuData; 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"); + if (menu->dwStyle & MNS_NOCHECK) FIXME("MNS_NOCHECK unimplemented\n"); + if (menu->dwStyle & MNS_NOTIFYBYPOS) FIXME("MNS_NOTIFYBYPOS unimplemented\n"); + } return TRUE; } diff --git a/include/winuser.h b/include/winuser.h index d3bd83c7f19..331e5379828 100644 --- a/include/winuser.h +++ b/include/winuser.h @@ -1962,6 +1962,13 @@ typedef const MENUINFO *LPCMENUINFO; #define MIM_STYLE 0x00000010 #define MIM_APPLYTOSUBMENUS 0x80000000 +#define MNS_NOCHECK 0x80000000 +#define MNS_MODELESS 0x40000000 +#define MNS_DRAGDROP 0x20000000 +#define MNS_AUTODISMISS 0x10000000 +#define MNS_NOTIFYBYPOS 0x08000000 +#define MNS_CHECKORBMP 0x04000000 + typedef struct { WORD versionNumber; WORD offset; -- 2.11.4.GIT