From: Zhiyi Zhang zzhang@codeweavers.com
--- dlls/user32/tests/msg.c | 114 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 114 insertions(+)
diff --git a/dlls/user32/tests/msg.c b/dlls/user32/tests/msg.c index a5f7318dffd..d99059c23f8 100644 --- a/dlls/user32/tests/msg.c +++ b/dlls/user32/tests/msg.c @@ -11338,6 +11338,42 @@ static LRESULT WINAPI WmCopyDataProcA(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp) return DefWindowProcA(hwnd,msg,wp,lp); }
+static LRESULT WINAPI WmPrintProcA(HWND hwnd, UINT message, WPARAM wp, LPARAM lp) +{ + static LONG defwndproc_counter = 0; + struct recvd_message msg; + LRESULT lr; + + msg.hwnd = hwnd; + msg.message = message; + msg.flags = sent | wparam | lparam; + if (defwndproc_counter) + msg.flags |= defwinproc; + msg.wParam = wp; + msg.lParam = lp; + msg.descr = "WmPrintProcA"; + add_message(&msg); + + switch (message) + { + case WM_PRINT: + { + static RECT rect = {0, 0, 1, 1}; + HBRUSH brush; + + brush = CreateSolidBrush(RGB(0xff, 0, 0)); + FillRect((HDC)wp, &rect, brush); + DeleteObject(brush); + return 0; + } + } + + defwndproc_counter++; + lr = DefWindowProcA(hwnd, message, wp, lp); + defwndproc_counter--; + return lr; +} + static void register_classes(void) { WNDCLASSA cls; @@ -11387,6 +11423,10 @@ static void register_classes(void) cls.lpszClassName = "WmCopyDataWindowClass"; register_class(&cls);
+ cls.lpfnWndProc = WmPrintProcA; + cls.lpszClassName = "WmPrintClass"; + register_class(&cls); + cls.style = CS_NOCLOSE; cls.lpszClassName = "NoCloseWindowClass"; register_class(&cls); @@ -21103,6 +21143,79 @@ static void test_WM_COPYDATA(char **argv) CloseHandle(pi.hThread); }
+static const struct message wm_print_prf_children[] = +{ + { WM_PRINT, sent|lparam, 0, PRF_NONCLIENT|PRF_CLIENT|PRF_ERASEBKGND|PRF_CHILDREN }, + { 0 } +}; + +static void test_defwinproc_wm_print(void) +{ + HWND hwnd, child; + COLORREF color; + LRESULT lr; + HDC hdc; + + hwnd = CreateWindowA("SimpleWindowClass", "test_defwinproc_wm_print", WS_POPUP, 0, + 0, 100, 100, 0, 0, 0, NULL); + ok(!!hwnd, "CreateWindowA failed, error %lu.\n", GetLastError()); + child = CreateWindowA("WmPrintClass", "test_defwinproc_wm_print_child", WS_VISIBLE | WS_CHILD, + 50, 50, 50, 50, hwnd, 0, 0, NULL); + ok(!!child, "CreateWindowA failed, error %lu.\n", GetLastError()); + + hdc = GetDC(hwnd); + + /* Check the return code when no flags are specified */ + lr = DefWindowProcA(hwnd, WM_PRINT, (WPARAM)hdc, 0); + todo_wine + ok(lr == 1, "Got unexpected lr %Id.\n", lr); + + /* Check the return code when PRF_CHECKVISIBLE is specified and the window is invisible */ + lr = DefWindowProcA(hwnd, WM_PRINT, (WPARAM)hdc, PRF_CHECKVISIBLE); + ok(lr == 0, "Got unexpected lr %Id.\n", lr); + + ShowWindow(hwnd, SW_SHOWNORMAL); + flush_events(); + flush_sequence(); + + /* Check the return code when PRF_CHECKVISIBLE is specified and the window is visible */ + lr = DefWindowProcA(hwnd, WM_PRINT, (WPARAM)hdc, PRF_CHECKVISIBLE); + todo_wine + ok(lr == 1, "Got unexpected lr %Id.\n", lr); + + /* Check the return code when PRF_ERASEBKGND is specified */ + lr = DefWindowProcA(hwnd, WM_PRINT, (WPARAM)hdc, PRF_ERASEBKGND); + todo_wine + ok(lr == 1, "Got unexpected lr %Id.\n", lr); + + /* Check the return code when PRF_CLIENT is specified */ + lr = DefWindowProcA(hwnd, WM_PRINT, (WPARAM)hdc, PRF_CLIENT); + todo_wine + ok(lr == 1, "Got unexpected lr %Id.\n", lr); + + /* PRF_CHILDREN needs to be used with PRF_CLIENT */ + lr = DefWindowProcA(hwnd, WM_PRINT, (WPARAM)hdc, PRF_CHILDREN); + todo_wine + ok(lr == 1, "Got unexpected lr %Id.\n", lr); + color = GetPixel(hdc, 50, 50); + ok(color == RGB(0xff, 0xff, 0xff), "Got unexpected color %#lx.\n", color); + ok_sequence(WmEmptySeq, "DefWindowProc WM_PRINT PRF_CHILDREN", FALSE); + flush_sequence(); + + /* PRF_CHILDREN | PRF_CLIENT */ + lr = DefWindowProcA(hwnd, WM_PRINT, (WPARAM)hdc, PRF_CHILDREN | PRF_CLIENT); + todo_wine + ok(lr == 1, "Got unexpected lr %Id.\n", lr); + color = GetPixel(hdc, 50, 50); + todo_wine + ok(color == RGB(0xff, 0, 0), "Got unexpected color %#lx.\n", color); + ok_sequence(wm_print_prf_children, "DefWindowProc WM_PRINT with PRF_CHILDREN | PRF_CLIENT", TRUE); + flush_sequence(); + + ReleaseDC(hwnd, hdc); + DestroyWindow(hwnd); +} + START_TEST(msg) { char **test_argv; @@ -21221,6 +21334,7 @@ START_TEST(msg) test_dbcs_wm_char(); test_unicode_wm_char(); test_defwinproc(); + test_defwinproc_wm_print(); test_desktop_winproc(); test_clipboard_viewers(); test_keyflags();
From: Zhiyi Zhang zzhang@codeweavers.com
--- dlls/user32/tests/msg.c | 6 ------ dlls/win32u/defwnd.c | 1 + 2 files changed, 1 insertion(+), 6 deletions(-)
diff --git a/dlls/user32/tests/msg.c b/dlls/user32/tests/msg.c index d99059c23f8..9b4c1e88148 100644 --- a/dlls/user32/tests/msg.c +++ b/dlls/user32/tests/msg.c @@ -21167,7 +21167,6 @@ static void test_defwinproc_wm_print(void)
/* Check the return code when no flags are specified */ lr = DefWindowProcA(hwnd, WM_PRINT, (WPARAM)hdc, 0); - todo_wine ok(lr == 1, "Got unexpected lr %Id.\n", lr);
/* Check the return code when PRF_CHECKVISIBLE is specified and the window is invisible */ @@ -21180,22 +21179,18 @@ static void test_defwinproc_wm_print(void)
/* Check the return code when PRF_CHECKVISIBLE is specified and the window is visible */ lr = DefWindowProcA(hwnd, WM_PRINT, (WPARAM)hdc, PRF_CHECKVISIBLE); - todo_wine ok(lr == 1, "Got unexpected lr %Id.\n", lr);
/* Check the return code when PRF_ERASEBKGND is specified */ lr = DefWindowProcA(hwnd, WM_PRINT, (WPARAM)hdc, PRF_ERASEBKGND); - todo_wine ok(lr == 1, "Got unexpected lr %Id.\n", lr);
/* Check the return code when PRF_CLIENT is specified */ lr = DefWindowProcA(hwnd, WM_PRINT, (WPARAM)hdc, PRF_CLIENT); - todo_wine ok(lr == 1, "Got unexpected lr %Id.\n", lr);
/* PRF_CHILDREN needs to be used with PRF_CLIENT */ lr = DefWindowProcA(hwnd, WM_PRINT, (WPARAM)hdc, PRF_CHILDREN); - todo_wine ok(lr == 1, "Got unexpected lr %Id.\n", lr); color = GetPixel(hdc, 50, 50); ok(color == RGB(0xff, 0xff, 0xff), "Got unexpected color %#lx.\n", color); @@ -21204,7 +21199,6 @@ static void test_defwinproc_wm_print(void)
/* PRF_CHILDREN | PRF_CLIENT */ lr = DefWindowProcA(hwnd, WM_PRINT, (WPARAM)hdc, PRF_CHILDREN | PRF_CLIENT); - todo_wine ok(lr == 1, "Got unexpected lr %Id.\n", lr); color = GetPixel(hdc, 50, 50); todo_wine diff --git a/dlls/win32u/defwnd.c b/dlls/win32u/defwnd.c index 4246b5d7653..27bc76e1886 100644 --- a/dlls/win32u/defwnd.c +++ b/dlls/win32u/defwnd.c @@ -2829,6 +2829,7 @@ LRESULT default_window_proc( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam,
case WM_PRINT: if ((lparam & PRF_CHECKVISIBLE) && !is_window_visible ( hwnd )) break; + result = 1;
if (lparam & (PRF_CHILDREN | PRF_OWNED | PRF_NONCLIENT)) WARN( "WM_PRINT message with unsupported lparam %lx\n", lparam );
From: Zhiyi Zhang zzhang@codeweavers.com
--- dlls/user32/tests/msg.c | 3 +-- dlls/win32u/dc.c | 13 +++++++++++++ dlls/win32u/defwnd.c | 32 ++++++++++++++++++++++++++++++-- dlls/win32u/ntgdi_private.h | 1 + 4 files changed, 45 insertions(+), 4 deletions(-)
diff --git a/dlls/user32/tests/msg.c b/dlls/user32/tests/msg.c index 9b4c1e88148..ab41011c03c 100644 --- a/dlls/user32/tests/msg.c +++ b/dlls/user32/tests/msg.c @@ -21201,9 +21201,8 @@ static void test_defwinproc_wm_print(void) lr = DefWindowProcA(hwnd, WM_PRINT, (WPARAM)hdc, PRF_CHILDREN | PRF_CLIENT); ok(lr == 1, "Got unexpected lr %Id.\n", lr); color = GetPixel(hdc, 50, 50); - todo_wine ok(color == RGB(0xff, 0, 0), "Got unexpected color %#lx.\n", color); - ok_sequence(wm_print_prf_children, "DefWindowProc WM_PRINT with PRF_CHILDREN | PRF_CLIENT", TRUE); + ok_sequence(wm_print_prf_children, "DefWindowProc WM_PRINT with PRF_CHILDREN | PRF_CLIENT", FALSE); flush_sequence();
ReleaseDC(hwnd, hdc); diff --git a/dlls/win32u/dc.c b/dlls/win32u/dc.c index 16092141163..94946d9ad23 100644 --- a/dlls/win32u/dc.c +++ b/dlls/win32u/dc.c @@ -1095,6 +1095,19 @@ BOOL WINAPI NtGdiSetBrushOrg( HDC hdc, INT x, INT y, POINT *oldorg ) }
+BOOL offset_viewport_org( HDC hdc, INT x, INT y, POINT *point ) +{ + DC *dc; + + if (!(dc = get_dc_ptr( hdc ))) return FALSE; + if (point) *point = dc->attr->vport_org; + dc->attr->vport_org.x += x; + dc->attr->vport_org.y += y; + release_dc_ptr( dc ); + return NtGdiComputeXformCoefficients( hdc ); +} + + BOOL set_viewport_org( HDC hdc, INT x, INT y, POINT *point ) { DC *dc; diff --git a/dlls/win32u/defwnd.c b/dlls/win32u/defwnd.c index 27bc76e1886..d8bd8e8637b 100644 --- a/dlls/win32u/defwnd.c +++ b/dlls/win32u/defwnd.c @@ -2831,11 +2831,39 @@ LRESULT default_window_proc( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam, if ((lparam & PRF_CHECKVISIBLE) && !is_window_visible ( hwnd )) break; result = 1;
- if (lparam & (PRF_CHILDREN | PRF_OWNED | PRF_NONCLIENT)) + if (lparam & (PRF_OWNED | PRF_NONCLIENT)) WARN( "WM_PRINT message with unsupported lparam %lx\n", lparam );
if (lparam & PRF_ERASEBKGND) send_message( hwnd, WM_ERASEBKGND, wparam, 0 ); - if (lparam & PRF_CLIENT) send_message(hwnd, WM_PRINTCLIENT, wparam, lparam ); + if (lparam & PRF_CLIENT) + { + send_message( hwnd, WM_PRINTCLIENT, wparam, lparam ); + + if (lparam & PRF_CHILDREN) + { + HWND *list, *child; + POINT org; + RECT rect; + UINT dpi; + + if ((list = list_window_children( hwnd ))) + { + for (child = list; *child; child++) + { + if (!is_window_visible( *child )) + continue; + + dpi = NtUserGetDpiForWindow( *child ); + NtUserGetClientRect( *child, &rect, dpi ); + NtUserMapWindowPoints( *child, hwnd, (POINT *)&rect, 2, dpi ); + offset_viewport_org( (HDC)wparam, rect.left, rect.top, &org ); + send_message( *child, WM_PRINT, wparam, PRF_NONCLIENT | PRF_CLIENT | PRF_ERASEBKGND | PRF_CHILDREN ); + set_viewport_org( (HDC)wparam, org.x, org.y, NULL ); + } + free( list ); + } + } + } break;
case WM_APPCOMMAND: diff --git a/dlls/win32u/ntgdi_private.h b/dlls/win32u/ntgdi_private.h index 78b3ad89796..ba61a7369b5 100644 --- a/dlls/win32u/ntgdi_private.h +++ b/dlls/win32u/ntgdi_private.h @@ -185,6 +185,7 @@ extern struct dce *get_dc_dce( HDC hdc ); extern void set_dc_dce( HDC hdc, struct dce *dce ); extern WORD set_dce_flags( HDC hdc, WORD flags ); extern DWORD set_stretch_blt_mode( HDC hdc, DWORD mode ); +extern BOOL offset_viewport_org( HDC hdc, INT x, INT y, POINT *point ); extern BOOL set_viewport_org( HDC hdc, INT x, INT y, POINT *point ); extern void DC_InitDC( DC * dc ); extern void DC_UpdateXforms( DC * dc );