Implemented MIIM_BITMAP state.
Handle MNS_CHECKORBMP style.
This commit is contained in:
parent
b58c170c4d
commit
cbd3a53d4b
132
dlls/user/menu.c
132
dlls/user/menu.c
|
@ -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,7 +907,39 @@ static void MENU_CalcItemSize( HDC hdc, MENUITEM *lpitem, HWND hwndOwner,
|
||||||
|
|
||||||
if (!menuBar)
|
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)
|
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)
|
||||||
{
|
{
|
||||||
INT y = rect.top + rect.bottom;
|
HBITMAP bm;
|
||||||
|
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))
|
||||||
{
|
{
|
||||||
/* Draw the check mark
|
/* New style MIIM_BITMAP */
|
||||||
*
|
if (lpitem->hbmpItem)
|
||||||
* FIXME:
|
{
|
||||||
* Custom checkmark bitmaps are monochrome but not always 1bpp.
|
POPUPMENU *menu = MENU_GetMenu(hmenu);
|
||||||
*/
|
HBITMAP hbm = lpitem->hbmpItem;
|
||||||
HBITMAP bm = (lpitem->fState & MF_CHECKED) ? lpitem->hCheckBit : lpitem->hUnCheckBit;
|
|
||||||
|
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 */
|
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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
Loading…
Reference in New Issue