ScrollWindowEx fix with tests

Rein Klazes wijn at wanadoo.nl
Tue Feb 8 06:12:14 CST 2005


Hi,

This fixes the endless RedrawWindow looping regression in Xnews. The
looping bug may still be there, this fix addresses the RDW_ERASENOW flag
that was wrongly passed to RedrawWindow.

Contrary to what MSDN documentation suggests, ScrollWindowEx does not
send WM_ERASEBKGND message itself, it merely sets the eraseflag.

One question: the tests show that ScrollWindowEx in windows manages to
move child windows without the WM_POSCHANGING and WM_POSCHANGED
messages, instead it sends in some, but not all, cases a WM_MOVE
message. That does not seem to be possible with SetWindowPos and
friends, how should this be implemented?

Changelog:
	windows		: scroll.c
	dlls/user/tests	: msg.c

	ScrollWindowEx when called with the SW_ERASE flag does not
	send a WM_ERASEBKGND message, it just sets the erase flag.
	With some tests that show this behavior.
  
Rein.	  
-------------- next part --------------
--- wine/windows/scroll.c	2004-12-09 19:08:50.000000000 +0100
+++ mywine/windows/scroll.c	2005-02-08 12:01:57.000000000 +0100
@@ -75,6 +75,7 @@ INT WINAPI ScrollWindowEx( HWND hwnd, IN
     INT   retVal = NULLREGION;
     BOOL  bOwnRgn = TRUE;
     BOOL  bUpdate = (rcUpdate || hrgnUpdate || flags & (SW_INVALIDATE | SW_ERASE));
+    int rdw_flags;
     HRGN  hrgnTemp;
     HDC   hDC;
     RECT  rc, cliprc;
@@ -84,6 +85,11 @@ INT WINAPI ScrollWindowEx( HWND hwnd, IN
     TRACE( "%p, %d,%d hrgnUpdate=%p rcUpdate = %p %s %04x\n",
            hwnd, dx, dy, hrgnUpdate, rcUpdate, wine_dbgstr_rect(rect), flags );
     TRACE( "clipRect = %s\n", wine_dbgstr_rect(clipRect));
+    if( flags & ~( SW_SCROLLCHILDREN | SW_INVALIDATE | SW_ERASE))
+        FIXME("some flags (%04x) are unhandled\n", flags);
+
+    rdw_flags = (flags & SW_ERASE) && (flags & SW_INVALIDATE) ?
+                                RDW_INVALIDATE | RDW_ERASE  : RDW_INVALIDATE ;
 
     if (!WIN_IsWindowDrawable( hwnd, TRUE )) return ERROR;
     hwnd = WIN_GetFullHandle( hwnd );
@@ -109,7 +115,7 @@ INT WINAPI ScrollWindowEx( HWND hwnd, IN
             ReleaseDC( hwnd, hDC );
 
             if (!bUpdate)
-                RedrawWindow( hwnd, NULL, hrgnUpdate, RDW_INVALIDATE | RDW_ERASE );
+                RedrawWindow( hwnd, NULL, hrgnUpdate, rdw_flags);
         }
 
         /* Take into account the fact that some damage may have occurred during
@@ -121,7 +127,7 @@ INT WINAPI ScrollWindowEx( HWND hwnd, IN
             HRGN hrgnClip = CreateRectRgnIndirect(&cliprc);
             OffsetRgn( hrgnTemp, dx, dy );
             CombineRgn( hrgnTemp, hrgnTemp, hrgnClip, RGN_AND );
-            RedrawWindow( hwnd, NULL, hrgnTemp, RDW_INVALIDATE | RDW_ERASE );
+            RedrawWindow( hwnd, NULL, hrgnTemp, rdw_flags);
             DeleteObject( hrgnClip );
         }
         DeleteObject( hrgnTemp );
@@ -153,8 +159,7 @@ INT WINAPI ScrollWindowEx( HWND hwnd, IN
     }
 
     if( flags & (SW_INVALIDATE | SW_ERASE) )
-        RedrawWindow( hwnd, NULL, hrgnUpdate, RDW_INVALIDATE | RDW_ERASE |
-                      ((flags & SW_ERASE) ? RDW_ERASENOW : 0) |
+        RedrawWindow( hwnd, NULL, hrgnUpdate, rdw_flags |
                       ((flags & SW_SCROLLCHILDREN) ? RDW_ALLCHILDREN : 0 ) );
 
     if( hwndCaret ) {
--- wine/dlls/user/tests/msg.c	2005-01-28 17:10:14.000000000 +0100
+++ mywine/dlls/user/tests/msg.c	2005-02-08 11:59:01.000000000 +0100
@@ -5222,6 +5222,72 @@ static void test_set_hook(void)
 	"unexpected error %ld\n", GetLastError());
 }
 
+static const struct message ScrollWindowPaint1[] = {
+    { WM_PAINT, sent },
+    { WM_ERASEBKGND, sent|beginpaint },
+    { 0 }
+};
+
+static const struct message ScrollWindowPaint2[] = {
+    { WM_PAINT, sent },
+    { 0 }
+};
+
+static void test_scrollwindowex(void)
+{
+    HWND hwnd, hchild;
+    RECT rect={0,0,130,130};
+    MSG msg;
+
+    hwnd = CreateWindowExA(0, "TestWindowClass", "Test Scroll",
+            WS_VISIBLE|WS_OVERLAPPEDWINDOW,
+            100, 100, 200, 200, 0, 0, 0, NULL);
+    ok (hwnd != 0, "Failed to create overlapped window\n");
+    hchild = CreateWindowExA(0, "TestWindowClass", "Test child", 
+            WS_VISIBLE|WS_CAPTION|WS_CHILD,
+            10, 10, 150, 150, hwnd, 0, 0, NULL);
+    ok (hchild != 0, "Failed to create child\n");
+    UpdateWindow(hwnd);
+    while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
+    flush_sequence();
+
+    /* scroll without the child window */
+    trace("start scroll\n");
+    ScrollWindowEx( hwnd, 10, 10, &rect, NULL, NULL, NULL,
+            SW_ERASE|SW_INVALIDATE);
+    ok_sequence(WmEmptySeq, "ScrollWindowEx\n", 0);
+    trace("end scroll\n");
+    flush_sequence();
+    while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
+    ok_sequence(ScrollWindowPaint1, "ScrollWindowEx\n", 0);
+
+    /* Now without the SW_ERASE flag */
+    trace("start scroll\n");
+    ScrollWindowEx( hwnd, 10, 10, &rect, NULL, NULL, NULL, SW_INVALIDATE);
+    ok_sequence(WmEmptySeq, "ScrollWindowEx\n", 0);
+    trace("end scroll\n");
+    flush_sequence();
+    while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
+    ok_sequence(ScrollWindowPaint2, "ScrollWindowEx\n", 0);
+
+    /* now scroll the child window as well */
+    trace("start scroll\n");
+    ScrollWindowEx( hwnd, 10, 10, &rect, NULL, NULL, NULL,
+            SW_SCROLLCHILDREN|SW_ERASE|SW_INVALIDATE);
+    todo_wine { /* wine sends WM_POSCHANGING, WM_POSCHANGED messages */
+                /* windows sometimes a WM_MOVE */
+        ok_sequence(WmEmptySeq, "ScrollWindowEx\n", 0);
+    }
+    trace("end scroll\n");
+    flush_sequence();
+    while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
+    ok_sequence(ScrollWindowPaint1, "ScrollWindowEx\n", 0);
+
+    ok(DestroyWindow(hchild), "failed to destroy window\n");
+    ok(DestroyWindow(hwnd), "failed to destroy window\n");
+    flush_sequence();
+}
+
 START_TEST(msg)
 {
     HMODULE user32 = GetModuleHandleA("user32.dll");
@@ -5258,6 +5324,7 @@ START_TEST(msg)
     hCBT_hook = SetWindowsHookExA(WH_CBT, cbt_hook_proc, 0, GetCurrentThreadId());
     assert(hCBT_hook);
 
+    test_scrollwindowex();
     test_messages();
     test_mdi_messages();
     test_button_messages();


More information about the wine-patches mailing list