diff --git a/dlls/user/tests/msg.c b/dlls/user/tests/msg.c index 99d70ad3b4bc01c9ac6f8b27ac9befb2c8d92071..cee0179302d5497584e066cdca673445f92aa228 100644 --- a/dlls/user/tests/msg.c +++ b/dlls/user/tests/msg.c @@ -5495,6 +5495,80 @@ static void test_DestroyWindow(void) ok(!IsWindow(child4), "child4 still exists"); } + +static const struct message WmDispatchPaint[] = { + { WM_NCPAINT, sent }, + { WM_GETTEXT, sent|defwinproc|optional }, + { WM_GETTEXT, sent|defwinproc|optional }, + { WM_ERASEBKGND, sent }, + { 0 } +}; + +static LRESULT WINAPI DispatchMessageCheckProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + if (message == WM_PAINT) + { + trace( "Got WM_PAINT, ignoring\n" ); + return 0; + } + return MsgCheckProcA( hwnd, message, wParam, lParam ); +} + +static void test_DispatchMessage(void) +{ + RECT rect; + MSG msg; + int count; + HWND hwnd = CreateWindowA( "TestWindowClass", NULL, WS_OVERLAPPEDWINDOW, + 100, 100, 200, 200, 0, 0, 0, NULL); + ShowWindow( hwnd, SW_SHOW ); + UpdateWindow( hwnd ); + while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg ); + flush_sequence(); + SetWindowLongPtrA( hwnd, GWL_WNDPROC, (LONG_PTR)DispatchMessageCheckProc ); + + SetRect( &rect, -5, -5, 5, 5 ); + RedrawWindow( hwnd, &rect, 0, RDW_INVALIDATE|RDW_ERASE|RDW_FRAME ); + count = 0; + while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) + { + if (msg.message != WM_PAINT) DispatchMessage( &msg ); + else + { + flush_sequence(); + DispatchMessage( &msg ); + /* DispatchMessage will send WM_NCPAINT if non client area is still invalid after WM_PAINT */ + if (!count) ok_sequence( WmDispatchPaint, "WmDispatchPaint", FALSE ); + else ok_sequence( WmEmptySeq, "WmEmpty", FALSE ); + if (++count > 10) break; + } + } + ok( msg.message == WM_PAINT && count > 10, "WM_PAINT messages stopped\n" ); + + trace("now without DispatchMessage\n"); + flush_sequence(); + RedrawWindow( hwnd, &rect, 0, RDW_INVALIDATE|RDW_ERASE|RDW_FRAME ); + count = 0; + while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) + { + if (msg.message != WM_PAINT) DispatchMessage( &msg ); + else + { + HRGN hrgn = CreateRectRgn( 0, 0, 0, 0 ); + flush_sequence(); + /* this will send WM_NCCPAINT just like DispatchMessage does */ + GetUpdateRgn( hwnd, hrgn, TRUE ); + ok_sequence( WmDispatchPaint, "WmDispatchPaint", FALSE ); + DeleteObject( hrgn ); + GetClientRect( hwnd, &rect ); + ValidateRect( hwnd, &rect ); /* this will stop WM_PAINTs */ + ok( !count, "Got multiple WM_PAINTs\n" ); + if (++count > 10) break; + } + } +} + + START_TEST(msg) { HMODULE user32 = GetModuleHandleA("user32.dll"); @@ -5544,6 +5618,7 @@ START_TEST(msg) test_timers(); test_set_hook(); test_DestroyWindow(); + test_DispatchMessage(); UnhookWindowsHookEx(hCBT_hook); if (pUnhookWinEvent) diff --git a/windows/message.c b/windows/message.c index 65bd970a4f5ca7e94dccf7e8e4ac55b80b5cd6ee..e03b69b80e687433c9b4d85da731eff7ac0feef3 100644 --- a/windows/message.c +++ b/windows/message.c @@ -795,6 +795,13 @@ LONG WINAPI DispatchMessageA( const MSG* msg ) SPY_ExitMessage( SPY_RESULT_OK, msg->hwnd, msg->message, retval, msg->wParam, msg->lParam ); + if (msg->message == WM_PAINT) + { + /* send a WM_NCPAINT and WM_ERASEBKGND if the non-client area is still invalid */ + HRGN hrgn = CreateRectRgn( 0, 0, 0, 0 ); + GetUpdateRgn( msg->hwnd, hrgn, TRUE ); + DeleteObject( hrgn ); + } return retval; } @@ -866,6 +873,13 @@ LONG WINAPI DispatchMessageW( const MSG* msg ) SPY_ExitMessage( SPY_RESULT_OK, msg->hwnd, msg->message, retval, msg->wParam, msg->lParam ); + if (msg->message == WM_PAINT) + { + /* send a WM_NCPAINT and WM_ERASEBKGND if the non-client area is still invalid */ + HRGN hrgn = CreateRectRgn( 0, 0, 0, 0 ); + GetUpdateRgn( msg->hwnd, hrgn, TRUE ); + DeleteObject( hrgn ); + } return retval; }