DefWindowproc NCCALC fix for WS_xSCROLL styles

Rein Klazes wijn at wanadoo.nl
Mon Feb 21 14:42:32 CST 2005


Hi,

This fixes a bug that was exposed by this change:

| Log message:
| 	Vitaly Lipatov <lav at etersoft.ru>
| 	Rename SCROLL_GetScrollBarInfo to SCROLL_GetInternalInfo and make
| 	allocation of a new info structure optional.
| 	Add some descriptions.
| 
| Patch: http://cvs.winehq.org/patch.py?id=16164

A horizontal scrollbar control in Visual Studio 6 is created with the
WS_HSCROLL window style set. Now Windows will happily add a scroll bar
to a scroll bar control, but only if there is space enough. 
If there is not, DefWindowProc's WM_NCCALC handler will not subtract the
scrollbar's height (or width for vertical sb's), leaving the client
space to draw Visual Studio's control.

Changelog:
	windows		: nonclient.c
	dlls/user/tests	: win.c

	DefWindowProc's WM_NCCALC handler must not subtract space for
	scrollbars if there is not enough space for it anyway. With
tests
	to confirm the behavior.

Rein.
-------------- next part --------------
--- wine/windows/nonclient.c	2005-02-16 12:27:51.000000000 +0100
+++ mywine/windows/nonclient.c	2005-02-21 12:29:10.000000000 +0100
@@ -402,12 +402,23 @@ LONG NC_HandleNCCalcSize( HWND hwnd, REC
 				       -tmpRect.left, -tmpRect.top ) + 1;
 	}
 
-	SetRect(&tmpRect, 0, 0, 0, 0);
-	NC_AdjustRectInner (&tmpRect, style, exStyle);
-	winRect->left   -= tmpRect.left;
-	winRect->top    -= tmpRect.top;
-	winRect->right  -= tmpRect.right;
-	winRect->bottom -= tmpRect.bottom;
+        if( exStyle & WS_EX_CLIENTEDGE)
+            if( winRect->right - winRect->left > 2 * GetSystemMetrics(SM_CXEDGE) &&
+                   winRect->bottom - winRect->top > 2 * GetSystemMetrics(SM_CYEDGE))
+                InflateRect( winRect, - GetSystemMetrics(SM_CXEDGE),
+                        - GetSystemMetrics(SM_CYEDGE));
+
+        if (style & WS_VSCROLL)
+            if( winRect->right - winRect->left >= GetSystemMetrics(SM_CXVSCROLL)){
+                if((exStyle & WS_EX_LEFTSCROLLBAR) != 0)
+                    winRect->left  += GetSystemMetrics(SM_CXVSCROLL);
+                else
+                    winRect->right -= GetSystemMetrics(SM_CXVSCROLL);
+            }
+
+        if (style & WS_HSCROLL)
+            if( winRect->bottom - winRect->top > GetSystemMetrics(SM_CYHSCROLL))
+                    winRect->bottom -= GetSystemMetrics(SM_CYHSCROLL);
 
         if (winRect->top > winRect->bottom)
             winRect->bottom = winRect->top;
--- wine/dlls/user/tests/win.c	2005-02-18 14:38:24.000000000 +0100
+++ mywine/dlls/user/tests/win.c	2005-02-21 15:36:11.000000000 +0100
@@ -2231,6 +2231,58 @@ static void test_validatergn(HWND hwnd)
     DestroyWindow( child );
 }
 
+
+void nccalchelper( HWND hwnd, INT x, INT y, RECT *prc)
+{
+    MoveWindow( hwnd, 0, 0, x, y, 0);
+    GetWindowRect( hwnd, prc);
+    trace("window rect is %ld,%ld - %ld,%ld\n", 
+            prc->left,prc->top,prc->right,prc->bottom);
+    DefWindowProcA(hwnd, WM_NCCALCSIZE, 0, (LPARAM)prc);
+    trace("nccalc rect is %ld,%ld - %ld,%ld\n",
+            prc->left,prc->top,prc->right,prc->bottom);
+}
+
+void test_nccalcscroll( HWND parent)
+{
+    RECT rc1;
+    INT sbheight = GetSystemMetrics( SM_CYHSCROLL);
+    INT sbwidth = GetSystemMetrics( SM_CXVSCROLL);
+    HWND hwnd = CreateWindowExA(0, "static", NULL, 
+            WS_CHILD| WS_VISIBLE | WS_VSCROLL | WS_HSCROLL , 
+            10, 10, 200, 200, parent, 0, 0, NULL); 
+    ShowWindow( parent, SW_SHOW);
+    UpdateWindow( parent);
+
+    /* test window too low for a horizontal scroll bar */
+    nccalchelper( hwnd, 100, sbheight, &rc1);
+    ok( rc1.bottom - rc1.top == sbheight, "Height should be %d size is %ld,%ld - %ld,%ld\n", 
+            sbheight, rc1.left, rc1.top, rc1.right, rc1.bottom);
+
+    /* test window just high enough for a horizontal scroll bar */
+    nccalchelper( hwnd, 100, sbheight + 1, &rc1);
+    ok( rc1.bottom - rc1.top == 1, "Height should be %d size is %ld,%ld - %ld,%ld\n", 
+            1, rc1.left, rc1.top, rc1.right, rc1.bottom);
+
+    /* test window too narrow for a vertical scroll bar */
+    nccalchelper( hwnd, sbwidth - 1, 100, &rc1);
+    ok( rc1.right - rc1.left == sbwidth - 1 , "Width should be %d size is %ld,%ld - %ld,%ld\n", 
+            sbwidth - 1, rc1.left, rc1.top, rc1.right, rc1.bottom);
+
+    /* test window just wide enough for a vertical scroll bar */
+    nccalchelper( hwnd, sbwidth, 100, &rc1);
+    ok( rc1.right - rc1.left == 0, "Width should be %d size is %ld,%ld - %ld,%ld\n", 
+            0, rc1.left, rc1.top, rc1.right, rc1.bottom);
+
+    /* same test, but with client edge: not enough width */
+    SetWindowLong( hwnd, GWL_EXSTYLE, WS_EX_CLIENTEDGE | GetWindowLong( hwnd, GWL_EXSTYLE));
+    nccalchelper( hwnd, sbwidth, 100, &rc1);
+    ok( rc1.right - rc1.left == sbwidth - 2 * GetSystemMetrics(SM_CXEDGE),
+            "Width should be %d size is %ld,%ld - %ld,%ld\n", 
+            sbwidth - 2 * GetSystemMetrics(SM_CXEDGE), rc1.left, rc1.top, rc1.right, rc1.bottom);
+
+    DestroyWindow( hwnd);
+}
 START_TEST(win)
 {
     pGetAncestor = (void *)GetProcAddress( GetModuleHandleA("user32.dll"), "GetAncestor" );
@@ -2287,6 +2339,7 @@ START_TEST(win)
     test_keyboard_input(hwndMain);
     test_mouse_input(hwndMain);
     test_validatergn(hwndMain);
+    test_nccalcscroll( hwndMain);
 
     UnhookWindowsHookEx(hhook);
 }


More information about the wine-patches mailing list