From bbd8ae432256d32d99e75580b1896002045223b9 Mon Sep 17 00:00:00 2001 From: Dmitry Timoshkov Date: Wed, 18 Jun 2008 12:34:01 +0900 Subject: [PATCH] user32: Add a test for MNS_NOTIFYBYPOS, make it pass under Wine. --- dlls/user32/menu.c | 41 ++-- dlls/user32/tests/msg.c | 375 +++++++++++++++++++++++++++++----- dlls/user32/tests/resource.rc | 7 +- 3 files changed, 351 insertions(+), 72 deletions(-) diff --git a/dlls/user32/menu.c b/dlls/user32/menu.c index dd859b170ec..88eb72f4e3f 100644 --- a/dlls/user32/menu.c +++ b/dlls/user32/menu.c @@ -2267,7 +2267,7 @@ static HMENU MENU_GetSubPopup( HMENU hmenu ) * Hide the sub-popup menus of this menu. */ static void MENU_HideSubPopups( HWND hwndOwner, HMENU hmenu, - BOOL sendMenuSelect ) + BOOL sendMenuSelect, UINT wFlags ) { POPUPMENU *menu = MENU_GetMenu( hmenu ); @@ -2289,10 +2289,14 @@ static void MENU_HideSubPopups( HWND hwndOwner, HMENU hmenu, } else return; submenu = MENU_GetMenu( hsubmenu ); - MENU_HideSubPopups( hwndOwner, hsubmenu, FALSE ); + MENU_HideSubPopups( hwndOwner, hsubmenu, FALSE, wFlags ); MENU_SelectItem( hwndOwner, hsubmenu, NO_SELECTED_ITEM, sendMenuSelect, 0 ); DestroyWindow( submenu->hWnd ); submenu->hWnd = 0; + + if (!(wFlags & TPM_NONOTIFY)) + SendMessageW( hwndOwner, WM_UNINITMENUPOPUP, (WPARAM)hsubmenu, + MAKELPARAM(0, IS_SYSTEM_MENU(submenu)) ); } } @@ -2499,7 +2503,7 @@ static INT MENU_ExecFocusedItem( MTRACKER* pmt, HMENU hMenu, UINT wFlags ) * * Helper function for menu navigation routines. */ -static void MENU_SwitchTracking( MTRACKER* pmt, HMENU hPtMenu, UINT id ) +static void MENU_SwitchTracking( MTRACKER* pmt, HMENU hPtMenu, UINT id, UINT wFlags ) { POPUPMENU *ptmenu = MENU_GetMenu( hPtMenu ); POPUPMENU *topmenu = MENU_GetMenu( pmt->hTopMenu ); @@ -2510,11 +2514,11 @@ static void MENU_SwitchTracking( MTRACKER* pmt, HMENU hPtMenu, UINT id ) !((ptmenu->wFlags | topmenu->wFlags) & MF_POPUP) ) { /* both are top level menus (system and menu-bar) */ - MENU_HideSubPopups( pmt->hOwnerWnd, pmt->hTopMenu, FALSE ); + MENU_HideSubPopups( pmt->hOwnerWnd, pmt->hTopMenu, FALSE, wFlags ); MENU_SelectItem( pmt->hOwnerWnd, pmt->hTopMenu, NO_SELECTED_ITEM, FALSE, 0 ); pmt->hTopMenu = hPtMenu; } - else MENU_HideSubPopups( pmt->hOwnerWnd, hPtMenu, FALSE ); + else MENU_HideSubPopups( pmt->hOwnerWnd, hPtMenu, FALSE, wFlags ); MENU_SelectItem( pmt->hOwnerWnd, hPtMenu, id, TRUE, 0 ); } @@ -2542,7 +2546,7 @@ static BOOL MENU_ButtonDown( MTRACKER* pmt, HMENU hPtMenu, UINT wFlags ) if( item ) { if( ptmenu->FocusedItem != id ) - MENU_SwitchTracking( pmt, hPtMenu, id ); + MENU_SwitchTracking( pmt, hPtMenu, id, wFlags ); /* If the popup menu is not already "popped" */ if(!(item->fState & MF_MOUSESELECT )) @@ -2630,7 +2634,7 @@ static BOOL MENU_MouseMove( MTRACKER* pmt, HMENU hPtMenu, UINT wFlags ) } else if( ptmenu->FocusedItem != id ) { - MENU_SwitchTracking( pmt, hPtMenu, id ); + MENU_SwitchTracking( pmt, hPtMenu, id, wFlags ); pmt->hCurrentMenu = MENU_ShowSubPopup(pmt->hOwnerWnd, hPtMenu, FALSE, wFlags); } return TRUE; @@ -2642,7 +2646,7 @@ static BOOL MENU_MouseMove( MTRACKER* pmt, HMENU hPtMenu, UINT wFlags ) * * NOTE: WM_NEXTMENU documented in Win32 is a bit different. */ -static LRESULT MENU_DoNextMenu( MTRACKER* pmt, UINT vk ) +static LRESULT MENU_DoNextMenu( MTRACKER* pmt, UINT vk, UINT wFlags ) { POPUPMENU *menu = MENU_GetMenu( pmt->hTopMenu ); BOOL atEnd = FALSE; @@ -2753,7 +2757,7 @@ static LRESULT MENU_DoNextMenu( MTRACKER* pmt, UINT vk ) MENU_SelectItem( pmt->hOwnerWnd, pmt->hTopMenu, NO_SELECTED_ITEM, FALSE, 0 ); if( pmt->hCurrentMenu != pmt->hTopMenu ) - MENU_HideSubPopups( pmt->hOwnerWnd, pmt->hTopMenu, FALSE ); + MENU_HideSubPopups( pmt->hOwnerWnd, pmt->hTopMenu, FALSE, wFlags ); } if( hNewWnd != pmt->hOwnerWnd ) @@ -2834,7 +2838,7 @@ static BOOL MENU_KeyEscape(MTRACKER* pmt, UINT wFlags) hmenutmp = MENU_GetSubPopup( hmenuprev ); } - MENU_HideSubPopups( pmt->hOwnerWnd, hmenuprev, TRUE ); + MENU_HideSubPopups( pmt->hOwnerWnd, hmenuprev, TRUE, wFlags ); pmt->hCurrentMenu = hmenuprev; bEndMenu = FALSE; } @@ -2873,14 +2877,14 @@ static void MENU_KeyLeft( MTRACKER* pmt, UINT wFlags ) hmenutmp = MENU_GetSubPopup( hmenuprev ); } - MENU_HideSubPopups( pmt->hOwnerWnd, hmenuprev, TRUE ); + MENU_HideSubPopups( pmt->hOwnerWnd, hmenuprev, TRUE, wFlags ); pmt->hCurrentMenu = hmenuprev; if ( (hmenuprev == pmt->hTopMenu) && !(menu->wFlags & MF_POPUP) ) { /* move menu bar selection if no more popups are left */ - if( !MENU_DoNextMenu( pmt, VK_LEFT) ) + if( !MENU_DoNextMenu( pmt, VK_LEFT, wFlags ) ) MENU_MoveSelection( pmt->hOwnerWnd, pmt->hTopMenu, ITEM_PREV ); if ( hmenuprev != hmenutmp || pmt->trackFlags & TF_SUSPENDPOPUP ) @@ -2936,12 +2940,12 @@ static void MENU_KeyRight( MTRACKER* pmt, UINT wFlags ) { if( pmt->hCurrentMenu != pmt->hTopMenu ) { - MENU_HideSubPopups( pmt->hOwnerWnd, pmt->hTopMenu, FALSE ); + MENU_HideSubPopups( pmt->hOwnerWnd, pmt->hTopMenu, FALSE, wFlags ); hmenutmp = pmt->hCurrentMenu = pmt->hTopMenu; } else hmenutmp = 0; /* try to move to the next item */ - if( !MENU_DoNextMenu( pmt, VK_RIGHT) ) + if( !MENU_DoNextMenu( pmt, VK_RIGHT, wFlags ) ) MENU_MoveSelection( pmt->hOwnerWnd, pmt->hTopMenu, ITEM_NEXT ); if( hmenutmp || pmt->trackFlags & TF_SUSPENDPOPUP ) @@ -3232,12 +3236,16 @@ static BOOL MENU_TrackMenu( HMENU hmenu, UINT wFlags, INT x, INT y, if( IsWindow( mt.hOwnerWnd ) ) { - MENU_HideSubPopups( mt.hOwnerWnd, mt.hTopMenu, FALSE ); + MENU_HideSubPopups( mt.hOwnerWnd, mt.hTopMenu, FALSE, wFlags ); if (menu && (menu->wFlags & MF_POPUP)) { DestroyWindow( menu->hWnd ); menu->hWnd = 0; + + if (!(wFlags & TPM_NONOTIFY)) + SendMessageW( mt.hOwnerWnd, WM_UNINITMENUPOPUP, (WPARAM)mt.hTopMenu, + MAKELPARAM(0, IS_SYSTEM_MENU(menu)) ); } MENU_SelectItem( mt.hOwnerWnd, mt.hTopMenu, NO_SELECTED_ITEM, FALSE, 0 ); SendMessageW( mt.hOwnerWnd, WM_MENUSELECT, MAKELONG(0,0xffff), 0 ); @@ -3671,7 +3679,7 @@ BOOL WINAPI HiliteMenuItem( HWND hWnd, HMENU hMenu, UINT wItemID, if (!MENU_FindItem( &hMenu, &wItemID, wHilite )) return FALSE; if (!(menu = MENU_GetMenu(hMenu))) return FALSE; if (menu->FocusedItem == wItemID) return TRUE; - MENU_HideSubPopups( hWnd, hMenu, FALSE ); + MENU_HideSubPopups( hWnd, hMenu, FALSE, 0 ); MENU_SelectItem( hWnd, hMenu, wItemID, TRUE, 0 ); return TRUE; } @@ -4974,7 +4982,6 @@ BOOL WINAPI SetMenuInfo (HMENU hMenu, LPCMENUINFO lpmi) 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_NOTIFYBYPOS) FIXME("MNS_NOTIFYBYPOS partially implemented\n"); } return TRUE; diff --git a/dlls/user32/tests/msg.c b/dlls/user32/tests/msg.c index 3c403200ca1..962aa5c745a 100644 --- a/dlls/user32/tests/msg.c +++ b/dlls/user32/tests/msg.c @@ -6952,6 +6952,35 @@ static BOOL RegisterWindowClasses(void) return TRUE; } +static BOOL is_our_logged_class(HWND hwnd) +{ + char buf[256]; + + if (GetClassNameA(hwnd, buf, sizeof(buf))) + { + if (!lstrcmpiA(buf, "TestWindowClass") || + !lstrcmpiA(buf, "ShowWindowClass") || + !lstrcmpiA(buf, "TestParentClass") || + !lstrcmpiA(buf, "TestPopupClass") || + !lstrcmpiA(buf, "SimpleWindowClass") || + !lstrcmpiA(buf, "TestDialogClass") || + !lstrcmpiA(buf, "MDI_frame_class") || + !lstrcmpiA(buf, "MDI_client_class") || + !lstrcmpiA(buf, "MDI_child_class") || + !lstrcmpiA(buf, "my_button_class") || + !lstrcmpiA(buf, "my_edit_class") || + !lstrcmpiA(buf, "static") || + !lstrcmpiA(buf, "ListBox") || + !lstrcmpiA(buf, "ComboBox") || + !lstrcmpiA(buf, "MyDialogClass") || + !lstrcmpiA(buf, "#32770") || + !lstrcmpiA(buf, "#32768")) + return TRUE; + trace("ignoring window class %s\n", buf); + } + return FALSE; +} + static HHOOK hCBT_hook; static DWORD cbt_hook_thread_id; @@ -6970,7 +6999,6 @@ static LRESULT CALLBACK cbt_hook_proc(int nCode, WPARAM wParam, LPARAM lParam) "HCBT_SETFOCUS" }; const char *code_name = (nCode >= 0 && nCode <= HCBT_SETFOCUS) ? CBT_code_name[nCode] : "Unknown"; HWND hwnd; - char buf[256]; trace("CBT: %d (%s), %08lx, %08lx\n", nCode, code_name, wParam, lParam); @@ -7012,33 +7040,15 @@ static LRESULT CALLBACK cbt_hook_proc(int nCode, WPARAM wParam, LPARAM lParam) /* Log also SetFocus(0) calls */ hwnd = wParam ? (HWND)wParam : (HWND)lParam; - if (GetClassNameA(hwnd, buf, sizeof(buf))) + if (is_our_logged_class(hwnd)) { - if (!lstrcmpiA(buf, "TestWindowClass") || - !lstrcmpiA(buf, "ShowWindowClass") || - !lstrcmpiA(buf, "TestParentClass") || - !lstrcmpiA(buf, "TestPopupClass") || - !lstrcmpiA(buf, "SimpleWindowClass") || - !lstrcmpiA(buf, "TestDialogClass") || - !lstrcmpiA(buf, "MDI_frame_class") || - !lstrcmpiA(buf, "MDI_client_class") || - !lstrcmpiA(buf, "MDI_child_class") || - !lstrcmpiA(buf, "my_button_class") || - !lstrcmpiA(buf, "my_edit_class") || - !lstrcmpiA(buf, "static") || - !lstrcmpiA(buf, "ListBox") || - !lstrcmpiA(buf, "ComboBox") || - !lstrcmpiA(buf, "MyDialogClass") || - !lstrcmpiA(buf, "#32770")) - { - struct message msg; + struct message msg; - msg.message = nCode; - msg.flags = hook|wparam|lparam; - msg.wParam = wParam; - msg.lParam = lParam; - add_message(&msg); - } + msg.message = nCode; + msg.flags = hook|wparam|lparam; + msg.wParam = wParam; + msg.lParam = lParam; + add_message(&msg); } return CallNextHookEx(hCBT_hook, nCode, wParam, lParam); } @@ -7051,8 +7061,6 @@ static void CALLBACK win_event_proc(HWINEVENTHOOK hevent, DWORD thread_id, DWORD event_time) { - char buf[256]; - trace("WEH:%p,event %08x,hwnd %p,obj %08x,id %08x,thread %08x,time %08x\n", hevent, event, hwnd, object_id, child_id, thread_id, event_time); @@ -7061,33 +7069,15 @@ static void CALLBACK win_event_proc(HWINEVENTHOOK hevent, /* ignore mouse cursor events */ if (object_id == OBJID_CURSOR) return; - if (!hwnd || GetClassNameA(hwnd, buf, sizeof(buf))) + if (!hwnd || is_our_logged_class(hwnd)) { - if (!hwnd || - !lstrcmpiA(buf, "TestWindowClass") || - !lstrcmpiA(buf, "TestParentClass") || - !lstrcmpiA(buf, "TestPopupClass") || - !lstrcmpiA(buf, "SimpleWindowClass") || - !lstrcmpiA(buf, "TestDialogClass") || - !lstrcmpiA(buf, "MDI_frame_class") || - !lstrcmpiA(buf, "MDI_client_class") || - !lstrcmpiA(buf, "MDI_child_class") || - !lstrcmpiA(buf, "my_button_class") || - !lstrcmpiA(buf, "my_edit_class") || - !lstrcmpiA(buf, "static") || - !lstrcmpiA(buf, "ListBox") || - !lstrcmpiA(buf, "ComboBox") || - !lstrcmpiA(buf, "MyDialogClass") || - !lstrcmpiA(buf, "#32770")) - { - struct message msg; + struct message msg; - msg.message = event; - msg.flags = winevent_hook|wparam|lparam; - msg.wParam = object_id; - msg.lParam = child_id; - add_message(&msg); - } + msg.message = event; + msg.flags = winevent_hook|wparam|lparam; + msg.wParam = object_id; + msg.lParam = child_id; + add_message(&msg); } } @@ -10442,6 +10432,284 @@ static void test_listbox_messages(void) DestroyWindow(parent); } +/*************************** Menu test ******************************/ +static const struct message wm_popup_menu_1[] = +{ + { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_MENU, 0x20000001 }, + { WM_SYSKEYDOWN, sent|wparam|lparam, VK_MENU, 0x20000001 }, + { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 'E', 0x20000001 }, + { WM_SYSKEYDOWN, sent|wparam|lparam, 'E', 0x20000001 }, + { WM_SYSCHAR, sent|wparam|lparam, 'e', 0x20000001 }, + { HCBT_SYSCOMMAND, hook|wparam|lparam, SC_KEYMENU, 'e' }, + { WM_ENTERMENULOOP, sent|wparam|lparam, 0, 0 }, + { WM_INITMENU, sent|lparam, 0, 0 }, + { WM_MENUSELECT, sent|wparam, MAKEWPARAM(1,MF_HILITE|MF_POPUP) }, + { WM_INITMENUPOPUP, sent|lparam, 0, 1 }, + { HCBT_CREATEWND, hook|optional }, /* Win9x doesn't create a window */ + { WM_MENUSELECT, sent|wparam, MAKEWPARAM(200,MF_HILITE) }, + { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 'E', 0xf0000001 }, + { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_MENU, 0xd0000001 }, + { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_RETURN, 0x10000001 }, + { HCBT_DESTROYWND, hook|optional }, /* Win9x doesn't create a window */ + { WM_UNINITMENUPOPUP, sent|lparam, 0, 0 }, + { WM_MENUSELECT, sent|wparam|lparam, MAKEWPARAM(0,0xffff), 0 }, + { WM_EXITMENULOOP, sent|wparam|lparam, 0, 0 }, + { WM_MENUCOMMAND, sent }, /* |wparam, 200 - Win9x */ + { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_RETURN, 0xc0000001 }, + { WM_KEYUP, sent|wparam|lparam, VK_RETURN, 0xc0000001 }, + { 0 } +}; +static const struct message wm_popup_menu_2[] = +{ + { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_MENU, 0x20000001 }, + { WM_SYSKEYDOWN, sent|wparam|lparam, VK_MENU, 0x20000001 }, + { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 'F', 0x20000001 }, + { WM_SYSKEYDOWN, sent|wparam|lparam, 'F', 0x20000001 }, + { WM_SYSCHAR, sent|wparam|lparam, 'f', 0x20000001 }, + { HCBT_SYSCOMMAND, hook|wparam|lparam, SC_KEYMENU, 'f' }, + { WM_ENTERMENULOOP, sent|wparam|lparam, 0, 0 }, + { WM_INITMENU, sent|lparam, 0, 0 }, + { WM_MENUSELECT, sent|wparam, MAKEWPARAM(0,MF_HILITE|MF_POPUP) }, + { WM_INITMENUPOPUP, sent|lparam, 0, 0 }, + { WM_MENUSELECT, sent|wparam|optional, MAKEWPARAM(0,MF_HILITE|MF_POPUP) }, /* Win9x */ + { WM_INITMENUPOPUP, sent|lparam|optional, 0, 0 }, /* Win9x */ + { HCBT_CREATEWND, hook }, + { WM_MENUSELECT, sent }, /*|wparam, MAKEWPARAM(0,MF_HILITE|MF_POPUP) - XP + |wparam, MAKEWPARAM(100,MF_HILITE) - Win9x */ + { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 'F', 0xf0000001 }, + { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_MENU, 0xd0000001 }, + { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_RIGHT, 0x10000001 }, + { WM_INITMENUPOPUP, sent|lparam|optional, 0, 0 }, /* Win9x doesn't send it */ + { HCBT_CREATEWND, hook|optional }, /* Win9x doesn't send it */ + { WM_MENUSELECT, sent|wparam|optional, MAKEWPARAM(100,MF_HILITE) }, + { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_RIGHT, 0xd0000001 }, + { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_RETURN, 0x10000001 }, + { HCBT_DESTROYWND, hook }, + { WM_UNINITMENUPOPUP, sent|lparam, 0, 0 }, + { HCBT_DESTROYWND, hook|optional }, /* Win9x doesn't send it */ + { WM_UNINITMENUPOPUP, sent|lparam, 0, 0 }, + { WM_MENUSELECT, sent|wparam|lparam, MAKEWPARAM(0,0xffff), 0 }, + { WM_EXITMENULOOP, sent|wparam|lparam, 0, 0 }, + { WM_MENUCOMMAND, sent }, /* |wparam, 100 - Win9x */ + { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_RETURN, 0xc0000001 }, + { WM_KEYUP, sent|wparam|lparam, VK_RETURN, 0xc0000001 }, + { 0 } +}; +static const struct message wm_popup_menu_3[] = +{ + { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_MENU, 0x20000001 }, + { WM_SYSKEYDOWN, sent|wparam|lparam, VK_MENU, 0x20000001 }, + { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 'F', 0x20000001 }, + { WM_SYSKEYDOWN, sent|wparam|lparam, 'F', 0x20000001 }, + { WM_SYSCHAR, sent|wparam|lparam, 'f', 0x20000001 }, + { HCBT_SYSCOMMAND, hook|wparam|lparam, SC_KEYMENU, 'f' }, + { WM_ENTERMENULOOP, sent|wparam|lparam, 0, 0 }, + { WM_INITMENU, sent|lparam, 0, 0 }, + { WM_MENUSELECT, sent|wparam, MAKEWPARAM(0,MF_HILITE|MF_POPUP) }, + { WM_INITMENUPOPUP, sent|lparam, 0, 0 }, + { WM_MENUSELECT, sent|wparam|optional, MAKEWPARAM(0,MF_HILITE|MF_POPUP) }, /* Win9x */ + { WM_INITMENUPOPUP, sent|lparam|optional, 0, 0 }, /* Win9x */ + { HCBT_CREATEWND, hook }, + { WM_MENUSELECT, sent }, /*|wparam, MAKEWPARAM(0,MF_HILITE|MF_POPUP) - XP + |wparam, MAKEWPARAM(100,MF_HILITE) - Win9x */ + { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 'F', 0xf0000001 }, + { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_MENU, 0xd0000001 }, + { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_RIGHT, 0x10000001 }, + { WM_INITMENUPOPUP, sent|lparam|optional, 0, 0 }, /* Win9x doesn't send it */ + { HCBT_CREATEWND, hook|optional }, /* Win9x doesn't send it */ + { WM_MENUSELECT, sent|wparam|optional, MAKEWPARAM(100,MF_HILITE) }, + { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_RIGHT, 0xd0000001 }, + { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_RETURN, 0x10000001 }, + { HCBT_DESTROYWND, hook }, + { WM_UNINITMENUPOPUP, sent|lparam, 0, 0 }, + { HCBT_DESTROYWND, hook|optional }, /* Win9x doesn't send it */ + { WM_UNINITMENUPOPUP, sent|lparam, 0, 0 }, + { WM_MENUSELECT, sent|wparam|lparam, MAKEWPARAM(0,0xffff), 0 }, + { WM_EXITMENULOOP, sent|wparam|lparam, 0, 0 }, + { WM_COMMAND, sent|wparam|lparam, 100, 0 }, + { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_RETURN, 0xc0000001 }, + { WM_KEYUP, sent|wparam|lparam, VK_RETURN, 0xc0000001 }, + { 0 } +}; + +static LRESULT WINAPI parent_menu_proc(HWND hwnd, UINT message, WPARAM wp, LPARAM lp) +{ + if (message == WM_ENTERIDLE || + message == WM_INITMENU || + message == WM_INITMENUPOPUP || + message == WM_MENUSELECT || + message == WM_PARENTNOTIFY || + message == WM_ENTERMENULOOP || + message == WM_EXITMENULOOP || + message == WM_UNINITMENUPOPUP || + message == WM_KEYDOWN || + message == WM_KEYUP || + message == WM_CHAR || + message == WM_SYSKEYDOWN || + message == WM_SYSKEYUP || + message == WM_SYSCHAR || + message == WM_COMMAND || + message == WM_MENUCOMMAND) + { + struct message msg; + + trace("parent_menu_proc: %p, %04x, %08lx, %08lx\n", hwnd, message, wp, lp); + + msg.message = message; + msg.flags = sent|wparam|lparam; + msg.wParam = wp; + msg.lParam = lp; + add_message(&msg); + } + + return DefWindowProcA(hwnd, message, wp, lp); +} + +static void set_menu_style(HMENU hmenu, DWORD style) +{ + MENUINFO mi; + BOOL ret; + + mi.cbSize = sizeof(mi); + mi.fMask = MIM_STYLE; + mi.dwStyle = style; + SetLastError(0xdeadbeef); + ret = SetMenuInfo(hmenu, &mi); + ok(ret, "SetMenuInfo error %u\n", GetLastError()); +} + +static DWORD get_menu_style(HMENU hmenu) +{ + MENUINFO mi; + BOOL ret; + + mi.cbSize = sizeof(mi); + mi.fMask = MIM_STYLE; + mi.dwStyle = 0; + SetLastError(0xdeadbeef); + ret = GetMenuInfo(hmenu, &mi); + ok(ret, "GetMenuInfo error %u\n", GetLastError()); + + return mi.dwStyle; +} + +static void test_menu_messages(void) +{ + MSG msg; + WNDCLASSA cls; + HMENU hmenu, hmenu_popup; + HWND hwnd; + DWORD style; + + cls.style = 0; + cls.lpfnWndProc = parent_menu_proc; + cls.cbClsExtra = 0; + cls.cbWndExtra = 0; + cls.hInstance = GetModuleHandleA(0); + cls.hIcon = 0; + cls.hCursor = LoadCursorA(0, (LPSTR)IDC_ARROW); + cls.hbrBackground = GetStockObject(WHITE_BRUSH); + cls.lpszMenuName = NULL; + cls.lpszClassName = "TestMenuClass"; + UnregisterClass(cls.lpszClassName, cls.hInstance); + if (!RegisterClassA(&cls)) assert(0); + + SetLastError(0xdeadbeef); + hwnd = CreateWindowExA(0, "TestMenuClass", NULL, WS_OVERLAPPEDWINDOW | WS_VISIBLE, + 100, 100, 200, 200, 0, 0, 0, NULL); + ok(hwnd != 0, "LoadMenuA error %u\n", GetLastError()); + + SetLastError(0xdeadbeef); + hmenu = LoadMenuA(GetModuleHandle(0), MAKEINTRESOURCE(1)); + ok(hmenu != 0, "LoadMenuA error %u\n", GetLastError()); + + SetMenu(hwnd, hmenu); + + set_menu_style(hmenu, MNS_NOTIFYBYPOS); + style = get_menu_style(hmenu); + ok(style == MNS_NOTIFYBYPOS, "expected MNS_NOTIFYBYPOS, got %u\n", style); + + hmenu_popup = GetSubMenu(hmenu, 0); + ok(hmenu_popup != 0, "GetSubMenu returned 0 for submenu 0\n"); + style = get_menu_style(hmenu_popup); + ok(style == 0, "expected 0, got %u\n", style); + + hmenu_popup = GetSubMenu(hmenu_popup, 0); + ok(hmenu_popup != 0, "GetSubMenu returned 0 for submenu 0\n"); + style = get_menu_style(hmenu_popup); + ok(style == 0, "expected 0, got %u\n", style); + + /* Alt+E, Enter */ + trace("testing a popup menu command\n"); + flush_sequence(); + keybd_event(VK_MENU, 0, 0, 0); + keybd_event('E', 0, 0, 0); + keybd_event('E', 0, KEYEVENTF_KEYUP, 0); + keybd_event(VK_MENU, 0, KEYEVENTF_KEYUP, 0); + keybd_event(VK_RETURN, 0, 0, 0); + keybd_event(VK_RETURN, 0, KEYEVENTF_KEYUP, 0); + while (PeekMessage(&msg, 0, 0, 0, PM_REMOVE)) + { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + ok_sequence(wm_popup_menu_1, "popup menu command", FALSE); + + /* Alt+F, Right, Enter */ + trace("testing submenu of a popup menu command\n"); + flush_sequence(); + keybd_event(VK_MENU, 0, 0, 0); + keybd_event('F', 0, 0, 0); + keybd_event('F', 0, KEYEVENTF_KEYUP, 0); + keybd_event(VK_MENU, 0, KEYEVENTF_KEYUP, 0); + keybd_event(VK_RIGHT, 0, 0, 0); + keybd_event(VK_RIGHT, 0, KEYEVENTF_KEYUP, 0); + keybd_event(VK_RETURN, 0, 0, 0); + keybd_event(VK_RETURN, 0, KEYEVENTF_KEYUP, 0); + while (PeekMessage(&msg, 0, 0, 0, PM_REMOVE)) + { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + ok_sequence(wm_popup_menu_2, "submenu of a popup menu command", FALSE); + + set_menu_style(hmenu, 0); + style = get_menu_style(hmenu); + ok(style == 0, "expected MNS_NOTIFYBYPOS, got %u\n", style); + + hmenu_popup = GetSubMenu(hmenu, 0); + ok(hmenu_popup != 0, "GetSubMenu returned 0 for submenu 0\n"); + set_menu_style(hmenu_popup, MNS_NOTIFYBYPOS); + style = get_menu_style(hmenu_popup); + ok(style == MNS_NOTIFYBYPOS, "expected MNS_NOTIFYBYPOS, got %u\n", style); + + hmenu_popup = GetSubMenu(hmenu_popup, 0); + ok(hmenu_popup != 0, "GetSubMenu returned 0 for submenu 0\n"); + style = get_menu_style(hmenu_popup); + ok(style == 0, "expected 0, got %u\n", style); + + /* Alt+F, Right, Enter */ + trace("testing submenu of a popup menu command\n"); + flush_sequence(); + keybd_event(VK_MENU, 0, 0, 0); + keybd_event('F', 0, 0, 0); + keybd_event('F', 0, KEYEVENTF_KEYUP, 0); + keybd_event(VK_MENU, 0, KEYEVENTF_KEYUP, 0); + keybd_event(VK_RIGHT, 0, 0, 0); + keybd_event(VK_RIGHT, 0, KEYEVENTF_KEYUP, 0); + keybd_event(VK_RETURN, 0, 0, 0); + keybd_event(VK_RETURN, 0, KEYEVENTF_KEYUP, 0); + while (PeekMessage(&msg, 0, 0, 0, PM_REMOVE)) + { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + ok_sequence(wm_popup_menu_3, "submenu of a popup menu command", FALSE); + + DestroyWindow(hwnd); + DestroyMenu(hmenu); +} + START_TEST(msg) { BOOL ret; @@ -10523,6 +10791,7 @@ START_TEST(msg) test_nullCallback(); test_SetForegroundWindow(); test_dbcs_wm_char(); + test_menu_messages(); UnhookWindowsHookEx(hCBT_hook); if (pUnhookWinEvent) diff --git a/dlls/user32/tests/resource.rc b/dlls/user32/tests/resource.rc index 7da8a6c2d79..79c036cbdb0 100644 --- a/dlls/user32/tests/resource.rc +++ b/dlls/user32/tests/resource.rc @@ -165,13 +165,16 @@ FONT 8, "MS Shell Dlg" { POPUP "&File" { - MENUITEM "&New", 100 + POPUP "&New..." + { + MENUITEM "&New file", 100 + } MENUITEM "&Open", 101 MENUITEM "&Save", 102 MENUITEM SEPARATOR MENUITEM "E&xit", 103 } - POPUP "Edit" + POPUP "&Edit" { MENUITEM "&Undo", 200 MENUITEM SEPARATOR