Implemented MIIM_BITMAP state.
Handle MNS_CHECKORBMP style.
diff --git a/dlls/user/menu.c b/dlls/user/menu.c
index 56564d7..2d6593e 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 @@
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 @@
* 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 @@
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 @@
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 @@
/* 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 @@
* 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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
/* 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 @@
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 @@
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 d3bd83c..331e537 100644
--- a/include/winuser.h
+++ b/include/winuser.h
@@ -1962,6 +1962,13 @@
#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;