From c67be4ceff6c7d6db301ea30f6ebea759a2c60bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herm=C3=A8s=20B=C3=A9lusca-Ma=C3=AFto?= Date: Thu, 5 Mar 2026 23:11:58 +0100 Subject: [PATCH] [ROSTESTS] Add an interactive "menuaccels" test to view window keyboard messages This test allows viewing the window keyboard messages (`WM_KEYDOWN/UP`, `WM_CHAR`, ...) that are sent by Win32k whenever the user presses keys, including what happens when Alt+Numpad combinations are typed in. The application shows the list of received messages in a format similar to that of Microsoft Spy++. --- modules/rostests/win32/user32/CMakeLists.txt | 1 + .../win32/user32/menuaccels/CMakeLists.txt | 6 + .../rostests/win32/user32/menuaccels/data.c | 317 +++++++++ .../win32/user32/menuaccels/menuaccels.c | 612 ++++++++++++++++++ .../win32/user32/menuaccels/menuaccels.ico | Bin 0 -> 25214 bytes .../win32/user32/menuaccels/menuaccels.rc | 116 ++++ .../win32/user32/menuaccels/resource.h | 47 ++ 7 files changed, 1099 insertions(+) create mode 100644 modules/rostests/win32/user32/menuaccels/CMakeLists.txt create mode 100644 modules/rostests/win32/user32/menuaccels/data.c create mode 100644 modules/rostests/win32/user32/menuaccels/menuaccels.c create mode 100644 modules/rostests/win32/user32/menuaccels/menuaccels.ico create mode 100644 modules/rostests/win32/user32/menuaccels/menuaccels.rc create mode 100644 modules/rostests/win32/user32/menuaccels/resource.h diff --git a/modules/rostests/win32/user32/CMakeLists.txt b/modules/rostests/win32/user32/CMakeLists.txt index be1aa50f51b..f86e696165d 100644 --- a/modules/rostests/win32/user32/CMakeLists.txt +++ b/modules/rostests/win32/user32/CMakeLists.txt @@ -1,5 +1,6 @@ add_subdirectory(biditext) add_subdirectory(editalign) +add_subdirectory(menuaccels) add_subdirectory(messagebox) add_subdirectory(paintdesktop) add_subdirectory(psmtest) diff --git a/modules/rostests/win32/user32/menuaccels/CMakeLists.txt b/modules/rostests/win32/user32/menuaccels/CMakeLists.txt new file mode 100644 index 00000000000..f87afc95342 --- /dev/null +++ b/modules/rostests/win32/user32/menuaccels/CMakeLists.txt @@ -0,0 +1,6 @@ + +add_rc_deps(menuaccels.rc ${CMAKE_CURRENT_SOURCE_DIR}/menuaccels.ico) +add_executable(menuaccels menuaccels.c menuaccels.rc) +set_module_type(menuaccels win32gui UNICODE) +add_importlibs(menuaccels user32 msvcrt kernel32) +add_rostests_file(TARGET menuaccels SUBDIR suppl) diff --git a/modules/rostests/win32/user32/menuaccels/data.c b/modules/rostests/win32/user32/menuaccels/data.c new file mode 100644 index 00000000000..3267ddfd488 --- /dev/null +++ b/modules/rostests/win32/user32/menuaccels/data.c @@ -0,0 +1,317 @@ +/* + * PROJECT: ReactOS Tests + * LICENSE: LGPL-2.0-or-later (https://spdx.org/licenses/LGPL-2.0-or-later) + * PURPOSE: Common data + * COPYRIGHT: Copyright 2026 Hermès Bélusca-Maïto + */ + +/* + * References: + * https://learn.microsoft.com/en-us/windows/win32/inputdev/virtual-key-codes + * https://bsakatu.net/doc/virtual-key-of-windows/ + */ +static const PCSTR VkNames[] = +{ +/* 0x00 */ + "VK_NONE", + "VK_LBUTTON", + "VK_RBUTTON", + "VK_CANCEL", + "VK_MBUTTON", +// #if (_WIN32_WINNT >= 0x0500) + "VK_XBUTTON1", + "VK_XBUTTON2", +// #endif /* _WIN32_WINNT >= 0x0500 */ + NULL, // Reserved + "VK_BACK", + "VK_TAB", + NULL, // Reserved + NULL, // Reserved + "VK_CLEAR", + "VK_RETURN", + NULL, // Unassigned + NULL, // Unassigned +/* 0x10 */ + "VK_SHIFT", + "VK_CONTROL", + "VK_MENU", + "VK_PAUSE", + "VK_CAPITAL", + "VK_KANA-VK_HANGUL", + "VK_IME_ON", + "VK_JUNJA", + "VK_FINAL", + "VK_HANJA-VK_KANJI", + "VK_IME_OFF", + "VK_ESCAPE", + "VK_CONVERT", + "VK_NONCONVERT", + "VK_ACCEPT", + "VK_MODECHANGE", +/* 0x20 */ + "VK_SPACE", + "VK_PRIOR", + "VK_NEXT", + "VK_END", + "VK_HOME", + "VK_LEFT", + "VK_UP", + "VK_RIGHT", + "VK_DOWN", + "VK_SELECT", + "VK_PRINT", + "VK_EXECUTE", + "VK_SNAPSHOT", + "VK_INSERT", + "VK_DELETE", + "VK_HELP", +/* 0x30 */ + /* VK_0 - VK_9 are the same as ASCII '0' - '9' (0x30 - 0x39) */ + "0", + "1", + "2", + "3", + "4", + "5", + "6", + "7", + "8", + "9", + NULL, // Undefined + NULL, // Undefined + NULL, // Undefined + NULL, // Undefined + NULL, // Undefined + NULL, // Undefined +/* 0x40 */ + NULL, // Undefined + /* VK_A - VK_Z are the same as ASCII 'A' - 'Z' (0x41 - 0x5A) */ + "A", + "B", + "C", + "D", + "E", + "F", + "G", + "H", + "I", + "J", + "K", + "L", + "M", + "N", + "O", +/* 0x50 */ + "P", + "Q", + "R", + "S", + "T", + "U", + "V", + "W", + "X", + "Y", + "Z", + "VK_LWIN", + "VK_RWIN", + "VK_APPS", + NULL, // Reserved + "VK_SLEEP", +/* 0x60 */ + "VK_NUMPAD0", + "VK_NUMPAD1", + "VK_NUMPAD2", + "VK_NUMPAD3", + "VK_NUMPAD4", + "VK_NUMPAD5", + "VK_NUMPAD6", + "VK_NUMPAD7", + "VK_NUMPAD8", + "VK_NUMPAD9", + "VK_MULTIPLY", + "VK_ADD", + "VK_SEPARATOR", + "VK_SUBTRACT", + "VK_DECIMAL", + "VK_DIVIDE", +/* 0x70 */ + "VK_F1", + "VK_F2", + "VK_F3", + "VK_F4", + "VK_F5", + "VK_F6", + "VK_F7", + "VK_F8", + "VK_F9", + "VK_F10", + "VK_F11", + "VK_F12", + "VK_F13", + "VK_F14", + "VK_F15", + "VK_F16", +/* 0x80 */ + "VK_F17", + "VK_F18", + "VK_F19", + "VK_F20", + "VK_F21", + "VK_F22", + "VK_F23", + "VK_F24", +// #if (_WIN32_WINNT >= 0x0604) + "VK_NAVIGATION_VIEW", // Reserved + "VK_NAVIGATION_MENU", // Reserved + "VK_NAVIGATION_UP", // Reserved + "VK_NAVIGATION_DOWN", // Reserved + "VK_NAVIGATION_LEFT", // Reserved + "VK_NAVIGATION_RIGHT", // Reserved + "VK_NAVIGATION_ACCEPT", // Reserved + "VK_NAVIGATION_CANCEL", // Reserved +// #endif /* _WIN32_WINNT >= 0x0604 */ +/* 0x90 */ + "VK_NUMLOCK", + "VK_SCROLL", + /* + * OEM specific + */ + /* NEC PC-9800 kbd definitions */ + // "VK_OEM_NEC_EQUAL", // '=' key on numpad // Same value as VK_OEM_FJ_JISHO + /* + * Fujitsu/OASYS kbd definitions + */ + "VK_OEM_FJ_JISHO", // 'Dictionary' key + "VK_OEM_FJ_MASSHOU", // 'Unregister word' key + "VK_OEM_FJ_TOUROKU", // 'Register word' key + "VK_OEM_FJ_LOYA", // 'Left OYAYUBI' key + "VK_OEM_FJ_ROYA", // 'Right OYAYUBI' key + NULL, // Unassigned + NULL, // Unassigned + NULL, // Unassigned + NULL, // Unassigned + NULL, // Unassigned + NULL, // Unassigned + NULL, // Unassigned + NULL, // Unassigned + NULL, // Unassigned +/* 0xA0 */ + "VK_LSHIFT", + "VK_RSHIFT", + "VK_LCONTROL", + "VK_RCONTROL", + "VK_LMENU", + "VK_RMENU", +// #if (_WIN32_WINNT >= 0x0500) + "VK_BROWSER_BACK", + "VK_BROWSER_FORWARD", + "VK_BROWSER_REFRESH", + "VK_BROWSER_STOP", + "VK_BROWSER_SEARCH", + "VK_BROWSER_FAVORITES", + "VK_BROWSER_HOME", + "VK_VOLUME_MUTE", + "VK_VOLUME_DOWN", + "VK_VOLUME_UP", +/* 0xB0 */ + "VK_MEDIA_NEXT_TRACK", + "VK_MEDIA_PREV_TRACK", + "VK_MEDIA_STOP", + "VK_MEDIA_PLAY_PAUSE", + "VK_LAUNCH_MAIL", + "VK_LAUNCH_MEDIA_SELECT", + "VK_LAUNCH_APP1", + "VK_LAUNCH_APP2", +// #endif /* _WIN32_WINNT >= 0x0500 */ + NULL, // Reserved + NULL, // Reserved + "VK_OEM_1", // ';:' for US + "VK_OEM_PLUS", // '+' any country + "VK_OEM_COMMA", // ',' any country + "VK_OEM_MINUS", // '-' any country + "VK_OEM_PERIOD", // '.' any country + "VK_OEM_2", // '/?' for US +/* 0xC0 */ + "VK_OEM_3", // '`~' for US + NULL, // Reserved + NULL, // Reserved +// #if (_WIN32_WINNT >= 0x0604) + "VK_GAMEPAD_A", + "VK_GAMEPAD_B", + "VK_GAMEPAD_X", + "VK_GAMEPAD_Y", + "VK_GAMEPAD_RIGHT_SHOULDER", + "VK_GAMEPAD_LEFT_SHOULDER", + "VK_GAMEPAD_LEFT_TRIGGER", + "VK_GAMEPAD_RIGHT_TRIGGER", + "VK_GAMEPAD_DPAD_UP", + "VK_GAMEPAD_DPAD_DOWN", + "VK_GAMEPAD_DPAD_LEFT", + "VK_GAMEPAD_DPAD_RIGHT", + "VK_GAMEPAD_MENU", +/* 0xD0 */ + "VK_GAMEPAD_VIEW", + "VK_GAMEPAD_LEFT_THUMBSTICK_BUTTON", + "VK_GAMEPAD_RIGHT_THUMBSTICK_BUTTON", + "VK_GAMEPAD_LEFT_THUMBSTICK_UP", + "VK_GAMEPAD_LEFT_THUMBSTICK_DOWN", + "VK_GAMEPAD_LEFT_THUMBSTICK_RIGHT", + "VK_GAMEPAD_LEFT_THUMBSTICK_LEFT", + "VK_GAMEPAD_RIGHT_THUMBSTICK_UP", + "VK_GAMEPAD_RIGHT_THUMBSTICK_DOWN", + "VK_GAMEPAD_RIGHT_THUMBSTICK_RIGHT", + "VK_GAMEPAD_RIGHT_THUMBSTICK_LEFT", +// #endif /* _WIN32_WINNT >= 0x0604 */ + "VK_OEM_4", // '[{' for US + "VK_OEM_5", // '\|' for US + "VK_OEM_6", // ']}' for US + "VK_OEM_7", // ''"' for US + "VK_OEM_8", +/* 0xE0 */ + NULL, // Reserved + "VK_OEM_AX", // 'AX' key on Japanese AX kbd // OEM specific + "VK_OEM_102", // "<>" or "\|" on RT 102-key kbd // OEM specific + "VK_ICO_HELP", // Help key on ICO // OEM specific + "VK_ICO_00", // 00 key on ICO // OEM specific +// #if (WINVER >= 0x0400) + "VK_PROCESSKEY", +// #endif /* WINVER >= 0x0400 */ + "VK_ICO_CLEAR", // OEM specific +// #if (_WIN32_WINNT >= 0x0500) + "VK_PACKET", +// #endif /* _WIN32_WINNT >= 0x0500 */ + NULL, // Unassigned + /* + * OEM specific + * Nokia/Ericsson definitions + */ + "VK_OEM_RESET", + "VK_OEM_JUMP", + "VK_OEM_PA1", + "VK_OEM_PA2", + "VK_OEM_PA3", + "VK_OEM_WSCTRL", + "VK_OEM_CUSEL", +/* 0xF0 */ + "VK_OEM_ATTN", + "VK_OEM_FINISH", + "VK_OEM_COPY", + "VK_OEM_AUTO", + "VK_OEM_ENLW", + "VK_OEM_BACKTAB", + /* END of OEM definitions */ + "VK_ATTN", + "VK_CRSEL", + "VK_EXSEL", + "VK_EREOF", + "VK_PLAY", + "VK_ZOOM", + "VK_NONAME", // Reserved + "VK_PA1", + "VK_OEM_CLEAR", + "VK_UNKNOWN" +}; +C_ASSERT(_countof(VkNames) == 0x100); + +/* EOF */ diff --git a/modules/rostests/win32/user32/menuaccels/menuaccels.c b/modules/rostests/win32/user32/menuaccels/menuaccels.c new file mode 100644 index 00000000000..c37d5f343f1 --- /dev/null +++ b/modules/rostests/win32/user32/menuaccels/menuaccels.c @@ -0,0 +1,612 @@ +/* + * PROJECT: ReactOS Tests + * LICENSE: LGPL-2.0-or-later (https://spdx.org/licenses/LGPL-2.0-or-later) + * PURPOSE: Tests the interaction between menus, accelerators, and Alt+Numpad keys + * COPYRIGHT: Copyright 2026 Hermès Bélusca-Maïto + */ + +/* HEADERS *******************************************************************/ + +/* C Headers */ +#include +#include + +/* PSDK Headers */ +#include +#include +#include + +#include "resource.h" + +/* GLOBALS *******************************************************************/ + +static HINSTANCE g_hInst; +static const PCWSTR szWindowClass = L"TESTAPP"; + +static HWND g_hEdit, g_hMsgDump; +static ATOM g_aHotKey1, g_aHotKey2; +static HHOOK g_hHook1, g_hHook2, g_hHook3; +static BOOL g_bShowEdit = TRUE; +static BOOL g_bXlatAccels = TRUE; + +#define EDIT_STYLE_WRAP (WS_CHILD | WS_VSCROLL | ES_AUTOVSCROLL | ES_MULTILINE | ES_NOHIDESEL) +#define EDIT_STYLE (EDIT_STYLE_WRAP | WS_HSCROLL | ES_AUTOHSCROLL) + +/* FUNCTIONS *****************************************************************/ + +LRESULT CALLBACK +HookProcCallWnd( + _In_ int nCode, + _In_ WPARAM wParam, + _In_ LPARAM lParam); + +LRESULT CALLBACK +HookProcGetMsg( + _In_ int nCode, + _In_ WPARAM wParam, + _In_ LPARAM lParam); + +LRESULT CALLBACK +HookProcMessage( + _In_ int nCode, + _In_ WPARAM wParam, + _In_ LPARAM lParam); + +LRESULT CALLBACK +WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); + +static ATOM +MyRegisterClass(_In_ HINSTANCE hInstance) +{ + WNDCLASSEXW wcex; + HICON hSmIcon, hBgIcon; + + hSmIcon = LoadImageW(hInstance, + MAKEINTRESOURCEW(IDI_TESTAPP), + IMAGE_ICON, + GetSystemMetrics(SM_CXSMICON), + GetSystemMetrics(SM_CYSMICON), + LR_SHARED); + + hBgIcon = LoadImageW(hInstance, + MAKEINTRESOURCEW(IDI_TESTAPP), + IMAGE_ICON, + GetSystemMetrics(SM_CXICON), + GetSystemMetrics(SM_CYICON), + LR_SHARED); + + wcex.cbSize = sizeof(wcex); + wcex.style = CS_HREDRAW | CS_VREDRAW; + wcex.lpfnWndProc = WndProc; + wcex.cbClsExtra = 0; + wcex.cbWndExtra = 0; + wcex.hInstance = hInstance; + wcex.hIcon = hBgIcon; + wcex.hCursor = LoadCursorW(NULL, IDC_ARROW); + wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); + wcex.lpszMenuName = MAKEINTRESOURCEW(IDC_TESTAPP); + wcex.lpszClassName = szWindowClass; + wcex.hIconSm = hSmIcon; + + return RegisterClassExW(&wcex); +} + +int APIENTRY +wWinMain( + _In_ HINSTANCE hInstance, + _In_ HINSTANCE hPrevInstance, + _In_ LPWSTR lpCmdLine, + _In_ int nCmdShow) +{ + HWND hWnd; + MSG msg; + HACCEL hAccelTable; + + UNREFERENCED_PARAMETER(hPrevInstance); + UNREFERENCED_PARAMETER(lpCmdLine); + + /* Register ourselves */ + if (!MyRegisterClass(hInstance)) + return FALSE; + g_hInst = hInstance; + + /* Create the main window and load the accelerators */ + hWnd = CreateWindowW(szWindowClass, L"MyTestApp", WS_OVERLAPPEDWINDOW, + CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, + NULL, NULL, hInstance, NULL); + if (!hWnd) + return FALSE; + + /* Show ourselves */ + ShowWindow(hWnd, nCmdShow); + UpdateWindow(hWnd); + + /* Set up the accelerators, hotkey, and window hooks */ + hAccelTable = LoadAcceleratorsW(hInstance, MAKEINTRESOURCEW(IDC_TESTAPP)); + if (!hAccelTable) + OutputDebugStringA("LoadAcceleratorsW() failed\n"); + + g_aHotKey1 = GlobalAddAtomW(L"TESTAPP Alt 4 Hotkey"); + if (!RegisterHotKey(NULL, g_aHotKey1, MOD_ALT, VK_NUMPAD4)) + OutputDebugStringA("RegisterHotKey() failed\n"); //DPRINT1("RegisterHotKey failed with %lu\n", GetLastError()); + + g_aHotKey2 = GlobalAddAtomW(L"TESTAPP Alt 5 Hotkey"); + if (!RegisterHotKey(hWnd, g_aHotKey2, MOD_ALT, VK_NUMPAD5)) + OutputDebugStringA("RegisterHotKey() failed\n"); //DPRINT1("RegisterHotKey failed with %lu\n", GetLastError()); + + g_hHook1 = SetWindowsHookExW(WH_CALLWNDPROC, HookProcCallWnd, NULL, GetCurrentThreadId()); + g_hHook2 = SetWindowsHookExW(WH_GETMESSAGE, HookProcGetMsg, NULL, GetCurrentThreadId()); + g_hHook3 = SetWindowsHookExW(WH_MSGFILTER, HookProcMessage, NULL, GetCurrentThreadId()); + + /* Pump the queue */ + while (GetMessageW(&msg, NULL, 0, 0)) + { + if ((msg.message == WM_HOTKEY) && (msg.wParam == g_aHotKey1)) + { + // if (LOWORD(msg.lParam) == MOD_ALT && HIWORD(msg.lParam) == VK_NUMPAD4) + PostMessageW(hWnd, WM_COMMAND, MAKEWPARAM(IDM_FOUR, 1), 0); + continue; + } + + if (!g_bXlatAccels || !TranslateAcceleratorW(hWnd, hAccelTable, &msg)) + { + TranslateMessage(&msg); + DispatchMessageW(&msg); + } + } + + /* Cleanup and return */ + UnhookWindowsHookEx(g_hHook3); + UnhookWindowsHookEx(g_hHook2); + UnhookWindowsHookEx(g_hHook1); + + UnregisterHotKey(NULL, g_aHotKey2); + GlobalDeleteAtom(g_aHotKey2); + UnregisterHotKey(NULL, g_aHotKey1); + GlobalDeleteAtom(g_aHotKey1); + + return (int)msg.wParam; +} + +static void +SetMenuString( + _In_ HMENU hMenu, + _In_ UINT uCommand, + _In_ LPCWSTR pszString) +{ + WCHAR szMenu[128]; + + if (IS_INTRESOURCE(pszString)) + { + LoadStringW(g_hInst, PtrToUlong(pszString), szMenu, _countof(szMenu)); + pszString = szMenu; + } + ModifyMenuW(hMenu, uCommand, MF_BYCOMMAND | MF_STRING, uCommand, pszString); +} + +static void +UpdateEditWnd(_In_ HWND hWndParent) +{ + /* Change the menu command string */ + SetMenuString(GetMenu(hWndParent), IDM_SHOWHIDEEDIT, + g_bShowEdit ? MAKEINTRESOURCEW(IDS_EDITHIDE) + : MAKEINTRESOURCEW(IDS_EDITSHOW)); + + /* Show or hide the editable edit control and set focus to it if needed */ + ShowWindow(g_hEdit, g_bShowEdit ? SW_SHOW : SW_HIDE); + if (g_bShowEdit) + SetFocus(g_hEdit); + + /* Re-arrange controls */ + PostMessageW(hWndParent, WM_SIZE, 0, 0); +} + +static void +UpdateAccelXlatMenu(_In_ HWND hWnd) +{ + /* Change the menu command string */ + SetMenuString(GetMenu(hWnd), IDM_ACCELXLAT, + g_bXlatAccels ? MAKEINTRESOURCEW(IDS_ACCELNOXLAT) + : MAKEINTRESOURCEW(IDS_ACCELXLAT)); +} + +static void +DoCreateEditChildren(_In_ HWND hWndParent) +{ + g_hEdit = CreateWindowW(/*WC_EDITW*/ L"Edit", L"", EDIT_STYLE_WRAP, + CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, + hWndParent, NULL, g_hInst, NULL); + SendMessageW(g_hEdit, EM_LIMITTEXT, 0, 0); + + g_hMsgDump = CreateWindowW(/*WC_EDITW*/ L"Edit", L"", EDIT_STYLE_WRAP | ES_READONLY, + CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, + hWndParent, NULL, g_hInst, NULL); + SendMessageW(g_hMsgDump, EM_LIMITTEXT, 0, 0); + + /* Finally shows new edit controls */ + ShowWindow(g_hMsgDump, SW_SHOW); + UpdateEditWnd(hWndParent); + + /* Re-arrange controls */ + PostMessageW(hWndParent, WM_SIZE, 0, 0); +} + + +static void +AppendTextLineA( + _In_ HWND hEdit, + _In_ PCSTR pszLine) +{ + DWORD l, r; + SendMessageW(hEdit, EM_GETSEL, (WPARAM)&l, (LPARAM)&r); + //SendMessageW(hEdit, EM_SETSEL, -1, -1); + SendMessageW(hEdit, EM_SETSEL, GetWindowTextLengthW(hEdit), -1); + SendMessageA(hEdit, EM_REPLACESEL, FALSE, (LPARAM)pszLine); + SendMessageW(hEdit, EM_SETSEL, l, r); +} + +static void dump_printf(const CHAR *fmt, ...) +{ + CHAR szText[512]; + int len; + + va_list va; + va_start(va, fmt); + len = _vsnprintf(szText, _countof(szText) - 2, fmt, va); + if (len < 0) + *szText = ANSI_NULL; + va_end(va); + + /* Ensure the line ends with CR-LF */ + len = min(len, _countof(szText) - 3); + szText[len + 0] = '\r'; + szText[len + 1] = '\n'; + szText[len + 2] = ANSI_NULL; + + /* Append the text line */ + AppendTextLineA(g_hMsgDump, szText); + //DbgPrint("TEST: %s\n", szText); + OutputDebugStringA(szText); +} +#define MSGDUMP_PRINTF dump_printf +//#include "msgdump.h" +#define MSGDUMP_PREFIX "" +#define MSGDUMP_API WINAPI + +/* For 'PCSTR VkNames[]' */ +#include "data.c" + +static int +GetVkName( + _In_ UINT vk, + _Out_writes_(cchBuff) PSTR pszBuffer, + _In_ SIZE_T cchBuff) +{ + PCSTR vkName; + + if (vk > 0xFF) + vk = 0xFF; // VK_UNKNOWN + vkName = VkNames[vk]; + + if (!vkName) + { + return _snprintf(pszBuffer, cchBuff, "%lX", vk); + } + else + { + if ((0x30 <= vk && vk <= 0x39) || (0x41 <= vk && vk <= 0x5A)) + return _snprintf(pszBuffer, cchBuff, "'%s'", vkName); + else + return _snprintf(pszBuffer, cchBuff, "%s", vkName); + } +} + +static __inline void MSGDUMP_API +MD_OnKey(_In_ CHAR Pfx, _In_ HWND hwnd, _In_ BOOL fDown, _In_ WPARAM wParam, _In_ LPARAM lParam) +{ + UINT vk = (UINT)wParam; + UINT cRepeat = (UINT)LOWORD(lParam); + USHORT flags = HIWORD(lParam); + UCHAR ScanCode = (flags & 0xFF); + + CHAR szVkName[100]; + GetVkName(vk, szVkName, _countof(szVkName)); + + if (fDown) + { + MSGDUMP_PRINTF("%p %c %sWM_KEYDOWN\tnVirtKey:%s cRepeat:%u ScanCode:%02X fExtended:%u fAltDown:%u fRepeat:%u fUp:%u [wParam:%08lX lParam:%08lX]", + hwnd, Pfx, MSGDUMP_PREFIX, szVkName, cRepeat, ScanCode, + !!(flags & KF_EXTENDED), !!(flags & KF_ALTDOWN), !!(flags & KF_REPEAT), !!(flags & KF_UP), + wParam, lParam); + } + else + { + MSGDUMP_PRINTF("%p %c %sWM_KEYUP\tnVirtKey:%s cRepeat:%u ScanCode:%02X fExtended:%u fAltDown:%u fRepeat:%u fUp:%u [wParam:%08lX lParam:%08lX]", + hwnd, Pfx, MSGDUMP_PREFIX, szVkName, cRepeat, ScanCode, + !!(flags & KF_EXTENDED), !!(flags & KF_ALTDOWN), !!(flags & KF_REPEAT), !!(flags & KF_UP), + wParam, lParam); + } +} + +static __inline void MSGDUMP_API +MD_OnChar(_In_ CHAR Pfx, _In_ HWND hwnd, _In_ WPARAM wParam, _In_ LPARAM lParam) +{ + WCHAR ch = (WCHAR)wParam; + UINT cRepeat = (UINT)LOWORD(lParam); + USHORT flags = HIWORD(lParam); + UCHAR ScanCode = (flags & 0xFF); + MSGDUMP_PRINTF("%p %c %sWM_CHAR\tchCharCode:'%04X' (%u) cRepeat:%u ScanCode:%02X fExtended:%u fAltDown:%u fRepeat:%u fUp:%u [wParam:%08lX lParam:%08lX]", + hwnd, Pfx, MSGDUMP_PREFIX, ch, ch, cRepeat, ScanCode, + !!(flags & KF_EXTENDED), !!(flags & KF_ALTDOWN), !!(flags & KF_REPEAT), !!(flags & KF_UP), + wParam, lParam); +} + +static __inline void MSGDUMP_API +MD_OnDeadChar(_In_ CHAR Pfx, _In_ HWND hwnd, _In_ WPARAM wParam, _In_ LPARAM lParam) +{ + WCHAR ch = (WCHAR)wParam; + UINT cRepeat = (UINT)LOWORD(lParam); + USHORT flags = HIWORD(lParam); + UCHAR ScanCode = (flags & 0xFF); + MSGDUMP_PRINTF("%p %c %sWM_DEADCHAR\tchCharCode:'%04X' (%u) cRepeat:%u ScanCode:%02X fExtended:%u fAltDown:%u fRepeat:%u fUp:%u [wParam:%08lX lParam:%08lX]", + hwnd, Pfx, MSGDUMP_PREFIX, ch, ch, cRepeat, ScanCode, + !!(flags & KF_EXTENDED), !!(flags & KF_ALTDOWN), !!(flags & KF_REPEAT), !!(flags & KF_UP), + wParam, lParam); +} + +static __inline void MSGDUMP_API +MD_OnSysKey(_In_ CHAR Pfx, _In_ HWND hwnd, _In_ BOOL fDown, _In_ WPARAM wParam, _In_ LPARAM lParam) +{ + UINT vk = (UINT)wParam; + UINT cRepeat = (UINT)LOWORD(lParam); + USHORT flags = HIWORD(lParam); + UCHAR ScanCode = (flags & 0xFF); + + CHAR szVkName[100]; + GetVkName(vk, szVkName, _countof(szVkName)); + + if (fDown) + { + MSGDUMP_PRINTF("%p %c %sWM_SYSKEYDOWN\tnVirtKey:%s cRepeat:%u ScanCode:%02X fExtended:%u fAltDown:%u fRepeat:%u fUp:%u [wParam:%08lX lParam:%08lX]", + hwnd, Pfx, MSGDUMP_PREFIX, szVkName, cRepeat, ScanCode, + !!(flags & KF_EXTENDED), !!(flags & KF_ALTDOWN), !!(flags & KF_REPEAT), !!(flags & KF_UP), + wParam, lParam); + } + else + { + MSGDUMP_PRINTF("%p %c %sWM_SYSKEYUP\tnVirtKey:%s cRepeat:%u ScanCode:%02X fExtended:%u fAltDown:%u fRepeat:%u fUp:%u [wParam:%08lX lParam:%08lX]", + hwnd, Pfx, MSGDUMP_PREFIX, szVkName, cRepeat, ScanCode, + !!(flags & KF_EXTENDED), !!(flags & KF_ALTDOWN), !!(flags & KF_REPEAT), !!(flags & KF_UP), + wParam, lParam); + } +} + +static __inline void MSGDUMP_API +MD_OnSysChar(_In_ CHAR Pfx, _In_ HWND hwnd, _In_ WPARAM wParam, _In_ LPARAM lParam) +{ + WCHAR ch = (WCHAR)wParam; + UINT cRepeat = (UINT)LOWORD(lParam); + USHORT flags = HIWORD(lParam); + UCHAR ScanCode = (flags & 0xFF); + MSGDUMP_PRINTF("%p %c %sWM_SYSCHAR\tchCharCode:'%04X' (%u) cRepeat:%u ScanCode:%02X fExtended:%u fAltDown:%u fRepeat:%u fUp:%u [wParam:%08lX lParam:%08lX]", + hwnd, Pfx, MSGDUMP_PREFIX, ch, ch, cRepeat, ScanCode, + !!(flags & KF_EXTENDED), !!(flags & KF_ALTDOWN), !!(flags & KF_REPEAT), !!(flags & KF_UP), + wParam, lParam); +} + +static __inline void MSGDUMP_API +MD_OnSysDeadChar(_In_ CHAR Pfx, _In_ HWND hwnd, _In_ WPARAM wParam, _In_ LPARAM lParam) +{ + WCHAR ch = (WCHAR)wParam; + UINT cRepeat = (UINT)LOWORD(lParam); + USHORT flags = HIWORD(lParam); + UCHAR ScanCode = (flags & 0xFF); + MSGDUMP_PRINTF("%p %c %sWM_SYSDEADCHAR\tchCharCode:'%04X' (%u) cRepeat:%u ScanCode:%02X fExtended:%u fAltDown:%u fRepeat:%u fUp:%u [wParam:%08lX lParam:%08lX]", + hwnd, Pfx, MSGDUMP_PREFIX, ch, ch, cRepeat, ScanCode, + !!(flags & KF_EXTENDED), !!(flags & KF_ALTDOWN), !!(flags & KF_REPEAT), !!(flags & KF_UP), + wParam, lParam); +} + +static __inline void MSGDUMP_API +MD_OnUniChar(_In_ CHAR Pfx, _In_ HWND hwnd, _In_ WPARAM wParam, _In_ LPARAM lParam) +{ + WCHAR ch = (WCHAR)wParam; + UINT cRepeat = (UINT)LOWORD(lParam); + USHORT flags = HIWORD(lParam); + UCHAR ScanCode = (flags & 0xFF); + MSGDUMP_PRINTF("%p %c %sWM_UNICHAR\tchCharCode:'%04X' (%u) cRepeat:%u ScanCode:%02X fExtended:%u fAltDown:%u fRepeat:%u fUp:%u [wParam:%08lX lParam:%08lX]", + hwnd, Pfx, MSGDUMP_PREFIX, ch, ch, cRepeat, ScanCode, + !!(flags & KF_EXTENDED), !!(flags & KF_ALTDOWN), !!(flags & KF_REPEAT), !!(flags & KF_UP), + wParam, lParam); +} + +static __inline void MSGDUMP_API +MD_OnHotKey(_In_ CHAR Pfx, _In_ HWND hwnd, _In_ WPARAM wParam, _In_ LPARAM lParam) +{ + int idHotKey = (int)wParam; + UINT fuModifiers = (UINT)LOWORD(lParam); + UINT vk = (UINT)HIWORD(lParam); + + CHAR szVkName[100]; + GetVkName(vk, szVkName, _countof(szVkName)); + // TODO: Convert fuModifiers to "human-readable" names. + + MSGDUMP_PRINTF("%p %c %sWM_HOTKEY\tidHotKey:%04X fuModifiers:%u nVirtKey:%s [wParam:%08lX lParam:%08lX]", + hwnd, Pfx, MSGDUMP_PREFIX, idHotKey, fuModifiers, szVkName, + wParam, lParam); +} + +static __inline LRESULT MSGDUMP_API +MD_msgdump(_In_ CHAR Pfx, _In_ HWND hwnd, _In_ UINT uMsg, _In_ WPARAM wParam, _In_ LPARAM lParam) +{ + switch (uMsg) + { + case WM_KEYDOWN: MD_OnKey(Pfx, hwnd, TRUE, wParam, lParam); break; + case WM_KEYUP: MD_OnKey(Pfx, hwnd, FALSE, wParam, lParam); break; + case WM_CHAR: MD_OnChar(Pfx, hwnd, wParam, lParam); break; + case WM_DEADCHAR: MD_OnDeadChar(Pfx, hwnd, wParam, lParam); break; + case WM_SYSKEYDOWN: MD_OnSysKey(Pfx, hwnd, TRUE, wParam, lParam); break; + case WM_SYSKEYUP: MD_OnSysKey(Pfx, hwnd, FALSE, wParam, lParam); break; + case WM_SYSCHAR: MD_OnSysChar(Pfx, hwnd, wParam, lParam); break; + case WM_SYSDEADCHAR: MD_OnSysDeadChar(Pfx, hwnd, wParam, lParam); break; + case WM_UNICHAR: MD_OnUniChar(Pfx, hwnd, wParam, lParam); break; + case WM_HOTKEY: MD_OnHotKey(Pfx, hwnd, wParam, lParam); break; + case WM_IME_CHAR: break; // TODO + case WM_IME_KEYDOWN: break; // TODO + case WM_IME_KEYUP: break; // TODO + } + return 0; +} + +LRESULT CALLBACK +HookProcCallWnd( + _In_ int nCode, + _In_ WPARAM wParam, + _In_ LPARAM lParam) +{ + PCWPSTRUCT pcwp; + + //if (nCode < 0) /* Do not process the message */ + // return CallNextHookEx(g_hHook1, nCode, wParam, lParam); + + pcwp = (PCWPSTRUCT)lParam; + MD_msgdump('C', pcwp->hwnd, pcwp->message, pcwp->wParam, pcwp->lParam); + + return CallNextHookEx(g_hHook1, nCode, wParam, lParam); +} + +LRESULT CALLBACK +HookProcGetMsg( + _In_ int nCode, + _In_ WPARAM wParam, + _In_ LPARAM lParam) +{ + PMSG pmsg; + + //if (nCode < 0) /* Do not process the message */ + // return CallNextHookEx(g_hHook2, nCode, wParam, lParam); + + pmsg = (PMSG)lParam; + MD_msgdump('G', pmsg->hwnd, pmsg->message, pmsg->wParam, pmsg->lParam); + + return CallNextHookEx(g_hHook2, nCode, wParam, lParam); +} + +LRESULT CALLBACK +HookProcMessage( + _In_ int nCode, + _In_ WPARAM wParam, + _In_ LPARAM lParam) +{ + PMSG pmsg; + + //if (nCode < 0) /* Do not process the message */ + // return CallNextHookEx(g_hHook3, nCode, wParam, lParam); + + pmsg = (PMSG)lParam; + MD_msgdump('M', pmsg->hwnd, pmsg->message, pmsg->wParam, pmsg->lParam); + + return CallNextHookEx(g_hHook3, nCode, wParam, lParam); +} + + +LRESULT CALLBACK +WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + // MD_msgdump(hWnd, uMsg, wParam, lParam); + switch (uMsg) + { + case WM_CREATE: + DoCreateEditChildren(hWnd); + UpdateAccelXlatMenu(hWnd); + break; + + case WM_DESTROY: + PostQuitMessage(0); + break; + + case WM_HOTKEY: + if (wParam == g_aHotKey1) // && LOWORD(lParam) == MOD_ALT && HIWORD(lParam) == VK_NUMPAD4 + PostMessageW(hWnd, WM_COMMAND, MAKEWPARAM(IDM_FOUR, 1), 0); + else if (wParam == g_aHotKey2) // && LOWORD(lParam) == MOD_ALT && HIWORD(lParam) == VK_NUMPAD5 + PostMessageW(hWnd, WM_COMMAND, MAKEWPARAM(IDM_FIVE, 1), 0); + break; + + case WM_COMMAND: + { + WORD wmId = LOWORD(wParam); + //WORD wmEvent = HIWORD(wParam); + switch (wmId) + { + case IDM_ONE: case IDM_TWO: case IDM_THREE: + case IDM_FOUR: case IDM_FIVE: + case IDM_THIRTEEN: case IDM_FOURTEEN: case IDM_FIFTEEN: + { + /* See `IDC_TESTAPP ACCELERATORS` */ + static const PCWSTR Messages[] = + {L"One (Alt '1' ASCII)", L"Two (Alt 2 VIRTKEY)", L"Three (Alt VK_NUMPAD3 VIRTKEY)", + L"Four (Alt VK_NUMPAD4 -- WM_HOTKEY thread)", L"Five (Alt VK_NUMPAD5 -- WM_HOTKEY hWnd)", + L"Thirteen (Alt 'D' ASCII)", L"Fourteen (Alt E VIRTKEY)", L"Fifteen (Alt F VIRTKEY)"}; + + if (IDM_ONE <= wmId && wmId <= IDM_FIVE) + wmId -= IDM_ONE; + else if (IDM_THIRTEEN <= wmId && wmId <= IDM_FIFTEEN) + wmId -= IDM_THIRTEEN - (IDM_FIVE - IDM_ONE + 1); + MessageBoxW(hWnd, Messages[wmId], L"Info", MB_OK); + break; + } + + case IDM_SHOWHIDEEDIT: + g_bShowEdit = !g_bShowEdit; + UpdateEditWnd(hWnd); + break; + + case IDM_ACCELXLAT: + g_bXlatAccels = !g_bXlatAccels; + UpdateAccelXlatMenu(hWnd); + break; + + case IDM_CLEARLOG: + SendMessageW(g_hMsgDump, WM_SETTEXT, 0, (LPARAM)L""); + break; + + case IDM_EXIT: + DestroyWindow(hWnd); + break; + default: + return DefWindowProcW(hWnd, uMsg, wParam, lParam); + } + break; + } + + case WM_SIZE: + { + RECT rc; + GetClientRect(hWnd, &rc); + if (g_bShowEdit) + { + MoveWindow(g_hEdit, 0, 0, rc.right, rc.bottom / 2, TRUE); + MoveWindow(g_hMsgDump, 0, rc.bottom / 2, rc.right, rc.bottom / 2, TRUE); + } + else + { + MoveWindow(g_hMsgDump, 0, 0, rc.right, rc.bottom, TRUE); + } + break; + } + + case WM_PAINT: + { + PAINTSTRUCT ps; + BeginPaint(hWnd, &ps); + EndPaint(hWnd, &ps); + break; + } + + default: + return DefWindowProcW(hWnd, uMsg, wParam, lParam); + } + return 0; +} + +/* EOF */ diff --git a/modules/rostests/win32/user32/menuaccels/menuaccels.ico b/modules/rostests/win32/user32/menuaccels/menuaccels.ico new file mode 100644 index 0000000000000000000000000000000000000000..c4005b83f4d6d393f0e609d51efc57838ec481bc GIT binary patch literal 25214 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 literal 0 HcmV?d00001 diff --git a/modules/rostests/win32/user32/menuaccels/menuaccels.rc b/modules/rostests/win32/user32/menuaccels/menuaccels.rc new file mode 100644 index 00000000000..28fcc50bb5c --- /dev/null +++ b/modules/rostests/win32/user32/menuaccels/menuaccels.rc @@ -0,0 +1,116 @@ +/* + * PROJECT: ReactOS Tests + * LICENSE: LGPL-2.0-or-later (https://spdx.org/licenses/LGPL-2.0-or-later) + * PURPOSE: Resources + * COPYRIGHT: Copyright 2026 Hermès Bélusca-Maïto + */ + +#include +#include +#include "resource.h" + +LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL + +#define REACTOS_STR_FILE_DESCRIPTION "ReactOS Menu & Accelerators Test" +#define REACTOS_STR_INTERNAL_NAME "menuaccels" +#define REACTOS_STR_ORIGINAL_FILENAME "menuaccels.exe" +#include + +IDI_TESTAPP ICON "menuaccels.ico" + +IDC_TESTAPP MENU +BEGIN + POPUP "Zero (&0)" + BEGIN + MENUITEM "", IDM_SHOWHIDEEDIT + MENUITEM "", IDM_ACCELXLAT + MENUITEM "&Clear Log", IDM_CLEARLOG + MENUITEM "&Quit", IDM_EXIT + END + POPUP "One (&1)" + BEGIN + MENUITEM "Alpha", ID_ONE_ALPHA + END + POPUP "Two (&2)" + BEGIN + MENUITEM "Bravo", ID_TWO_BRAVO + END + POPUP "Three (&3)" + BEGIN + MENUITEM "Charlie", ID_THREE_CHARLIE + END + POPUP "Four (&4)" + BEGIN + MENUITEM "Delta", ID_FOUR_DELTA + END + POPUP "Five (&5)" + BEGIN + MENUITEM "Echo", ID_FIVE_ECHO + END + POPUP "Six (&6)" + BEGIN + MENUITEM "Foxtrot", ID_SIX_FOXTROT + END + POPUP "Seven (&7)" + BEGIN + MENUITEM "Golf", ID_SEVEN_GOLF + END + POPUP "Eight (&8)" + BEGIN + MENUITEM "Hotel", ID_EIGHT_HOTEL + END + POPUP "Nine (&9)" + BEGIN + MENUITEM "India", ID_NINE_INDIA + END + POPUP "Ten (&A)" + BEGIN + MENUITEM "Juliet", ID_TEN_JULIET + END + POPUP "Eleven (&B)" + BEGIN + MENUITEM "Kilo", ID_ELEVEN_KILO + END + POPUP "Twelve (&C)" + BEGIN + MENUITEM "Lima", ID_TWELVE_LIMA + END + POPUP "Thirteen (&D)" + BEGIN + MENUITEM "Mike", ID_THIRTEEN_MIKE + END + POPUP "Fourteen (&E)" + BEGIN + MENUITEM "November", ID_FOURTEEN_NOVEMBER + END + POPUP "Fifteen (&F)" + BEGIN + MENUITEM "Oscar", ID_FIFTEEN_OSCAR + END + POPUP "Plus (&+)" + BEGIN + MENUITEM "Papa", ID_PLUS_PAPA + END + POPUP "Dot (&.)" + BEGIN + MENUITEM "Quebec", ID_DOT_QUEBEC + END +END + +IDC_TESTAPP ACCELERATORS +BEGIN + "1", IDM_ONE, ASCII, ALT, NOINVERT + "2", IDM_TWO, VIRTKEY, ALT, NOINVERT + VK_NUMPAD3, IDM_THREE, VIRTKEY, ALT, NOINVERT + "D", IDM_THIRTEEN, ASCII, ALT, NOINVERT + "E", IDM_FOURTEEN, VIRTKEY, ALT, NOINVERT + "F", IDM_FIFTEEN, VIRTKEY, ALT, NOINVERT +END + +STRINGTABLE +BEGIN + IDS_EDITSHOW "&Show Edit" + IDS_EDITHIDE "&Hide Edit" + IDS_ACCELXLAT "&Translate accelerators" + IDS_ACCELNOXLAT "&Don't translate accelerators" +END diff --git a/modules/rostests/win32/user32/menuaccels/resource.h b/modules/rostests/win32/user32/menuaccels/resource.h new file mode 100644 index 00000000000..990b0c23a7d --- /dev/null +++ b/modules/rostests/win32/user32/menuaccels/resource.h @@ -0,0 +1,47 @@ +/* + * PROJECT: ReactOS Tests + * LICENSE: LGPL-2.0-or-later (https://spdx.org/licenses/LGPL-2.0-or-later) + * PURPOSE: Resources header + * COPYRIGHT: Copyright 2026 Hermès Bélusca-Maïto + */ + +#define IDC_STATIC (-1) + +#define IDI_TESTAPP 100 +#define IDC_TESTAPP 101 + +#define IDS_EDITSHOW 110 +#define IDS_EDITHIDE 111 +#define IDS_ACCELXLAT 112 +#define IDS_ACCELNOXLAT 113 + +#define IDM_SHOWHIDEEDIT 200 +#define IDM_ACCELXLAT 201 +#define IDM_CLEARLOG 202 +#define IDM_EXIT 203 +#define IDM_ONE 204 +#define IDM_TWO 205 +#define IDM_THREE 206 +#define IDM_FOUR 207 +#define IDM_FIVE 208 +#define IDM_THIRTEEN 209 +#define IDM_FOURTEEN 210 +#define IDM_FIFTEEN 211 + +#define ID_ONE_ALPHA 220 +#define ID_TWO_BRAVO 221 +#define ID_THREE_CHARLIE 222 +#define ID_FOUR_DELTA 223 +#define ID_FIVE_ECHO 224 +#define ID_SIX_FOXTROT 225 +#define ID_SEVEN_GOLF 226 +#define ID_EIGHT_HOTEL 227 +#define ID_NINE_INDIA 228 +#define ID_TEN_JULIET 229 +#define ID_ELEVEN_KILO 230 +#define ID_TWELVE_LIMA 231 +#define ID_THIRTEEN_MIKE 232 +#define ID_FOURTEEN_NOVEMBER 233 +#define ID_FIFTEEN_OSCAR 234 +#define ID_PLUS_PAPA 235 +#define ID_DOT_QUEBEC 236