user32: Add a test for CheckMenuRadioItem and make it pass under
Wine
Dmitry Timoshkov
dmitry at codeweavers.com
Mon May 14 09:46:32 CDT 2007
Hello,
as reported in the bug 8038 CheckMenuRadioItem doesn't behave as expected
in Wine. The test I'm adding for CheckMenuRadioItem passes under Win98 and XP.
Changelog:
user32: Add a test for CheckMenuRadioItem and make it pass under Wine.
---
dlls/user32/menu.c | 61 +++++++++++++--------
dlls/user32/tests/menu.c | 119 ++++++++++++++++++++++++++++++++++++++++-
dlls/user32/tests/resource.rc | 21 +++++++
3 files changed, 177 insertions(+), 24 deletions(-)
diff --git a/dlls/user32/menu.c b/dlls/user32/menu.c
index 4aca343..789f769 100644
--- a/dlls/user32/menu.c
+++ b/dlls/user32/menu.c
@@ -4817,34 +4817,49 @@ BOOL WINAPI CheckMenuRadioItem(HMENU hMenu,
UINT first, UINT last, UINT check,
UINT bypos)
{
- MENUITEM *mifirst, *milast, *micheck;
- HMENU mfirst = hMenu, mlast = hMenu, mcheck = hMenu;
+ BOOL done = FALSE;
+ UINT i;
+ MENUITEM *mi_first = NULL, *mi_check;
+ HMENU m_first, m_check;
- TRACE("%p: %d-%d, check %d, bypos=%d\n", hMenu, first, last, check, bypos);
+ TRACE("%p: %u-%u, check %u, flags %04x\n", hMenu, first, last, check, bypos);
- mifirst = MENU_FindItem (&mfirst, &first, bypos);
- milast = MENU_FindItem (&mlast, &last, bypos);
- micheck = MENU_FindItem (&mcheck, &check, bypos);
+ for (i = first; i <= last; i++)
+ {
+ UINT pos = i;
- if (mifirst == NULL || milast == NULL || micheck == NULL ||
- mifirst > milast || mfirst != mlast || mfirst != mcheck ||
- micheck > milast || micheck < mifirst)
- return FALSE;
+ if (!mi_first)
+ {
+ m_first = hMenu;
+ mi_first = MENU_FindItem(&m_first, &pos, bypos);
+ if (!mi_first) continue;
+ mi_check = mi_first;
+ m_check = m_first;
+ }
+ else
+ {
+ m_check = hMenu;
+ mi_check = MENU_FindItem(&m_check, &pos, bypos);
+ if (!mi_check) continue;
+ }
- while (mifirst <= milast)
- {
- if (mifirst == micheck)
- {
- mifirst->fType |= MFT_RADIOCHECK;
- mifirst->fState |= MFS_CHECKED;
- } else {
- mifirst->fType &= ~MFT_RADIOCHECK;
- mifirst->fState &= ~MFS_CHECKED;
- }
- mifirst++;
- }
+ if (m_first != m_check) continue;
+ if (mi_check->fType == MFT_SEPARATOR) continue;
- return TRUE;
+ if (i == check)
+ {
+ mi_check->fType |= MFT_RADIOCHECK;
+ mi_check->fState |= MFS_CHECKED;
+ done = TRUE;
+ }
+ else
+ {
+ /* MSDN is wrong, Windows does not remove MFT_RADIOCHECK */
+ mi_check->fState &= ~MFS_CHECKED;
+ }
+ }
+
+ return done;
}
diff --git a/dlls/user32/tests/menu.c b/dlls/user32/tests/menu.c
index 0fb2ced..141d6c5 100644
--- a/dlls/user32/tests/menu.c
+++ b/dlls/user32/tests/menu.c
@@ -2,6 +2,7 @@
* Unit tests for menus
*
* Copyright 2005 Robert Shearman
+ * Copyright 2007 Dmitry Timoshkov
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -18,7 +19,8 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
-#include <stdlib.h>
+#define _WIN32_WINNT 0x0501
+
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
@@ -1872,6 +1874,120 @@ static void test_menu_hilitemenuitem( void )
DestroyMenu(hMenu);
}
+static void check_menu_items(HMENU hmenu, UINT checked_cmd, UINT checked_type,
+ UINT checked_state)
+{
+ UINT i, count;
+
+ count = GetMenuItemCount(hmenu);
+
+ for (i = 0; i < count; i++)
+ {
+ BOOL ret;
+ MENUITEMINFO mii;
+
+ memset(&mii, 0, sizeof(mii));
+ mii.cbSize = sizeof(mii);
+ mii.fMask = MIIM_FTYPE | MIIM_STATE | MIIM_ID | MIIM_SUBMENU;
+ ret = GetMenuItemInfo(hmenu, i, TRUE, &mii);
+ ok(ret, "GetMenuItemInfo(%u) failed\n", i);
+#if 0
+ trace("item #%u: fType %04x, fState %04x, wID %u, hSubMenu %p\n",
+ i, mii.fType, mii.fState, mii.wID, mii.hSubMenu);
+#endif
+ if (mii.hSubMenu)
+ {
+ ok((HMENU)mii.wID == mii.hSubMenu, "id %u: wID should be equal to hSubMenu\n", checked_cmd);
+ check_menu_items(mii.hSubMenu, checked_cmd, checked_type, checked_state);
+ }
+ else
+ {
+ if (mii.wID == checked_cmd)
+ {
+ ok(mii.fType == checked_type, "id %u: expected fType %04x, got %04x\n", checked_cmd, checked_type, mii.fType);
+ ok(mii.fState == checked_state, "id %u: expected fState %04x, got %04x\n", checked_cmd, checked_state, mii.fState);
+ ok(mii.wID != 0, "id %u: not expected wID 0\n", checked_cmd);
+ }
+ else
+ {
+ ok(mii.fType != MFT_RADIOCHECK, "id %u: not expected fType MFT_RADIOCHECK on cmd %u\n", checked_cmd, mii.wID);
+
+ if (mii.fType == MFT_SEPARATOR)
+ {
+todo_wine {
+ ok(mii.fState == MFS_GRAYED, "id %u: expected fState MFS_GRAYED, got %04x\n", checked_cmd, mii.fState);
+}
+ ok(mii.wID == 0, "id %u: expected wID 0, got %u\n", checked_cmd, mii.wID);
+ }
+ else
+ {
+ ok(mii.fState == 0, "id %u: expected fState 0, got %04x\n", checked_cmd, mii.fState);
+ ok(mii.wID != 0, "id %u: not expected wID 0\n", checked_cmd);
+ }
+ }
+ }
+ }
+}
+
+static void clear_ftype_and_state(HMENU hmenu, UINT id, UINT flags)
+{
+ BOOL ret;
+ MENUITEMINFO mii;
+
+ memset(&mii, 0, sizeof(mii));
+ mii.cbSize = sizeof(mii);
+ mii.fMask = MIIM_FTYPE | MIIM_STATE;
+ ret = SetMenuItemInfo(hmenu, id, (flags & MF_BYPOSITION) != 0, &mii);
+ ok(ret, "SetMenuItemInfo(%u) failed\n", id);
+}
+
+static void test_CheckMenuRadioItem(void)
+{
+ BOOL ret;
+ HMENU hmenu;
+
+ hmenu = LoadMenu(GetModuleHandle(0), MAKEINTRESOURCE(1));
+ assert(hmenu != 0);
+
+ check_menu_items(hmenu, -1, 0, 0);
+
+ ret = CheckMenuRadioItem(hmenu, 100, 100, 100, MF_BYCOMMAND);
+ ok(ret, "CheckMenuRadioItem failed\n");
+ check_menu_items(hmenu, 100, MFT_RADIOCHECK, MFS_CHECKED);
+
+ /* MSDN is wrong, Windows does not remove MFT_RADIOCHECK */
+ ret = CheckMenuRadioItem(hmenu, 100, 100, -1, MF_BYCOMMAND);
+ ok(!ret, "CheckMenuRadioItem should return FALSE\n");
+ check_menu_items(hmenu, 100, MFT_RADIOCHECK, 0);
+
+ /* clear check */
+ clear_ftype_and_state(hmenu, 100, MF_BYCOMMAND);
+ check_menu_items(hmenu, -1, 0, 0);
+
+ /* first and checked items are on different menus */
+ ret = CheckMenuRadioItem(hmenu, 0, 300, 202, MF_BYCOMMAND);
+ ok(!ret, "CheckMenuRadioItem should return FALSE\n");
+ check_menu_items(hmenu, -1, 0, 0);
+
+ ret = CheckMenuRadioItem(hmenu, 200, 300, 202, MF_BYCOMMAND);
+ ok(ret, "CheckMenuRadioItem failed\n");
+ check_menu_items(hmenu, 202, MFT_RADIOCHECK, MFS_CHECKED);
+
+ /* MSDN is wrong, Windows does not remove MFT_RADIOCHECK */
+ ret = CheckMenuRadioItem(hmenu, 202, 202, -1, MF_BYCOMMAND);
+ ok(!ret, "CheckMenuRadioItem should return FALSE\n");
+ check_menu_items(hmenu, 202, MFT_RADIOCHECK, 0);
+
+ /* clear check */
+ clear_ftype_and_state(hmenu, 202, MF_BYCOMMAND);
+ check_menu_items(hmenu, -1, 0, 0);
+
+ /* just for fun, try to check separator */
+ ret = CheckMenuRadioItem(hmenu, 0, 300, 0, MF_BYCOMMAND);
+ ok(!ret, "CheckMenuRadioItem should return FALSE\n");
+ check_menu_items(hmenu, -1, 0, 0);
+}
+
START_TEST(menu)
{
pSetMenuInfo =
@@ -1890,4 +2006,5 @@ START_TEST(menu)
test_menu_input();
test_menu_flags();
test_menu_hilitemenuitem();
+ test_CheckMenuRadioItem();
}
diff --git a/dlls/user32/tests/resource.rc b/dlls/user32/tests/resource.rc
index 47328fc..c2d5c30 100644
--- a/dlls/user32/tests/resource.rc
+++ b/dlls/user32/tests/resource.rc
@@ -106,3 +106,24 @@ END
'00 00 00 00 00 00 00 00 00 00 FF FF FF 00 40 00'
'00 00'
} */
+
+1 MENU
+{
+ POPUP "&File"
+ {
+ MENUITEM "&New", 100
+ MENUITEM "&Open", 101
+ MENUITEM "&Save", 102
+ MENUITEM SEPARATOR
+ MENUITEM "E&xit", 103
+ }
+ POPUP "Edit"
+ {
+ MENUITEM "&Undo", 200
+ MENUITEM SEPARATOR
+ MENUITEM "Cu&t", 201
+ MENUITEM "&Copy", 202
+ MENUITEM "&Paste", 203
+ MENUITEM "&Delete", 204
+ }
+}
--
1.5.1.3
More information about the wine-patches
mailing list