Something went wrong. Try again.
Reactos
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343/* * PROJECT: ReactOS API tests * LICENSE: LGPL-2.1+ (https://spdx.org/licenses/LGPL-2.1+) * PURPOSE: Tests for TrackPopupMenuEx * COPYRIGHT: Copyright 2025 Katayama Hirofumi MZ <katayama.hirofumi.mz@gmail.com> */
#include "precomp.h"#include <versionhelpers.h>
#define CLASSNAME L"TrackPopupMenuEx tests"#define MENUCLASS L"#32768"
#define VALID_TPM_FLAGS ( \ TPM_LAYOUTRTL | TPM_NOANIMATION | TPM_VERNEGANIMATION | TPM_VERPOSANIMATION | \ TPM_HORNEGANIMATION | TPM_HORPOSANIMATION | TPM_RETURNCMD | \ TPM_NONOTIFY | TPM_VERTICAL | TPM_BOTTOMALIGN | TPM_VCENTERALIGN | \ TPM_RIGHTALIGN | TPM_CENTERALIGN | TPM_RIGHTBUTTON | TPM_RECURSE \)
#ifndef TPM_WORKAREA#define TPM_WORKAREA 0x10000#endif
static VOIDTEST_InvalidFlags(VOID){ HWND hwnd = GetDesktopWindow(); HMENU hMenu = CreatePopupMenu(); BOOL ret;
ret = AppendMenuW(hMenu, MF_STRING, 100, L"(Dummy)"); ok_int(ret, TRUE);
INT iBit; UINT uFlags; for (iBit = 0; iBit < sizeof(DWORD) * CHAR_BIT; ++iBit) { uFlags = (1 << iBit); if (uFlags & ~VALID_TPM_FLAGS) { SetLastError(0xBEEFCAFE); ret = TrackPopupMenuEx(hMenu, uFlags, 0, 0, hwnd, NULL); ok_int(ret, FALSE); if (uFlags == TPM_WORKAREA && IsWindows7OrGreater()) ok_err(ERROR_INVALID_PARAMETER); else ok_err(ERROR_INVALID_FLAGS); } }
DestroyMenu(hMenu);}
static VOIDTEST_InvalidSize(VOID){ HWND hwnd = GetDesktopWindow(); HMENU hMenu = CreatePopupMenu(); TPMPARAMS params; UINT uFlags = TPM_RIGHTBUTTON; BOOL ret;
ZeroMemory(¶ms, sizeof(params));
ret = AppendMenuW(hMenu, MF_STRING, 100, L"(Dummy)"); ok_int(ret, TRUE);
SetLastError(0xBEEFCAFE); params.cbSize = 0; ret = TrackPopupMenuEx(hMenu, uFlags, 0, 0, hwnd, ¶ms); ok_int(ret, FALSE); ok_err(ERROR_INVALID_PARAMETER);
SetLastError(0xBEEFCAFE); params.cbSize = sizeof(params) - 1; ret = TrackPopupMenuEx(hMenu, uFlags, 0, 0, hwnd, ¶ms); ok_int(ret, FALSE); ok_err(ERROR_INVALID_PARAMETER);
SetLastError(0xBEEFCAFE); params.cbSize = sizeof(params) + 1; ret = TrackPopupMenuEx(hMenu, uFlags, 0, 0, hwnd, ¶ms); ok_int(ret, FALSE); ok_err(ERROR_INVALID_PARAMETER);
DestroyMenu(hMenu);}
#define DELAY 100#define INTERVAL 300
typedef enum tagAUTO_CLICK{ AUTO_LEFT_CLICK, AUTO_RIGHT_CLICK, AUTO_LEFT_DOUBLE_CLICK, AUTO_RIGHT_DOUBLE_CLICK,} AUTO_CLICK;
typedef enum tagAUTO_KEY{ AUTO_KEY_DOWN, AUTO_KEY_UP, AUTO_KEY_DOWN_UP,} AUTO_KEY;
static VOIDAutoKey(AUTO_KEY type, UINT vKey){ if (type == AUTO_KEY_DOWN_UP) { AutoKey(AUTO_KEY_DOWN, vKey); AutoKey(AUTO_KEY_UP, vKey); return; }
INPUT input; ZeroMemory(&input, sizeof(input));
input.type = INPUT_KEYBOARD; input.ki.wVk = vKey; input.ki.dwFlags = ((type == AUTO_KEY_UP) ? KEYEVENTF_KEYUP : 0); SendInput(1, &input, sizeof(INPUT)); Sleep(DELAY);}
static VOIDAutoClick(AUTO_CLICK type, INT x, INT y){ INPUT input; ZeroMemory(&input, sizeof(input));
INT nScreenWidth = GetSystemMetrics(SM_CXSCREEN) - 1; INT nScreenHeight = GetSystemMetrics(SM_CYSCREEN) - 1;
input.type = INPUT_MOUSE; input.mi.dx = (LONG)(x * (65535.0f / nScreenWidth)); input.mi.dy = (LONG)(y * (65535.0f / nScreenHeight)); input.mi.dwFlags = MOUSEEVENTF_MOVE | MOUSEEVENTF_ABSOLUTE; SendInput(1, &input, sizeof(INPUT)); Sleep(DELAY);
input.mi.dx = input.mi.dy = 0;
INT i, count = 1; switch (type) { case AUTO_LEFT_DOUBLE_CLICK: count = 2; // FALL THROUGH case AUTO_LEFT_CLICK: { for (i = 0; i < count; ++i) { input.mi.dwFlags = MOUSEEVENTF_LEFTDOWN; SendInput(1, &input, sizeof(INPUT)); Sleep(DELAY);
input.mi.dwFlags = MOUSEEVENTF_LEFTUP; SendInput(1, &input, sizeof(INPUT)); Sleep(DELAY); } break; } case AUTO_RIGHT_DOUBLE_CLICK: count = 2; // FALL THROUGH case AUTO_RIGHT_CLICK: { for (i = 0; i < count; ++i) { input.mi.dwFlags = MOUSEEVENTF_RIGHTDOWN; SendInput(1, &input, sizeof(INPUT)); Sleep(DELAY);
input.mi.dwFlags = MOUSEEVENTF_RIGHTUP; SendInput(1, &input, sizeof(INPUT)); Sleep(DELAY); } break; } }}
static POINTCenterPoint(const RECT *prc){ POINT pt = { (prc->left + prc->right) / 2, (prc->top + prc->bottom) / 2 }; return pt;}
typedef struct tagCOUNTMENUWND{ INT nMenuCount;} COUNTMENUWND, *PCOUNTMENUWND;
static BOOL CALLBACKCountMenuWndProc(HWND hwnd, LPARAM lParam){ if (!IsWindowVisible(hwnd)) return TRUE;
WCHAR szClass[64]; GetClassNameW(hwnd, szClass, _countof(szClass)); if (lstrcmpiW(szClass, MENUCLASS) != 0) return TRUE;
PCOUNTMENUWND pData = (PCOUNTMENUWND)lParam; pData->nMenuCount += 1; return TRUE;}
static INTCountMenuWnds(VOID){ COUNTMENUWND data = { 0 }; EnumWindows(CountMenuWndProc, (LPARAM)&data); return data.nMenuCount;}
static DWORD WINAPITEST_Tracking_ThreadFunc(LPVOID arg){ HWND hwnd = (HWND)arg;
ok_int(CountMenuWnds(), 0);
RECT rc; GetWindowRect(hwnd, &rc); POINT pt = CenterPoint(&rc);
AutoClick(AUTO_RIGHT_CLICK, pt.x, pt.y); Sleep(INTERVAL);
ok_int(CountMenuWnds(), 1);
AutoKey(AUTO_KEY_DOWN_UP, VK_DOWN); Sleep(INTERVAL);
ok_int(CountMenuWnds(), 1);
AutoKey(AUTO_KEY_DOWN_UP, VK_RETURN); Sleep(INTERVAL);
ok_int(CountMenuWnds(), 0);
PostMessageW(hwnd, WM_CLOSE, 0, 0); return 0;}
static VOIDOnRButtonDown(HWND hwnd){ SetForegroundWindow(hwnd);
POINT pt; GetCursorPos(&pt);
HMENU hMenu = CreatePopupMenu(); BOOL ret = AppendMenuW(hMenu, MF_STRING, 100, L"(Dummy)"); ok_int(ret, TRUE);
UINT uFlags = TPM_RIGHTBUTTON | TPM_RETURNCMD; INT nCmdID = (INT)TrackPopupMenuEx(hMenu, uFlags, pt.x, pt.y, hwnd, NULL);
ok_int(nCmdID, 100);
DestroyMenu(hMenu);}
static LRESULT CALLBACKWindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam){ switch (uMsg) { case WM_CREATE: return 0; case WM_RBUTTONDOWN: OnRButtonDown(hwnd); break; case WM_DESTROY: PostQuitMessage(0); break; default: return DefWindowProcW(hwnd, uMsg, wParam, lParam); } return 0;}
static VOIDTEST_Tracking(VOID){ HINSTANCE hInstance = GetModuleHandleW(NULL);;
WNDCLASSW wc = { 0, WindowProc }; wc.hInstance = hInstance; wc.hIcon = LoadIcon(NULL, IDI_APPLICATION); wc.hCursor = LoadCursor(NULL, IDC_ARROW); wc.hbrBackground = (HBRUSH)UlongToHandle(COLOR_3DFACE + 1); wc.lpszClassName = CLASSNAME; if (!RegisterClassW(&wc)) { skip("RegisterClassW failed\n"); return; }
DWORD style = WS_OVERLAPPEDWINDOW; HWND hwnd = CreateWindowW(CLASSNAME, CLASSNAME, style, 0, 0, 320, 200, NULL, NULL, hInstance, NULL); if (!hwnd) { skip("CreateWindowW failed\n"); return; }
ShowWindow(hwnd, SW_SHOWNORMAL); UpdateWindow(hwnd);
HANDLE hThread = CreateThread(NULL, 0, TEST_Tracking_ThreadFunc, hwnd, 0, NULL); if (!hThread) { skip("CreateThread failed\n"); DestroyWindow(hwnd); return; } CloseHandle(hThread);
MSG msg; while (GetMessageW(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessageW(&msg); }}
START_TEST(TrackPopupMenuEx){ TEST_InvalidFlags(); TEST_InvalidSize(); TEST_Tracking();}