diff --git a/dlls/user32/tests/msg.c b/dlls/user32/tests/msg.c index f1236cf6e0d..5f10a89ec29 100644 --- a/dlls/user32/tests/msg.c +++ b/dlls/user32/tests/msg.c @@ -10440,6 +10440,124 @@ done: flush_events(); } +static void test_PeekMessage3(void) +{ + HWND hwnd; + BOOL ret; + MSG msg; + + hwnd = CreateWindowA("TestWindowClass", "PeekMessage3", WS_OVERLAPPEDWINDOW, + 10, 10, 800, 800, NULL, NULL, NULL, NULL); + ok(hwnd != NULL, "expected hwnd != NULL\n"); + flush_events(); + + /* GetMessage() and PeekMessage(..., PM_REMOVE) should prefer messages which + * were already seen. */ + + SetTimer(hwnd, 1, 0, NULL); + while (!PeekMessageA(&msg, NULL, 0, 0, PM_NOREMOVE)); + ok(msg.message == WM_TIMER, "msg.message = %u instead of WM_TIMER\n", msg.message); + PostMessageA(hwnd, WM_USER, 0, 0); + ret = PeekMessageA(&msg, NULL, 0, 0, PM_NOREMOVE); + todo_wine + ok(ret && msg.message == WM_TIMER, "msg.message = %u instead of WM_TIMER\n", msg.message); + ret = GetMessageA(&msg, NULL, 0, 0); + todo_wine + ok(ret && msg.message == WM_TIMER, "msg.message = %u instead of WM_TIMER\n", msg.message); + ret = GetMessageA(&msg, NULL, 0, 0); + todo_wine + ok(ret && msg.message == WM_USER, "msg.message = %u instead of WM_USER\n", msg.message); + ret = PeekMessageA(&msg, NULL, 0, 0, 0); + ok(!ret, "expected PeekMessage to return FALSE, got %u\n", ret); + + SetTimer(hwnd, 1, 0, NULL); + while (!PeekMessageA(&msg, NULL, 0, 0, PM_NOREMOVE)); + ok(msg.message == WM_TIMER, "msg.message = %u instead of WM_TIMER\n", msg.message); + PostMessageA(hwnd, WM_USER, 0, 0); + ret = PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE); + todo_wine + ok(ret && msg.message == WM_TIMER, "msg.message = %u instead of WM_TIMER\n", msg.message); + ret = PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE); + todo_wine + ok(ret && msg.message == WM_USER, "msg.message = %u instead of WM_USER\n", msg.message); + ret = PeekMessageA(&msg, NULL, 0, 0, 0); + ok(!ret, "expected PeekMessage to return FALSE, got %u\n", ret); + + /* It doesn't matter if a message range is specified or not. */ + + SetTimer(hwnd, 1, 0, NULL); + while (!PeekMessageA(&msg, NULL, WM_TIMER, WM_TIMER, PM_NOREMOVE)); + ok(msg.message == WM_TIMER, "msg.message = %u instead of WM_TIMER\n", msg.message); + PostMessageA(hwnd, WM_USER, 0, 0); + ret = GetMessageA(&msg, NULL, 0, 0); + todo_wine + ok(ret && msg.message == WM_TIMER, "msg.message = %u instead of WM_TIMER\n", msg.message); + ret = GetMessageA(&msg, NULL, 0, 0); + todo_wine + ok(ret && msg.message == WM_USER, "msg.message = %u instead of WM_USER\n", msg.message); + ret = PeekMessageA(&msg, NULL, 0, 0, 0); + ok(!ret, "expected PeekMessage to return FALSE, got %u\n", ret); + + /* But not if the post messages were added before the PeekMessage() call. */ + + PostMessageA(hwnd, WM_USER, 0, 0); + SetTimer(hwnd, 1, 0, NULL); + while (!PeekMessageA(&msg, NULL, WM_TIMER, WM_TIMER, PM_NOREMOVE)); + ok(msg.message == WM_TIMER, "msg.message = %u instead of WM_TIMER\n", msg.message); + ret = GetMessageA(&msg, NULL, 0, 0); + ok(ret && msg.message == WM_USER, "msg.message = %u instead of WM_USER\n", msg.message); + ret = GetMessageA(&msg, NULL, 0, 0); + ok(ret && msg.message == WM_TIMER, "msg.message = %u instead of WM_TIMER\n", msg.message); + ret = PeekMessageA(&msg, NULL, 0, 0, 0); + ok(!ret, "expected PeekMessage to return FALSE, got %u\n", ret); + + /* More complicated test with multiple messages. */ + + PostMessageA(hwnd, WM_USER, 0, 0); + SetTimer(hwnd, 1, 0, NULL); + while (!PeekMessageA(&msg, NULL, WM_TIMER, WM_TIMER, PM_NOREMOVE)); + ok(msg.message == WM_TIMER, "msg.message = %u instead of WM_TIMER\n", msg.message); + PostMessageA(hwnd, WM_USER + 1, 0, 0); + ret = GetMessageA(&msg, NULL, 0, 0); + ok(ret && msg.message == WM_USER, "msg.message = %u instead of WM_USER\n", msg.message); + ret = GetMessageA(&msg, NULL, 0, 0); + todo_wine + ok(ret && msg.message == WM_TIMER, "msg.message = %u instead of WM_TIMER\n", msg.message); + ret = GetMessageA(&msg, NULL, 0, 0); + todo_wine + ok(ret && msg.message == WM_USER + 1, "msg.message = %u instead of WM_USER + 1\n", msg.message); + ret = PeekMessageA(&msg, NULL, 0, 0, 0); + ok(!ret, "expected PeekMessage to return FALSE, got %u\n", ret); + + /* Also works for posted messages, but the situation is a bit different, + * because both messages are in the same queue. */ + + PostMessageA(hwnd, WM_TIMER, 0, 0); + while (!PeekMessageA(&msg, NULL, WM_TIMER, WM_TIMER, PM_NOREMOVE)); + ok(msg.message == WM_TIMER, "msg.message = %u instead of WM_TIMER\n", msg.message); + PostMessageA(hwnd, WM_USER, 0, 0); + ret = GetMessageA(&msg, NULL, 0, 0); + ok(ret && msg.message == WM_TIMER, "msg.message = %u instead of WM_TIMER\n", msg.message); + ret = GetMessageA(&msg, NULL, 0, 0); + ok(ret && msg.message == WM_USER, "msg.message = %u instead of WM_USER\n", msg.message); + ret = PeekMessageA(&msg, NULL, 0, 0, 0); + ok(!ret, "expected PeekMessage to return FALSE, got %u\n", ret); + + PostMessageA(hwnd, WM_USER, 0, 0); + PostMessageA(hwnd, WM_TIMER, 0, 0); + while (!PeekMessageA(&msg, NULL, WM_TIMER, WM_TIMER, PM_NOREMOVE)); + ok(msg.message == WM_TIMER, "msg.message = %u instead of WM_TIMER\n", msg.message); + ret = GetMessageA(&msg, NULL, 0, 0); + ok(ret && msg.message == WM_USER, "msg.message = %u instead of WM_USER\n", msg.message); + ret = GetMessageA(&msg, NULL, 0, 0); + ok(ret && msg.message == WM_TIMER, "msg.message = %u instead of WM_TIMER\n", msg.message); + ret = PeekMessageA(&msg, NULL, 0, 0, 0); + ok(!ret, "expected PeekMessage to return FALSE, got %u\n", ret); + + DestroyWindow(hwnd); + flush_events(); +} + static INT_PTR CALLBACK wm_quit_dlg_proc(HWND hwnd, UINT message, WPARAM wp, LPARAM lp) { struct recvd_message msg; @@ -14563,6 +14681,7 @@ START_TEST(msg) test_ShowWindow(); test_PeekMessage(); test_PeekMessage2(); + test_PeekMessage3(); test_WaitForInputIdle( test_argv[0] ); test_scrollwindowex(); test_messages();