user: Accept more flags in SetMenuItemInfo and ModifyMenu
Michael Kaufmann
hallo at michael-kaufmann.ch
Tue Aug 8 16:22:50 CDT 2006
This makes the MDI buttons appear in Word 95.
An older version of this patch is at http://www.winehq.org/pipermail/wine-patches/2006-April/025919.html
Changelog:
- Accept MFT_MENU{BAR}BREAK, MFT_RADIOCHECK, MFT_RIGHTJUSTIFY, and
MFT_RIGHTORDER in SetMenuItemInfo
- InsertMenu, AppendMenu, ModifiyMenu: Accept MF_HILITE flag
(undocumented)
- SetMenuItemInfo: Only use the lower word of the bitmap handle as
documented in MSDN (Word 95 depends on this)
- The type MFT_RADIOCHECK cannot be set if only the checkmarks are
modified with SetMenuItemInfo
- New tests
-------------- next part --------------
Index: dlls/user/menu.c
===================================================================
RCS file: /home/wine/wine/dlls/user/menu.c,v
retrieving revision 1.65
diff -u -r1.65 menu.c
--- dlls/user/menu.c 12 Jun 2006 12:12:23 -0000 1.65
+++ dlls/user/menu.c 8 Aug 2006 21:02:40 -0000
@@ -159,11 +159,13 @@
#define IS_SYSTEM_MENU(menu) \
(!((menu)->wFlags & MF_POPUP) && ((menu)->wFlags & MF_SYSMENU))
-#define TYPE_MASK (MFT_STRING | MFT_BITMAP | MFT_OWNERDRAW | MFT_SEPARATOR | \
- MFT_MENUBARBREAK | MFT_MENUBREAK | MFT_RADIOCHECK | \
- MFT_RIGHTORDER | MFT_RIGHTJUSTIFY | \
- MF_POPUP | MF_SYSMENU | MF_HELP)
+#define MENUITEMINFO_TYPE_MASK \
+ (MFT_STRING | MFT_BITMAP | MFT_OWNERDRAW | MFT_SEPARATOR | \
+ MFT_MENUBARBREAK | MFT_MENUBREAK | MFT_RADIOCHECK | \
+ MFT_RIGHTORDER | MFT_RIGHTJUSTIFY /* same as MF_HELP */ )
+#define TYPE_MASK (MENUITEMINFO_TYPE_MASK | MF_POPUP | MF_SYSMENU)
#define STATE_MASK (~TYPE_MASK)
+#define MENUITEMINFO_STATE_MASK (STATE_MASK & ~(MF_BYPOSITION | MF_MOUSESELECT))
#define WIN_ALLOWED_MENU(style) ((style & (WS_CHILD | WS_POPUP)) != WS_CHILD)
@@ -2050,8 +2052,9 @@
flags |= MF_POPUP; /* keep popup */
item->fType = flags & TYPE_MASK;
- item->fState = (flags & STATE_MASK) &
- ~(MF_HILITE | MF_MOUSESELECT | MF_BYPOSITION);
+ /* MFS_DEFAULT is not accepted. MF_HILITE is not listed as a valid flag
+ for ModifyMenu, but Windows accepts it */
+ item->fState = flags & MENUITEMINFO_STATE_MASK & ~MFS_DEFAULT;
/* Don't call SetRectEmpty here! */
@@ -2123,10 +2126,14 @@
{
WORD flags, id = 0;
LPCSTR str;
+ BOOL end_flag;
do
{
flags = GET_WORD(res);
+ end_flag = flags & MF_END;
+ /* Remove MF_END because it has the same value as MF_HILITE */
+ flags &= ~MF_END;
res += sizeof(WORD);
if (!(flags & MF_POPUP))
{
@@ -2151,7 +2158,7 @@
else AppendMenuW( hMenu, flags, id,
*(LPCWSTR)str ? (LPCWSTR)str : NULL );
}
- } while (!(flags & MF_END));
+ } while (!end_flag);
return res;
}
@@ -4352,7 +4359,7 @@
static BOOL GetMenuItemInfo_common ( HMENU hmenu, UINT item, BOOL bypos,
LPMENUITEMINFOW lpmii, BOOL unicode)
{
- MENUITEM *menu = MENU_FindItem (&hmenu, &item, bypos? MF_BYPOSITION : 0);
+ MENUITEM *menu = MENU_FindItem (&hmenu, &item, bypos ? MF_BYPOSITION : 0);
debug_print_menuitem("GetMenuItemInfo_common: ", menu, "");
@@ -4366,7 +4373,7 @@
SetLastError( ERROR_INVALID_PARAMETER);
return FALSE;
}
- lpmii->fType = menu->fType & ~MF_POPUP;
+ lpmii->fType = menu->fType & MENUITEMINFO_TYPE_MASK;
if( menu->hbmpItem) lpmii->fType |= MFT_BITMAP;
lpmii->hbmpItem = menu->hbmpItem; /* not on Win9x/ME */
if( lpmii->fType & MFT_BITMAP) {
@@ -4421,13 +4428,13 @@
}
if (lpmii->fMask & MIIM_FTYPE)
- lpmii->fType = menu->fType & ~MF_POPUP;
+ lpmii->fType = menu->fType & MENUITEMINFO_TYPE_MASK;
if (lpmii->fMask & MIIM_BITMAP)
lpmii->hbmpItem = menu->hbmpItem;
if (lpmii->fMask & MIIM_STATE)
- lpmii->fState = menu->fState;
+ lpmii->fState = menu->fState & MENUITEMINFO_STATE_MASK;
if (lpmii->fMask & MIIM_ID)
lpmii->wID = menu->wID;
@@ -4524,7 +4531,7 @@
{
if (!menu) return FALSE;
- debug_print_menuitem("SetmenuItemInfo_common from: ", menu, "");
+ debug_print_menuitem("SetMenuItemInfo_common from: ", menu, "");
if (lpmii->fMask & MIIM_TYPE ) {
if( lpmii->fMask & ( MIIM_STRING | MIIM_FTYPE | MIIM_BITMAP)) {
@@ -4533,15 +4540,16 @@
SetLastError( ERROR_INVALID_PARAMETER);
return FALSE;
}
- /* make only MENU_ITEM_TYPE bits in menu->fType equal lpmii->fType */
- menu->fType &= ~MENU_ITEM_TYPE(menu->fType);
- menu->fType |= MENU_ITEM_TYPE(lpmii->fType);
+
+ /* Remove the old type bits and replace them with the new ones */
+ menu->fType &= ~MENUITEMINFO_TYPE_MASK;
+ menu->fType |= lpmii->fType & MENUITEMINFO_TYPE_MASK;
if (IS_STRING_ITEM(menu->fType)) {
HeapFree(GetProcessHeap(), 0, menu->text);
set_menu_item_text( menu, lpmii->dwTypeData, unicode );
} else if( (menu->fType) & MFT_BITMAP)
- menu->hbmpItem = (HBITMAP)lpmii->dwTypeData;
+ menu->hbmpItem = HBITMAP_32(LOWORD(lpmii->dwTypeData));
}
if (lpmii->fMask & MIIM_FTYPE ) {
@@ -4549,8 +4557,8 @@
SetLastError( ERROR_INVALID_PARAMETER);
return FALSE;
}
- menu->fType &= ~MENU_ITEM_TYPE(menu->fType);
- menu->fType |= MENU_ITEM_TYPE(lpmii->fType);
+ menu->fType &= ~MENUITEMINFO_TYPE_MASK;
+ menu->fType |= lpmii->fType & MENUITEMINFO_TYPE_MASK;
}
if (lpmii->fMask & MIIM_STRING ) {
/* free the string when used */
@@ -4560,8 +4568,9 @@
if (lpmii->fMask & MIIM_STATE)
{
- /* FIXME: MFS_DEFAULT do we have to reset the other menu items? */
- menu->fState = lpmii->fState;
+ /* Other menu items having MFS_DEFAULT are not converted
+ to normal items */
+ menu->fState = lpmii->fState & MENUITEMINFO_STATE_MASK;
}
if (lpmii->fMask & MIIM_ID)
@@ -4586,9 +4595,6 @@
if (lpmii->fMask & MIIM_CHECKMARKS)
{
- if (lpmii->fType & MFT_RADIOCHECK)
- menu->fType |= MFT_RADIOCHECK;
-
menu->hCheckBit = lpmii->hbmpChecked;
menu->hUnCheckBit = lpmii->hbmpUnchecked;
}
Index: dlls/user/tests/menu.c
===================================================================
RCS file: /home/wine/wine/dlls/user/tests/menu.c,v
retrieving revision 1.26
diff -u -r1.26 menu.c
--- dlls/user/tests/menu.c 27 Jul 2006 10:43:29 -0000 1.26
+++ dlls/user/tests/menu.c 8 Aug 2006 21:02:52 -0000
@@ -974,7 +974,7 @@
{, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
init, OK, ER )
TMII_DONE
-
+ /* Separator */
TMII_INSMI( {, S, MIIM_TYPE, MFT_SEPARATOR, 0, 0, 0, 0, 0, 0, txt, 0, 0, }, OK)
TMII_GMII ( {, S, MIIM_TYPE, -9, -9, -9, -9, -9, -9, -9, string, 80, -9, },
{, S, MIIM_TYPE, MFT_SEPARATOR, -9, -9, 0, -9, -9, -9, 0, 0, 0, },
@@ -1165,7 +1165,96 @@
{, S, MIIM_BITMAP|MIIM_FTYPE, MFT_SEPARATOR, -9, -9, 0, -9, -9, -9, string, 80, hbm, },
init, OK, ER )
TMII_DONE
-
+ /* Bitmaps inserted with MIIM_TYPE and MFT_BITMAP:
+ Only the low word of the dwTypeData is used.
+ Use a magic bitmap here (Word 95 uses this to create its MDI menu buttons) */
+ TMII_INSMI( {, S, MIIM_TYPE, MFT_BITMAP | MFT_RIGHTJUSTIFY, -1, -1, -1, -1, -1, -1, MAKELONG(HBMMENU_MBAR_CLOSE, 0x1234), -1, -1, }, OK)
+ TMII_GMII ( {, S, MIIM_TYPE, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, },
+ {, S, MIIM_TYPE, MFT_BITMAP | MFT_RIGHTJUSTIFY, -9, -9, 0, -9, -9, -9, HBMMENU_MBAR_CLOSE, 0, HBMMENU_MBAR_CLOSE, },
+ empty, OK, OK )
+ TMII_DONE
+ /* Type flags */
+ TMII_INSMI( {, S, MIIM_TYPE, MFT_BITMAP | MFT_MENUBARBREAK | MFT_RADIOCHECK | MFT_RIGHTJUSTIFY | MFT_RIGHTORDER, -1, -1, -1, -1, -1, -1, hbm, -1, -1, }, OK)
+ TMII_GMII ( {, S, MIIM_TYPE, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, },
+ {, S, MIIM_TYPE, MFT_BITMAP | MFT_MENUBARBREAK | MFT_RADIOCHECK | MFT_RIGHTJUSTIFY | MFT_RIGHTORDER, -9, -9, 0, -9, -9, -9, hbm, 0, hbm, },
+ empty, OK, OK )
+ TMII_DONE
+ /* State flags */
+ TMII_INSMI( {, S, MIIM_TYPE, MFT_BITMAP, -1, -1, -1, -1, -1, -1, hbm, -1, -1, }, OK)
+ TMII_SMII( {, S, MIIM_STATE, -1, MFS_CHECKED | MFS_DEFAULT | MFS_GRAYED | MFS_HILITE, -1, -1, -1, -1, -1, -1, -1, -1, }, OK)
+ TMII_GMII ( {, S, MIIM_STATE, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, },
+ {, S, MIIM_STATE, -9, MFS_CHECKED | MFS_DEFAULT | MFS_GRAYED | MFS_HILITE, -9, 0, -9, -9, -9, -9, -9, -9, },
+ empty, OK, OK )
+ TMII_DONE
+ /* The style MFT_RADIOCHECK cannot be set with MIIM_CHECKMARKS only */
+ TMII_INSMI( {, S, MIIM_TYPE, MFT_BITMAP, -1, -1, -1, -1, -1, -1, hbm, -1, -1, }, OK)
+ TMII_SMII( {, S, MIIM_CHECKMARKS, MFT_RADIOCHECK, -1, -1, -1, hbm, hbm, -1, -1, -1, -1, }, OK)
+ TMII_GMII ( {, S, MIIM_CHECKMARKS | MIIM_TYPE, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, },
+ {, S, MIIM_CHECKMARKS | MIIM_TYPE, MFT_BITMAP, -9, -9, 0, hbm, hbm, -9, hbm, 0, hbm, },
+ empty, OK, OK )
+ TMII_DONE
+ /* MFT_BITMAP is added automatically by GetMenuItemInfo() for MIIM_TYPE */
+ TMII_INSMI( {, S, MIIM_TYPE, MFT_BITMAP, -1, -1, -1, -1, -1, -1, hbm, -1, -1, }, OK)
+ TMII_SMII( {, S, MIIM_FTYPE, MFT_OWNERDRAW, -1, -1, -1, -1, -1, -1, 0x1234, -1, -1, }, OK)
+ TMII_GMII ( {, S, MIIM_FTYPE, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, },
+ {, S, MIIM_FTYPE, MFT_OWNERDRAW, -9, -9, 0, -9, -9, -9, -9, -9, -9, },
+ empty, OK, OK )
+ TMII_GMII ( {, S, MIIM_TYPE, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, },
+ {, S, MIIM_TYPE, MFT_BITMAP | MFT_OWNERDRAW, -9, -9, 0, -9, -9, -9, hbm, 0, hbm, },
+ empty, OK, OK )
+ TMII_GMII ( {, S, MIIM_FTYPE, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, },
+ {, S, MIIM_FTYPE, MFT_OWNERDRAW, -9, -9, 0, -9, -9, -9, -9, -9, -9, },
+ empty, OK, OK )
+ TMII_SMII( {, S, MIIM_BITMAP, -1, -1, -1, -1, -1, -1, -1, -1, -1, NULL, }, OK)
+ TMII_GMII ( {, S, MIIM_TYPE, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, },
+ {, S, MIIM_TYPE, MFT_OWNERDRAW, -9, -9, 0, -9, -9, -9, NULL, 0, NULL, },
+ empty, OK, OK )
+ TMII_DONE
+ /* Bitmaps inserted with MIIM_TYPE and MFT_BITMAP:
+ Only the low word of the dwTypeData is used.
+ Use a magic bitmap here (Word 95 uses this to create its MDI menu buttons) */
+ TMII_INSMI( {, S, MIIM_TYPE, MFT_BITMAP | MFT_RIGHTJUSTIFY, -1, -1, -1, -1, -1, -1, MAKELONG(HBMMENU_MBAR_CLOSE, 0x1234), -1, -1, }, OK)
+ TMII_GMII ( {, S, MIIM_TYPE, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, },
+ {, S, MIIM_TYPE, MFT_BITMAP | MFT_RIGHTJUSTIFY, -9, -9, 0, -9, -9, -9, HBMMENU_MBAR_CLOSE, 0, HBMMENU_MBAR_CLOSE, },
+ empty, OK, OK )
+ TMII_DONE
+ /* Type flags */
+ TMII_INSMI( {, S, MIIM_TYPE, MFT_BITMAP | MFT_MENUBARBREAK | MFT_RADIOCHECK | MFT_RIGHTJUSTIFY | MFT_RIGHTORDER, -1, -1, -1, -1, -1, -1, hbm, -1, -1, }, OK)
+ TMII_GMII ( {, S, MIIM_TYPE, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, },
+ {, S, MIIM_TYPE, MFT_BITMAP | MFT_MENUBARBREAK | MFT_RADIOCHECK | MFT_RIGHTJUSTIFY | MFT_RIGHTORDER, -9, -9, 0, -9, -9, -9, hbm, 0, hbm, },
+ empty, OK, OK )
+ TMII_DONE
+ /* State flags */
+ TMII_INSMI( {, S, MIIM_TYPE, MFT_BITMAP, -1, -1, -1, -1, -1, -1, hbm, -1, -1, }, OK)
+ TMII_SMII( {, S, MIIM_STATE, -1, MFS_CHECKED | MFS_DEFAULT | MFS_GRAYED | MFS_HILITE, -1, -1, -1, -1, -1, -1, -1, -1, }, OK)
+ TMII_GMII ( {, S, MIIM_STATE, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, },
+ {, S, MIIM_STATE, -9, MFS_CHECKED | MFS_DEFAULT | MFS_GRAYED | MFS_HILITE, -9, 0, -9, -9, -9, -9, -9, -9, },
+ empty, OK, OK )
+ TMII_DONE
+ /* The style MFT_RADIOCHECK cannot be set with MIIM_CHECKMARKS only */
+ TMII_INSMI( {, S, MIIM_TYPE, MFT_BITMAP, -1, -1, -1, -1, -1, -1, hbm, -1, -1, }, OK)
+ TMII_SMII( {, S, MIIM_CHECKMARKS, MFT_RADIOCHECK, -1, -1, -1, hbm, hbm, -1, -1, -1, -1, }, OK)
+ TMII_GMII ( {, S, MIIM_CHECKMARKS | MIIM_TYPE, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, },
+ {, S, MIIM_CHECKMARKS | MIIM_TYPE, MFT_BITMAP, -9, -9, 0, hbm, hbm, -9, hbm, 0, hbm, },
+ empty, OK, OK )
+ TMII_DONE
+ /* MFT_BITMAP is added automatically by GetMenuItemInfo() for MIIM_TYPE */
+ TMII_INSMI( {, S, MIIM_TYPE, MFT_BITMAP, -1, -1, -1, -1, -1, -1, hbm, -1, -1, }, OK)
+ TMII_SMII( {, S, MIIM_FTYPE, MFT_OWNERDRAW, -1, -1, -1, -1, -1, -1, 0x1234, -1, -1, }, OK)
+ TMII_GMII ( {, S, MIIM_FTYPE, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, },
+ {, S, MIIM_FTYPE, MFT_OWNERDRAW, -9, -9, 0, -9, -9, -9, -9, -9, -9, },
+ empty, OK, OK )
+ TMII_GMII ( {, S, MIIM_TYPE, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, },
+ {, S, MIIM_TYPE, MFT_BITMAP | MFT_OWNERDRAW, -9, -9, 0, -9, -9, -9, hbm, 0, hbm, },
+ empty, OK, OK )
+ TMII_GMII ( {, S, MIIM_FTYPE, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, },
+ {, S, MIIM_FTYPE, MFT_OWNERDRAW, -9, -9, 0, -9, -9, -9, -9, -9, -9, },
+ empty, OK, OK )
+ TMII_SMII( {, S, MIIM_BITMAP, -1, -1, -1, -1, -1, -1, -1, -1, -1, NULL, }, OK)
+ TMII_GMII ( {, S, MIIM_TYPE, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, },
+ {, S, MIIM_TYPE, MFT_OWNERDRAW, -9, -9, 0, -9, -9, -9, NULL, 0, NULL, },
+ empty, OK, OK )
+ TMII_DONE
} while( !(ansi = !ansi) );
DeleteObject( hbm);
}
@@ -1686,6 +1775,71 @@
DestroyWindow(hWnd);
}
+void test_menu_flags( void )
+{
+ HMENU hMenu, hPopupMenu;
+
+ hMenu = CreateMenu();
+ hPopupMenu = CreatePopupMenu();
+
+ AppendMenu(hMenu, MF_POPUP | MF_STRING, (UINT)hPopupMenu, "Popup");
+
+ AppendMenu(hPopupMenu, MF_STRING | MF_HILITE | MF_DEFAULT, 101, "Item 1");
+ InsertMenu(hPopupMenu, 1, MF_BYPOSITION | MF_STRING | MF_HILITE | MF_DEFAULT, 102, "Item 2");
+ AppendMenu(hPopupMenu, MF_STRING, 103, "Item 3");
+ ModifyMenu(hPopupMenu, 2, MF_BYPOSITION | MF_STRING | MF_HILITE | MF_DEFAULT, 103, "Item 3");
+
+ ok(GetMenuState(hPopupMenu, 0, MF_BYPOSITION) & MF_HILITE,
+ "AppendMenu should accept MF_HILITE\n");
+ ok(GetMenuState(hPopupMenu, 1, MF_BYPOSITION) & MF_HILITE,
+ "InsertMenu should accept MF_HILITE\n");
+ ok(GetMenuState(hPopupMenu, 2, MF_BYPOSITION) & MF_HILITE,
+ "ModifyMenu should accept MF_HILITE\n");
+
+ ok(!(GetMenuState(hPopupMenu, 0, MF_BYPOSITION) & MF_DEFAULT),
+ "AppendMenu must not accept MF_DEFAULT\n");
+ ok(!(GetMenuState(hPopupMenu, 1, MF_BYPOSITION) & MF_DEFAULT),
+ "InsertMenu must not accept MF_DEFAULT\n");
+ ok(!(GetMenuState(hPopupMenu, 2, MF_BYPOSITION) & MF_DEFAULT),
+ "ModifyMenu must not accept MF_DEFAULT\n");
+
+ DestroyMenu(hMenu);
+}
+
+void test_menu_hilitemenuitem( void )
+{
+ HMENU hMenu, hPopupMenu;
+
+ hMenu = CreateMenu();
+ hPopupMenu = CreatePopupMenu();
+
+ AppendMenu(hMenu, MF_POPUP | MF_STRING, (UINT)hPopupMenu, "Popup");
+
+ AppendMenu(hPopupMenu, MF_STRING, 101, "Item 1");
+ AppendMenu(hPopupMenu, MF_STRING, 102, "Item 2");
+ AppendMenu(hPopupMenu, MF_STRING, 103, "Item 3");
+
+ HiliteMenuItem(NULL, hPopupMenu, 0, MF_HILITE);
+ HiliteMenuItem(NULL, hPopupMenu, 1, MF_HILITE);
+ HiliteMenuItem(NULL, hPopupMenu, 2, MF_HILITE);
+ HiliteMenuItem(NULL, hPopupMenu, 1, MF_UNHILITE);
+
+ todo_wine
+ {
+ ok(GetMenuState(hPopupMenu, 0, MF_BYPOSITION) & MF_HILITE,
+ "HiliteMenuItem: Item 1 is not hilited\n");
+ }
+ ok(!(GetMenuState(hPopupMenu, 1, MF_BYPOSITION) & MF_HILITE),
+ "HiliteMenuItem: Item 2 is hilited\n");
+ todo_wine
+ {
+ ok(GetMenuState(hPopupMenu, 2, MF_BYPOSITION) & MF_HILITE,
+ "HiliteMenuItem: Item 3 is not hilited\n");
+ }
+
+ DestroyMenu(hMenu);
+}
+
START_TEST(menu)
{
pSetMenuInfo =
@@ -1702,4 +1856,6 @@
test_menu_search_bycommand();
test_menu_bmp_and_string();
test_menu_input();
+ test_menu_flags();
+ test_menu_hilitemenuitem();
}
More information about the wine-patches
mailing list