diff --git a/dlls/user32/painting.c b/dlls/user32/painting.c index dbc8cfeb814..9fe6764344d 100644 --- a/dlls/user32/painting.c +++ b/dlls/user32/painting.c @@ -870,6 +870,25 @@ INT WINAPI ScrollWindowEx( HWND hwnd, INT dx, INT dy, CombineRgn( hrgnWinupd, hrgnWinupd, hrgnTemp, RGN_OR ); RedrawWindow( hwnd, NULL, hrgnTemp, rdw_flags); DeleteObject( hrgnClip ); + + /* Catch the case where the scolling amount exceeds the size of the + * original window. This generated a second update area that is the + * location where the original scrolled content would end up. + * This second region is not returned by the ScrollDC and sets + * ScrollWindowEx apart from just a ScrollDC. + * + * This has been verified with testing on windows. + */ + if (abs(dx) > abs(rc.right - rc.left) || + abs(dy) > abs(rc.bottom - rc.top)) + { + SetRectRgn( hrgnTemp, rc.left + dx, rc.top + dy, rc.right+dx, rc.bottom + dy); + CombineRgn( hrgnTemp, hrgnTemp, hrgnClip, RGN_AND ); + CombineRgn( hrgnUpdate, hrgnUpdate, hrgnTemp, RGN_OR ); + + if( !bOwnRgn) + CombineRgn( hrgnWinupd, hrgnWinupd, hrgnTemp, RGN_OR ); + } } DeleteObject( hrgnTemp ); } else { diff --git a/dlls/user32/tests/win.c b/dlls/user32/tests/win.c index ef456cabe3e..9d07306bb1b 100644 --- a/dlls/user32/tests/win.c +++ b/dlls/user32/tests/win.c @@ -2991,6 +2991,15 @@ static void test_scrollvalidate( HWND parent) CombineRgn( exprgn, exprgn, tmprgn, RGN_OR); ok( EqualRgn( exprgn, hrgn), "wrong update region\n"); + SetRect( &rc, 0,40, 100,60); + SetRect( &cliprc, 0,0, 100,100); + ScrollWindowEx( hwnd1, 0, -25, &rc, &cliprc, hrgn, &rcu, SW_INVALIDATE); + SetRectRgn( tmprgn, 0,15,98,35); + CombineRgn( exprgn, exprgn, tmprgn, RGN_OR); + SetRectRgn( tmprgn, 0, 40, 98, 60); + CombineRgn( exprgn, exprgn, tmprgn, RGN_OR); + ok( EqualRgn( exprgn, hrgn), "wrong update region in excessive scroll\n"); + /* now test ScrollWindowEx with a combination of * WS_CLIPCHILDREN style and SW_SCROLLCHILDREN flag */ /* make hwnd2 the child of hwnd1 */