ScrollWindow fix for windows with WS_CLIPCHILDREN style, with tests - version 2
Rein Klazes
wijn at wanadoo.nl
Wed Mar 30 12:38:57 CST 2005
On 29 Mar 2005 21:03:27 +0200, you wrote:
> Rein Klazes <wijn at wanadoo.nl> writes:
>
> > windows : scroll.c
> > dlls/user/tests : win.c
> >
> > If ScrollWindowEx is called with SW_SCROLLCHILDREN flags for a window
> > with a WS_CLIPCHILDREN style, then do not use the DCX_USESTYLE flag
> > option to get a DC for this window. With a couple of regression tests.
>
> DCX_USESTYLE has other effects, is it really correct to disable them
> all? And if so, wouldn't it be better to never use DCX_USESTYLE?
Close inspection today shows that you were correct to be concerned, my
patch relies on a problem with GetDCEx(): it looks like the
DCX_CLIPSIBLINGS flag is always active.
You can see this by changing the GetDC( hwnd1) in test_scrollvalidate()
to GetDCEx( hwnd1, 0, DCX_CACHE). Under Windows this makes all the tests
depending on the WS_CLIPSIBLINGS fail, under Wine those tests still
succeed.
I cannot use DCX_USESTYLE because there appears not to be something like
a DCX_NOCLIPCHILDREN flag. So here is the next attempt, using the
meaning of DCX_USESTYLE except where I do not need it.
Changelog:
windows : scroll.c
dlls/user/tests : win.c
If ScrollWindowEx do not use the DCX_USESTYLE to get a DC. Instead
calculate DCX_CLIPSIBLINGS, DCX_PARENTCLIP and DCX_CLIPCHILDREN. The
DCX_CLIPCHILDREN is not used when ScrollWindowEx is called with a
SW_SCROLLCHILDREN flag. With a couple of regression tests.
Rein.
-------------- next part --------------
--- wine/windows/scroll.c 2005-03-25 20:54:05.000000000 +0100
+++ mywine/windows/scroll.c 2005-03-30 20:25:57.000000000 +0200
@@ -104,10 +104,17 @@ INT WINAPI ScrollWindowEx( HWND hwnd, IN
else if( bUpdate ) hrgnUpdate = CreateRectRgn( 0, 0, 0, 0 );
if( !IsRectEmpty(&cliprc) && (dx || dy)) {
+ DWORD dcxflags = DCX_CACHE;
+ DWORD style = GetWindowLongW( hwnd, GWL_STYLE );
caretrc = rc;
hwndCaret = fix_caret(hwnd, &caretrc, flags);
- hDC = GetDCEx( hwnd, 0, DCX_CACHE | DCX_USESTYLE );
+ if( style & WS_CLIPSIBLINGS) dcxflags |= DCX_CLIPSIBLINGS;
+ if( GetClassLongW( hwnd, GCL_STYLE ) & CS_PARENTDC)
+ dcxflags |= DCX_PARENTCLIP;
+ if( !(flags & SW_SCROLLCHILDREN) && (style & WS_CLIPCHILDREN))
+ dcxflags |= DCX_CLIPCHILDREN;
+ hDC = GetDCEx( hwnd, 0, dcxflags);
if (hDC)
{
ScrollDC( hDC, dx, dy, &rc, &cliprc, hrgnUpdate, rcUpdate );
--- wine/dlls/user/tests/win.c 2005-03-26 08:11:50.000000000 +0100
+++ mywine/dlls/user/tests/win.c 2005-03-30 20:02:17.000000000 +0200
@@ -2603,12 +2603,14 @@ void test_scrollvalidate( HWND parent)
/* create two overlapping child windows. The visual region
* of hwnd1 is clipped by the overlapping part of
* hwnd2 because of the WS_CLIPSIBLING style */
- HWND hwnd2 = CreateWindowExA(0, "static", NULL,
- WS_CHILD| WS_VISIBLE | WS_CLIPSIBLINGS | WS_BORDER ,
- 75, 30, 100, 100, parent, 0, 0, NULL);
- HWND hwnd1 = CreateWindowExA(0, "static", NULL,
- WS_CHILD| WS_VISIBLE | WS_CLIPSIBLINGS | WS_BORDER ,
- 25, 50, 100, 100, parent, 0, 0, NULL);
+ HWND hwnd1, hwnd2;
+
+ hwnd2 = CreateWindowExA(0, "static", NULL,
+ WS_CHILD| WS_VISIBLE | WS_CLIPSIBLINGS | WS_BORDER ,
+ 75, 30, 100, 100, parent, 0, 0, NULL);
+ hwnd1 = CreateWindowExA(0, "static", NULL,
+ WS_CHILD| WS_VISIBLE | WS_CLIPSIBLINGS | WS_BORDER ,
+ 25, 50, 100, 100, parent, 0, 0, NULL);
ShowWindow( parent, SW_SHOW);
UpdateWindow( parent);
GetClientRect( hwnd1, &rc);
@@ -2642,6 +2644,63 @@ void test_scrollvalidate( HWND parent)
trace("update rect is %ld,%ld - %ld,%ld\n",
rcu.left,rcu.top,rcu.right,rcu.bottom);
ReleaseDC( hwnd1, hdc);
+
+ /* now test ScrollWindowEx with a combination of
+ * WS_CLIPCHILDREN style and SW_SCROLLCHILDREN flag */
+ /* make hwnd2 the child of hwnd1 */
+ DestroyWindow( hwnd2);
+ hwnd2 = CreateWindowExA(0, "static", NULL,
+ WS_CHILD| WS_VISIBLE | WS_BORDER ,
+ 50, 50, 100, 100, hwnd1, 0, 0, NULL);
+ SetWindowLong( hwnd1, GWL_STYLE, GetWindowLong( hwnd1, GWL_STYLE) & ~WS_CLIPSIBLINGS);
+ GetClientRect( hwnd1, &rc);
+ cliprc=rc;
+
+ /* WS_CLIPCHILDREN and SW_SCROLLCHILDREN */
+ SetWindowLong( hwnd1, GWL_STYLE, GetWindowLong( hwnd1, GWL_STYLE) | WS_CLIPCHILDREN );
+ ValidateRect( hwnd1, NULL);
+ ValidateRect( hwnd2, NULL);
+ ScrollWindowEx( hwnd1, -10, -10, &rc, &cliprc, hrgn, &rcu,
+ SW_SCROLLCHILDREN | SW_INVALIDATE);
+ if (winetest_debug > 0) dump_region(hrgn);
+ exprgn = CreateRectRgn( 88,0,98,88);
+ tmprgn = CreateRectRgn( 0,88,98,98);
+ CombineRgn( exprgn, exprgn, tmprgn, RGN_OR);
+ ok( EqualRgn( exprgn, hrgn), "wrong update region\n");
+
+ /* SW_SCROLLCHILDREN */
+ SetWindowLong( hwnd1, GWL_STYLE, GetWindowLong( hwnd1, GWL_STYLE) & ~WS_CLIPCHILDREN );
+ ValidateRect( hwnd1, NULL);
+ ValidateRect( hwnd2, NULL);
+ ScrollWindowEx( hwnd1, -10, -10, &rc, &cliprc, hrgn, &rcu, SW_SCROLLCHILDREN | SW_INVALIDATE);
+ if (winetest_debug > 0) dump_region(hrgn);
+ /* expected region is the same as in previous test */
+ ok( EqualRgn( exprgn, hrgn), "wrong update region\n");
+
+ /* no SW_SCROLLCHILDREN */
+ SetWindowLong( hwnd1, GWL_STYLE, GetWindowLong( hwnd1, GWL_STYLE) & ~WS_CLIPCHILDREN );
+ ValidateRect( hwnd1, NULL);
+ ValidateRect( hwnd2, NULL);
+ ScrollWindowEx( hwnd1, -10, -10, &rc, &cliprc, hrgn, &rcu, SW_INVALIDATE);
+ if (winetest_debug > 0) dump_region(hrgn);
+ /* expected region is the same as in previous test */
+ ok( EqualRgn( exprgn, hrgn), "wrong update region\n");
+
+ /* WS_CLIPCHILDREN and no SW_SCROLLCHILDREN */
+ SetWindowLong( hwnd1, GWL_STYLE, GetWindowLong( hwnd1, GWL_STYLE) | WS_CLIPCHILDREN );
+ ValidateRect( hwnd1, NULL);
+ ValidateRect( hwnd2, NULL);
+ ScrollWindowEx( hwnd1, -10, -10, &rc, &cliprc, hrgn, &rcu, SW_INVALIDATE);
+ if (winetest_debug > 0) dump_region(hrgn);
+ exprgn = CreateRectRgn( 88,0,98,20);
+ tmprgn = CreateRectRgn( 20,20,98,30);
+ CombineRgn( exprgn, exprgn, tmprgn, RGN_OR);
+ tmprgn = CreateRectRgn( 20,30,30,88);
+ CombineRgn( exprgn, exprgn, tmprgn, RGN_OR);
+ tmprgn = CreateRectRgn( 0,88,30,98);
+ CombineRgn( exprgn, exprgn, tmprgn, RGN_OR);
+ ok( EqualRgn( exprgn, hrgn), "wrong update region\n");
+
/* clean up */
DeleteObject( hrgn);
DeleteObject( exprgn);
@@ -2711,6 +2770,6 @@ START_TEST(win)
test_scrollvalidate( hwndMain);
UnhookWindowsHookEx(hhook);
-
+
test_window_styles();
}
More information about the wine-devel
mailing list