Implemented MIIM_BITMAP state.

Handle MNS_CHECKORBMP style.
This commit is contained in:
Maxime Bellengé 2005-03-09 12:39:01 +00:00 committed by Alexandre Julliard
parent b58c170c4d
commit cbd3a53d4b
2 changed files with 119 additions and 20 deletions

View File

@ -4,6 +4,7 @@
* Copyright 1993 Martin Ayotte * Copyright 1993 Martin Ayotte
* Copyright 1994 Alexandre Julliard * Copyright 1994 Alexandre Julliard
* Copyright 1997 Morten Welinder * Copyright 1997 Morten Welinder
* Copyright 2005 Maxime Bellengé
* *
* This library is free software; you can redistribute it and/or * This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public * 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 * Note: the style MF_MOUSESELECT is used to mark popup items that
* have been selected, i.e. their popup menu is currently displayed. * have been selected, i.e. their popup menu is currently displayed.
* This is probably not the meaning this style has in MS-Windows. * 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" #include "config.h"
@ -91,6 +100,7 @@ typedef struct {
DWORD dwContextHelpID; DWORD dwContextHelpID;
DWORD dwMenuData; /* application defined value */ DWORD dwMenuData; /* application defined value */
HMENU hSysMenuOwner; /* Handle to the dummy sys menu holder */ HMENU hSysMenuOwner; /* Handle to the dummy sys menu holder */
SIZE maxBmpSize; /* Maximum size of the bitmap items in MIIM_BITMAP state */
} POPUPMENU, *LPPOPUPMENU; } POPUPMENU, *LPPOPUPMENU;
/* internal flags for menu tracking */ /* internal flags for menu tracking */
@ -751,8 +761,9 @@ static void MENU_GetBitmapItemSize( UINT id, DWORD data, SIZE *size )
* MENU_DrawBitmapItem * MENU_DrawBitmapItem
* *
* Draw a bitmap item. * 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; BITMAP bm;
DWORD rop; 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 h = rect->bottom - rect->top;
int bmp_xoffset = 0; int bmp_xoffset = 0;
int left, top; int left, top;
HBITMAP hbmToDraw = (drawhbmbitmap)?lpitem->hbmpItem:(HBITMAP)lpitem->text;
/* Check if there is a magic menu item associated with this item */ /* 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; UINT flags = 0;
RECT r; RECT r;
switch(LOWORD(lpitem->text)) switch(LOWORD(hbmToDraw))
{ {
case (INT_PTR)HBMMENU_SYSTEM: case (INT_PTR)HBMMENU_SYSTEM:
if (lpitem->dwItemData) 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_MAXIMIZE:
case (INT_PTR)HBMMENU_POPUP_MINIMIZE: case (INT_PTR)HBMMENU_POPUP_MINIMIZE:
default: default:
FIXME("Magic 0x%08x not implemented\n", LOWORD(lpitem->text)); FIXME("Magic 0x%08x not implemented\n", LOWORD(hbmToDraw));
return; return;
} }
r = *rect; r = *rect;
@ -826,7 +838,7 @@ static void MENU_DrawBitmapItem( HDC hdc, MENUITEM *lpitem, const RECT *rect, BO
/* handle fontsize > bitmap_height */ /* handle fontsize > bitmap_height */
top = (h>bm.bmHeight) ? rect->top+(h-bm.bmHeight)/2 : rect->top; top = (h>bm.bmHeight) ? rect->top+(h-bm.bmHeight)/2 : rect->top;
left=rect->left; 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)) if ((lpitem->fState & MF_HILITE) && IS_BITMAP_ITEM(lpitem->fType))
SetBkColor(hdc, GetSysColor(COLOR_HIGHLIGHT)); SetBkColor(hdc, GetSysColor(COLOR_HIGHLIGHT));
BitBlt( hdc, left, top, w, h, hdcMem, bmp_xoffset, 0, rop ); 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. * Calculate the size of the menu item and store it in lpitem->rect.
*/ */
static void MENU_CalcItemSize( HDC hdc, MENUITEM *lpitem, HWND hwndOwner, 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; WCHAR *p;
UINT check_bitmap_width = GetSystemMetrics( SM_CXMENUCHECK ); UINT check_bitmap_width = GetSystemMetrics( SM_CXMENUCHECK );
@ -895,6 +907,38 @@ static void MENU_CalcItemSize( HDC hdc, MENUITEM *lpitem, HWND hwndOwner,
if (!menuBar) if (!menuBar)
{ {
/* 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; lpitem->rect.right += 2 * check_bitmap_width;
if (lpitem->fType & MF_POPUP) if (lpitem->fType & MF_POPUP)
lpitem->rect.right += arrow_bitmap_width; 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); GetTextExtentPoint32W(hdc, lpitem->text, strlenW(lpitem->text), &size);
lpitem->rect.right += size.cx; 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; lpitem->xTab = 0;
if (menuBar) if (menuBar)
@ -970,6 +1014,9 @@ static void MENU_PopupMenuCalcSize( LPPOPUPMENU lppop, HWND hwndOwner )
start = 0; start = 0;
maxX = 2 + 1; maxX = 2 + 1;
lppop->maxBmpSize.cx = 0;
lppop->maxBmpSize.cy = 0;
while (start < lppop->nItems) while (start < lppop->nItems)
{ {
lpitem = &lppop->items[start]; lpitem = &lppop->items[start];
@ -977,14 +1024,13 @@ static void MENU_PopupMenuCalcSize( LPPOPUPMENU lppop, HWND hwndOwner )
orgY = 3; orgY = 3;
maxTab = maxTabWidth = 0; maxTab = maxTabWidth = 0;
/* Parse items until column break or end of menu */ /* Parse items until column break or end of menu */
for (i = start; i < lppop->nItems; i++, lpitem++) for (i = start; i < lppop->nItems; i++, lpitem++)
{ {
if ((i != start) && if ((i != start) &&
(lpitem->fType & (MF_MENUBREAK | MF_MENUBARBREAK))) break; (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++; if (lpitem->fType & MF_MENUBARBREAK) orgX++;
maxX = max( maxX, lpitem->rect.right ); maxX = max( maxX, lpitem->rect.right );
@ -1042,6 +1088,8 @@ static void MENU_MenuBarCalcSize( HDC hdc, LPRECT lprect,
maxY = lprect->top+1; maxY = lprect->top+1;
start = 0; start = 0;
helpPos = -1; helpPos = -1;
lppop->maxBmpSize.cx = 0;
lppop->maxBmpSize.cy = 0;
while (start < lppop->nItems) while (start < lppop->nItems)
{ {
lpitem = &lppop->items[start]; lpitem = &lppop->items[start];
@ -1058,7 +1106,7 @@ static void MENU_MenuBarCalcSize( HDC hdc, LPRECT lprect,
TRACE("calling MENU_CalcItemSize org=(%d, %d)\n", TRACE("calling MENU_CalcItemSize org=(%d, %d)\n",
orgX, orgY ); orgX, orgY );
debug_print_menuitem (" item: ", lpitem, ""); 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) if (lpitem->rect.right > lprect->right)
{ {
@ -1223,18 +1271,53 @@ static void MENU_DrawMenuItem( HWND hwnd, HMENU hmenu, HWND hwndOwner, HDC hdc,
if (!menuBar) if (!menuBar)
{ {
HBITMAP bm;
INT y = rect.top + rect.bottom; INT y = rect.top + rect.bottom;
UINT check_bitmap_width = GetSystemMetrics( SM_CXMENUCHECK ); UINT check_bitmap_width = GetSystemMetrics( SM_CXMENUCHECK );
UINT check_bitmap_height = GetSystemMetrics( SM_CYMENUCHECK ); UINT check_bitmap_height = GetSystemMetrics( SM_CYMENUCHECK );
if (!(lpitem->fType & MF_OWNERDRAW)) if (!(lpitem->fType & MF_OWNERDRAW))
{ {
/* 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 /* Draw the check mark
* *
* FIXME: * FIXME:
* Custom checkmark bitmaps are monochrome but not always 1bpp. * Custom checkmark bitmaps are monochrome but not always 1bpp.
*/ */
HBITMAP bm = (lpitem->fState & MF_CHECKED) ? lpitem->hCheckBit : lpitem->hUnCheckBit; bm = (lpitem->fState & MF_CHECKED) ? lpitem->hCheckBit : lpitem->hUnCheckBit;
if (bm) /* we have a custom bitmap */ if (bm) /* we have a custom bitmap */
{ {
HDC hdcMem = CreateCompatibleDC( hdc ); 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 */ /* Draw the item text or bitmap */
if (IS_BITMAP_ITEM(lpitem->fType)) if (IS_BITMAP_ITEM(lpitem->fType))
{ {
MENU_DrawBitmapItem( hdc, lpitem, &rect, menuBar ); MENU_DrawBitmapItem( hdc, lpitem, &rect, menuBar, FALSE);
return; return;
} }
/* No bitmap - process text if present */ /* No bitmap - process text if present */
else if (IS_STRING_ITEM(lpitem->fType)) else if (IS_STRING_ITEM(lpitem->fType))
@ -4178,6 +4260,9 @@ static BOOL SetMenuItemInfo_common(MENUITEM * menu,
if (lpmii->fMask & MIIM_DATA) if (lpmii->fMask & MIIM_DATA)
menu->dwItemData = lpmii->dwItemData; menu->dwItemData = lpmii->dwItemData;
if (lpmii->fMask & MIIM_BITMAP)
menu->hbmpItem = lpmii->hbmpItem;
debug_print_menuitem("SetMenuItemInfo_common to : ", menu, ""); debug_print_menuitem("SetMenuItemInfo_common to : ", menu, "");
return TRUE; return TRUE;
} }
@ -4424,7 +4509,14 @@ BOOL WINAPI SetMenuInfo (HMENU hMenu, LPCMENUINFO lpmi)
menu->dwMenuData = lpmi->dwMenuData; menu->dwMenuData = lpmi->dwMenuData;
if (lpmi->fMask & MIM_STYLE) if (lpmi->fMask & MIM_STYLE)
{
menu->dwStyle = lpmi->dwStyle; 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; return TRUE;
} }

View File

@ -1962,6 +1962,13 @@ typedef const MENUINFO *LPCMENUINFO;
#define MIM_STYLE 0x00000010 #define MIM_STYLE 0x00000010
#define MIM_APPLYTOSUBMENUS 0x80000000 #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 { typedef struct {
WORD versionNumber; WORD versionNumber;
WORD offset; WORD offset;