comctl32: rebar[2/4]: test and fix the WM_SIZE handler and REBAR_ForceResize (resend)

Mikołaj Zalewski mikolaj at zalewski.pl
Mon Feb 19 07:09:24 CST 2007


  The next patches differs only by a one line offset in tests/rebar.c 
but I regenerated them too.
-------------- next part --------------
From 2d3de7e513c90cfbc8cc11692839f4dbc53d3f83 Mon Sep 17 00:00:00 2001
From: =?utf-8?q?Miko=C5=82aj_Zalewski?= <mikolaj at zalewski.pl>
Date: Sat, 17 Feb 2007 19:30:34 +0100
Subject: [PATCH] comctl32: rebar: test and fix the WM_SIZE handler and REBAR_ForceResize

---
 dlls/comctl32/comctl32.h    |    3 +
 dlls/comctl32/rebar.c       |  264 +++++++++++++------------------------------
 dlls/comctl32/tests/rebar.c |  183 ++++++++++++++++++++++++++++++
 3 files changed, 263 insertions(+), 187 deletions(-)

diff --git a/dlls/comctl32/comctl32.h b/dlls/comctl32/comctl32.h
index 66a0973..e7a3598 100644
--- a/dlls/comctl32/comctl32.h
+++ b/dlls/comctl32/comctl32.h
@@ -38,6 +38,9 @@
 extern HMODULE COMCTL32_hModule;
 extern HBRUSH  COMCTL32_hPattern55AABrush;
 
+/* has a value of: 0, CCS_TOP, CCS_NOMOVEY, CCS_BOTTOM */
+#define CCS_LAYOUT_MASK 0x3
+
 /* Property sheet / Wizard */
 #define IDD_PROPSHEET 1006
 #define IDD_WIZARD    1020
diff --git a/dlls/comctl32/rebar.c b/dlls/comctl32/rebar.c
index 9da110c..0a196ba 100644
--- a/dlls/comctl32/rebar.c
+++ b/dlls/comctl32/rebar.c
@@ -32,9 +32,7 @@
  *   - RBS_FIXEDORDER
  *   - RBS_REGISTERDROP
  *   - RBS_TOOLTIPS
- *   - CCS_NORESIZE
- *   - CCS_NOMOVEX
- *   - CCS_NOMOVEY
+ *   - RBS_AUTOSIZE
  *   Messages:
  *   - RB_BEGINDRAG
  *   - RB_DRAGMOVE
@@ -190,7 +188,6 @@ typedef struct
     POINT    dragNow;     /* x,y of this MouseMove */
     INT      iOldBand;    /* last band that had the mouse cursor over it */
     INT      ihitoffset;  /* offset of hotspot from gripper.left */
-    POINT    origin;      /* left/upper corner of client */
     INT      ichevronhotBand; /* last band that had a hot chevron */
     INT      iGrabbedBand;/* band number of band whose gripper was grabbed */
 
@@ -200,11 +197,9 @@ typedef struct
 /* fStatus flags */
 #define BEGIN_DRAG_ISSUED   0x00000001
 #define AUTO_RESIZE         0x00000002
-#define RESIZE_ANYHOW       0x00000004
 #define NTF_HGHTCHG         0x00000008
 #define BAND_NEEDS_LAYOUT   0x00000010
 #define BAND_NEEDS_REDRAW   0x00000020
-#define CREATE_RUNNING      0x00000040
 
 /* used by Windows to mark that the header size has been set by the user and shouldn't be changed */
 #define RBBS_UNDOC_FIXEDHEADER 0x40000000
@@ -439,13 +434,18 @@ REBAR_DumpBand (REBAR_INFO *iP)
 
 }
 
+/* dest can be equal to src */
 static void translate_rect(REBAR_INFO *infoPtr, RECT *dest, const RECT *src)
 {
     if (infoPtr->dwStyle & CCS_VERT) {
-        dest->top = src->left;
-        dest->bottom = src->right;
+        int tmp;
+        tmp = src->left;
         dest->left = src->top;
+        dest->top = tmp;
+        
+        tmp = src->right;
         dest->right = src->bottom;
+        dest->bottom = tmp;
     } else {
         *dest = *src;
     }
@@ -465,6 +465,16 @@ static int get_rect_cy(REBAR_INFO *infoPtr, RECT *lpRect)
     return lpRect->bottom - lpRect->top;
 }
 
+static void swap_size_if_vert(REBAR_INFO *infoPtr, SIZE *size)
+{
+    if (infoPtr->dwStyle & CCS_VERT)
+    {
+        LONG tmp = size->cx;
+        size->cx = size->cy;
+        size->cy = tmp;
+    }
+}
+
 static void round_child_height(REBAR_BAND *lpBand, int cyHeight)
 {
     int cy = 0;
@@ -933,104 +943,71 @@ REBAR_ForceResize (REBAR_INFO *infoPtr)
      /* Function: This changes the size of the REBAR window to that */
      /*  calculated by REBAR_Layout.                                */
 {
-    RECT rc;
     INT x, y, width, height;
-    INT xedge = GetSystemMetrics(SM_CXEDGE);
-    INT yedge = GetSystemMetrics(SM_CYEDGE);
+    INT xedge = 0, yedge = 0;
+    RECT rcSelf;
 
-    GetClientRect (infoPtr->hwndSelf, &rc);
-
-    TRACE( " old [%d x %d], new [%d x %d], client [%d x %d]\n",
+    TRACE( "old [%d x %d], new [%d x %d]\n",
 	   infoPtr->oldSize.cx, infoPtr->oldSize.cy,
-	   infoPtr->calcSize.cx, infoPtr->calcSize.cy,
-	   rc.right, rc.bottom);
+	   infoPtr->calcSize.cx, infoPtr->calcSize.cy);
 
     if (infoPtr->dwStyle & CCS_NORESIZE)
         return;
 
-    /* If we need to shrink client, then skip size test */
-    if ((infoPtr->calcSize.cy >= rc.bottom) &&
-	(infoPtr->calcSize.cx >= rc.right)) {
-
-	/* if size did not change then skip process */
-	if ((infoPtr->oldSize.cx == infoPtr->calcSize.cx) &&
-	    (infoPtr->oldSize.cy == infoPtr->calcSize.cy) &&
-	    !(infoPtr->fStatus & RESIZE_ANYHOW))
-	    {
-		TRACE("skipping reset\n");
-		return;
-	    }
+    if (infoPtr->dwStyle & WS_BORDER)
+    {
+        xedge = GetSystemMetrics(SM_CXEDGE);
+        yedge = GetSystemMetrics(SM_CYEDGE);
+        /* swap for CCS_VERT? */
     }
 
-    infoPtr->fStatus &= ~RESIZE_ANYHOW;
-    /* Set flag to ignore next WM_SIZE message */
-    infoPtr->fStatus |= AUTO_RESIZE;
-
-    width = 0;
-    height = 0;
-    x = 0;
-    y = 0;
-
-    if (infoPtr->dwStyle & WS_BORDER) {
-	width = 2 * xedge;
-	height = 2 * yedge;
-    }
+    /* compute rebar window rect in parent client coordinates */
+    GetWindowRect(infoPtr->hwndSelf, &rcSelf);
+    MapWindowPoints(HWND_DESKTOP, GetParent(infoPtr->hwndSelf), (LPPOINT)&rcSelf, 2);
+    translate_rect(infoPtr, &rcSelf, &rcSelf);
 
+    height = (infoPtr->dwStyle & CCS_VERT ? infoPtr->calcSize.cx : infoPtr->calcSize.cy) + 2*yedge;
     if (!(infoPtr->dwStyle & CCS_NOPARENTALIGN)) {
-	INT mode = infoPtr->dwStyle & (CCS_VERT | CCS_TOP | CCS_BOTTOM);
-	RECT rcPcl;
-
-	GetClientRect(GetParent(infoPtr->hwndSelf), &rcPcl);
-	switch (mode) {
-	case CCS_TOP:
-	    /* _TOP sets width to parents width */
-	    width += (rcPcl.right - rcPcl.left);
-	    height += infoPtr->calcSize.cy;
-	    x += ((infoPtr->dwStyle & WS_BORDER) ? -xedge : 0);
-	    y += ((infoPtr->dwStyle & WS_BORDER) ? -yedge : 0);
-	    y += ((infoPtr->dwStyle & CCS_NODIVIDER) ? 0 : REBAR_DIVIDER);
-	    break;
-	case CCS_BOTTOM:
-	    /* FIXME: wrong wrong wrong */
-	    /* _BOTTOM sets width to parents width */
-	    width += (rcPcl.right - rcPcl.left);
-	    height += infoPtr->calcSize.cy;
-      	    x += -xedge;
-	    y = rcPcl.bottom - height + 1;
-	    break;
-	case CCS_LEFT:
-	    /* _LEFT sets height to parents height */
-            width += infoPtr->calcSize.cx;
-	    height += (rcPcl.bottom - rcPcl.top);
-	    x += ((infoPtr->dwStyle & WS_BORDER) ? -xedge : 0);
-	    x += ((infoPtr->dwStyle & CCS_NODIVIDER) ? 0 : REBAR_DIVIDER);
-	    y += ((infoPtr->dwStyle & WS_BORDER) ? -yedge : 0);
-            break;
-	case CCS_RIGHT:
-	    /* FIXME: wrong wrong wrong */
-	    /* _RIGHT sets height to parents height */
-	    width += infoPtr->calcSize.cx;
-	    height += (rcPcl.bottom - rcPcl.top);
-	    x = rcPcl.right - width + 1;
-      	    y = -yedge;
-	    break;
-	default:
-	    width += infoPtr->calcSize.cx;
-	    height += infoPtr->calcSize.cy;
+        RECT rcParent;
+        SIZE calcSize;
+
+        x = -xedge;
+        width = (infoPtr->dwStyle & CCS_VERT ? infoPtr->calcSize.cy : infoPtr->calcSize.cx) + 2*xedge;
+        y = 0; /* quiet compiler warning */
+        switch ( infoPtr->dwStyle & CCS_LAYOUT_MASK) {
+            case 0:     /* shouldn't happen - see NCCreate */
+            case CCS_TOP:
+                y = ((infoPtr->dwStyle & CCS_NODIVIDER) ? 0 : REBAR_DIVIDER) - yedge;
+                break;
+            case CCS_NOMOVEY:
+                y = rcSelf.top;
+                break;
+            case CCS_BOTTOM:
+                GetClientRect(GetParent(infoPtr->hwndSelf), &rcParent);
+                translate_rect(infoPtr, &rcParent, &rcParent);
+                calcSize = infoPtr->calcSize;
+                swap_size_if_vert(infoPtr, &calcSize);
+                y = rcParent.bottom - calcSize.cy - yedge;
+                break;
 	}
     }
     else {
-	width += infoPtr->calcSize.cx;
-	height += infoPtr->calcSize.cy;
-	x = infoPtr->origin.x;
-	y = infoPtr->origin.y;
+	x = rcSelf.left;
+	/* As on Windows if the CCS_NODIVIDER is not present the control will move
+	 * 2 pixel down after every layout */
+	y = rcSelf.top + ((infoPtr->dwStyle & CCS_NODIVIDER) ? 0 : REBAR_DIVIDER);
+	width = rcSelf.right - rcSelf.left;
     }
 
     TRACE("hwnd %p, style=%08x, setting at (%d,%d) for (%d,%d)\n",
-	infoPtr->hwndSelf, infoPtr->dwStyle,
-	x, y, width, height);
-    SetWindowPos (infoPtr->hwndSelf, 0, x, y, width, height,
-		    SWP_NOZORDER);
+	infoPtr->hwndSelf, infoPtr->dwStyle, x, y, width, height);
+
+    /* Set flag to ignore next WM_SIZE message and resize the window */
+    infoPtr->fStatus |= AUTO_RESIZE;
+    if ((infoPtr->dwStyle & CCS_VERT) == 0)
+        SetWindowPos(infoPtr->hwndSelf, 0, x, y, width, height, SWP_NOZORDER);
+    else
+        SetWindowPos(infoPtr->hwndSelf, 0, y, x, height, width, SWP_NOZORDER);
     infoPtr->fStatus &= ~AUTO_RESIZE;
 }
 
@@ -1158,16 +1135,6 @@ REBAR_MoveChildWindows (REBAR_INFO *infoPtr, UINT start, UINT endplus)
 
 }
 
-static void swap_size_if_vert(REBAR_INFO *infoPtr, SIZE *size)
-{
-    if (infoPtr->dwStyle & CCS_VERT)
-    {
-        LONG tmp = size->cx;
-        size->cx = size->cy;
-        size->cy = tmp;
-    }
-}
-
 static int next_band(REBAR_INFO *infoPtr, int i)
 {
     int n;
@@ -1394,7 +1361,7 @@ REBAR_Layout(REBAR_INFO *infoPtr, LPRECT lpRect, BOOL notify)
     if (lpRect) {
         rcAdj = *lpRect;
         cyTarget = get_rect_cy(infoPtr, lpRect);
-    } else if (infoPtr->dwStyle & CCS_NORESIZE || GetParent(infoPtr->hwndSelf) == NULL)
+    } else if (infoPtr->dwStyle & (CCS_NORESIZE | CCS_NOPARENTALIGN) || GetParent(infoPtr->hwndSelf) == NULL)
         GetClientRect(infoPtr->hwndSelf, &rcAdj);
     else
         GetClientRect(GetParent(infoPtr->hwndSelf), &rcAdj);
@@ -2010,7 +1977,6 @@ REBAR_DeleteBand (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
 
     TRACE("setting NEEDS_LAYOUT\n");
     infoPtr->fStatus |= BAND_NEEDS_LAYOUT;
-    infoPtr->fStatus |= RESIZE_ANYHOW;
     REBAR_Layout(infoPtr, NULL, TRUE);
 
     return TRUE;
@@ -3150,7 +3116,7 @@ REBAR_NCCreate (HWND hwnd, WPARAM wParam, LPARAM lParam)
     infoPtr->hcurHorz  = LoadCursorW (0, (LPWSTR)IDC_SIZEWE);
     infoPtr->hcurVert  = LoadCursorW (0, (LPWSTR)IDC_SIZENS);
     infoPtr->hcurDrag  = LoadCursorW (0, (LPWSTR)IDC_SIZE);
-    infoPtr->fStatus = CREATE_RUNNING;
+    infoPtr->fStatus = 0;
     infoPtr->hFont = GetStockObject (SYSTEM_FONT);
 
     /* issue WM_NOTIFYFORMAT to get unicode status of parent */
@@ -3159,7 +3125,9 @@ REBAR_NCCreate (HWND hwnd, WPARAM wParam, LPARAM lParam)
     /* Stow away the original style */
     infoPtr->orgStyle = cs->style;
     /* add necessary styles to the requested styles */
-    infoPtr->dwStyle = cs->style | WS_VISIBLE | CCS_TOP;
+    infoPtr->dwStyle = cs->style | WS_VISIBLE;
+    if ((infoPtr->dwStyle & CCS_LAYOUT_MASK) == 0)
+        infoPtr->dwStyle |= CCS_TOP;
     SetWindowLongW (hwnd, GWL_STYLE, infoPtr->dwStyle);
 
     /* get font handle for Caption Font */
@@ -3409,88 +3377,17 @@ REBAR_SetRedraw (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
 static LRESULT
 REBAR_Size (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
 {
-    RECT rcClient;
+    TRACE("wParam=%x, lParam=%lx\n", wParam, lParam);
 
-    /* auto resize deadlock check */
+    /* avoid auto resize infinite recursion */
     if (infoPtr->fStatus & AUTO_RESIZE) {
 	infoPtr->fStatus &= ~AUTO_RESIZE;
 	TRACE("AUTO_RESIZE was set, reset, fStatus=%08x lparam=%08lx\n",
 	      infoPtr->fStatus, lParam);
 	return 0;
     }
-
-    if (infoPtr->fStatus & CREATE_RUNNING) {
-	/* still in CreateWindow */
-	RECT rcWin;
-
-	if ((INT)wParam != SIZE_RESTORED) {
-	    ERR("WM_SIZE in create and flags=%08x, lParam=%08lx\n",
-		wParam, lParam);
-	}
-
-	TRACE("still in CreateWindow\n");
-	infoPtr->fStatus &= ~CREATE_RUNNING;
-	GetWindowRect ( infoPtr->hwndSelf, &rcWin);
-	TRACE("win rect (%d,%d)-(%d,%d)\n",
-	      rcWin.left, rcWin.top, rcWin.right, rcWin.bottom);
-
-	if ((lParam == 0) && (rcWin.right-rcWin.left == 0) &&
-	    (rcWin.bottom-rcWin.top == 0)) {
-	    /* native control seems to do this */
-	    GetClientRect (GetParent(infoPtr->hwndSelf), &rcClient);
-            TRACE("sizing rebar, message and client zero, parent client (%d,%d)\n",
-		  rcClient.right, rcClient.bottom);
-	}
-	else {
-	    INT cx, cy;
-
-	    cx = rcWin.right - rcWin.left;
-	    cy = rcWin.bottom - rcWin.top;
-	    if ((cx == LOWORD(lParam)) && (cy == HIWORD(lParam))) {
-		return 0;
-	    }
-
-	    /* do the actual WM_SIZE request */
-	    GetClientRect (infoPtr->hwndSelf, &rcClient);
-            TRACE("sizing rebar from (%d,%d) to (%d,%d), client (%d,%d)\n",
-		  infoPtr->calcSize.cx, infoPtr->calcSize.cy,
-		  LOWORD(lParam), HIWORD(lParam),
-		  rcClient.right, rcClient.bottom);
-	}
-        infoPtr->fStatus |= BAND_NEEDS_LAYOUT;
-        REBAR_Layout(infoPtr, &rcClient, TRUE);
-        return 0;
-    }
-    else {
-	if ((INT)wParam != SIZE_RESTORED) {
-	    ERR("WM_SIZE out of create and flags=%08x, lParam=%08lx\n",
-		wParam, lParam);
-	}
-
-	/* Handle cases when outside of the CreateWindow process */
-
-	GetClientRect (infoPtr->hwndSelf, &rcClient);
-	if ((lParam == 0) && (rcClient.right + rcClient.bottom != 0) &&
-	    (infoPtr->dwStyle & RBS_AUTOSIZE)) {
-	    /* on a WM_SIZE to zero and current client not zero and AUTOSIZE */
-	    /* native seems to use the current parent width for the size     */
-	    infoPtr->fStatus |= BAND_NEEDS_LAYOUT;
-	    GetClientRect (GetParent(infoPtr->hwndSelf), &rcClient);
-            if (infoPtr->dwStyle & CCS_VERT)
-                rcClient.right = 0;
-            else
-                rcClient.bottom = 0;
-            TRACE("sizing rebar to parent (%d,%d) size is zero but AUTOSIZE set\n",
-		  rcClient.right, rcClient.bottom);
-	}
-	else {
-            TRACE("sizing rebar from (%d,%d) to (%d,%d), client (%d,%d)\n",
-		  infoPtr->calcSize.cx, infoPtr->calcSize.cy,
-		  LOWORD(lParam), HIWORD(lParam),
-		  rcClient.right, rcClient.bottom);
-	}
-    }
-
+    
+    /* FIXME: wrong */
     if (infoPtr->dwStyle & RBS_AUTOSIZE) {
 	NMRBAUTOSIZE autosize;
 
@@ -3502,11 +3399,8 @@ REBAR_Size (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
 	      autosize.rcTarget.right, autosize.rcTarget.bottom, lParam);
     }
 
-    if (((infoPtr->calcSize.cx != rcClient.right) || (infoPtr->calcSize.cy != rcClient.bottom)))
-    {
-        infoPtr->fStatus |= BAND_NEEDS_LAYOUT;
-        REBAR_Layout(infoPtr, &rcClient, TRUE);
-    }
+    infoPtr->fStatus |= BAND_NEEDS_LAYOUT;
+    REBAR_Layout(infoPtr, NULL, TRUE);
 
     return 0;
 }
@@ -3548,13 +3442,9 @@ static LRESULT theme_changed (REBAR_INFO* infoPtr)
 static LRESULT
 REBAR_WindowPosChanged (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
 {
-    WINDOWPOS *lpwp = (WINDOWPOS *)lParam;
     LRESULT ret;
     RECT rc;
 
-    /* Save the new origin of this window - used by _ForceResize */
-    infoPtr->origin.x = lpwp->x;
-    infoPtr->origin.y = lpwp->y;
     ret = DefWindowProcW(infoPtr->hwndSelf, WM_WINDOWPOSCHANGED,
 			 wParam, lParam);
     GetWindowRect(infoPtr->hwndSelf, &rc);
diff --git a/dlls/comctl32/tests/rebar.c b/dlls/comctl32/tests/rebar.c
index 9773805..d110305 100644
--- a/dlls/comctl32/tests/rebar.c
+++ b/dlls/comctl32/tests/rebar.c
@@ -33,6 +33,12 @@ static HWND hRebar;
 #define check_rect(name, val, exp) ok(val.top == exp.top && val.bottom == exp.bottom && \
     val.left == exp.left && val.right == exp.right, "invalid rect (" name ") (%d,%d) (%d,%d) - expected (%d,%d) (%d,%d)\n", \
     val.left, val.top, val.right, val.bottom, exp.left, exp.top, exp.right, exp.bottom);
+
+#define check_rect_no_top(name, val, exp) { \
+        ok((val.bottom - val.top == exp.bottom - exp.top) && \
+            val.left == exp.left && val.right == exp.right, "invalid rect (" name ") (%d,%d) (%d,%d) - expected (%d,%d) (%d,%d), ignoring top\n", \
+            val.left, val.top, val.right, val.bottom, exp.left, exp.top, exp.right, exp.bottom); \
+    }
  
 #define compare(val, exp, format) ok((val) == (exp), #val " value " format " expected " format "\n", (val), (exp));
 
@@ -429,6 +435,182 @@ static void layout_test()
     DestroyWindow(hRebar);
 }
 
+#if 0       /* use this to generate more tests */
+
+static void dump_client(HWND hRebar)
+{
+    RECT r;
+    GetWindowRect(hRebar, &r);
+    MapWindowPoints(HWND_DESKTOP, hMainWnd, (LPPOINT)&r, 2);
+    printf("    {{%d, %d, %d, %d}, %d},\n", r.left, r.top, r.right, r.bottom, SendMessage(hRebar, RB_GETROWCOUNT, 0, 0));
+}
+
+#define comment(fmt, arg1)
+#define check_client() dump_client(hRebar)
+
+#else
+
+typedef struct {
+    RECT rc;
+    INT iNumRows;
+} rbresize_test_result_t;
+
+rbresize_test_result_t resize_results[] = {
+/* style 00000001 */
+    {{0, 2, 672, 2}, 0},
+    {{0, 2, 672, 22}, 1},
+    {{0, 2, 672, 22}, 1},
+    {{0, 2, 672, 22}, 1},
+/* style 00000041 */
+    {{0, 0, 672, 0}, 0},
+    {{0, 0, 672, 20}, 1},
+    {{0, 0, 672, 20}, 1},
+    {{0, 0, 672, 20}, 1},
+/* style 00000003 */
+    {{0, 226, 672, 226}, 0},
+    {{0, 206, 672, 226}, 1},
+    {{0, 206, 672, 226}, 1},
+    {{0, 206, 672, 226}, 1},
+/* style 00000043 */
+    {{0, 226, 672, 226}, 0},
+    {{0, 206, 672, 226}, 1},
+    {{0, 206, 672, 226}, 1},
+    {{0, 206, 672, 226}, 1},
+/* style 00000080 */
+    {{2, 0, 2, 226}, 0},
+    {{2, 0, 22, 226}, 1},
+    {{2, 0, 22, 226}, 1},
+    {{2, 0, 22, 226}, 1},
+/* style 00000083 */
+    {{672, 0, 672, 226}, 0},
+    {{652, 0, 672, 226}, 1},
+    {{652, 0, 672, 226}, 1},
+    {{652, 0, 672, 226}, 1},
+/* style 00000008 */
+    {{10, 11, 510, 11}, 0},
+    {{10, 15, 510, 35}, 1},
+    {{10, 17, 510, 37}, 1},
+    {{10, 14, 110, 54}, 2},
+    {{0, 4, 0, 44}, 2},
+    {{0, 6, 0, 46}, 2},
+    {{0, 8, 0, 48}, 2},
+/* style 00000048 */
+    {{10, 5, 510, 5}, 0},
+    {{10, 5, 510, 25}, 1},
+    {{10, 5, 510, 25}, 1},
+    {{10, 10, 110, 50}, 2},
+    {{0, 0, 0, 40}, 2},
+    {{0, 0, 0, 40}, 2},
+    {{0, 0, 0, 40}, 2},
+/* style 00000004 */
+    {{10, 5, 510, 20}, 0},
+    {{10, 5, 510, 20}, 1},
+    {{10, 10, 110, 110}, 2},
+    {{0, 0, 0, 0}, 2},
+    {{0, 0, 0, 0}, 2},
+    {{0, 0, 0, 0}, 2},
+/* style 00000002 */
+    {{0, 5, 672, 5}, 0},
+    {{0, 5, 672, 25}, 1},
+    {{0, 10, 672, 30}, 1},
+    {{0, 0, 672, 20}, 1},
+/* style 00000082 */
+    {{10, 0, 10, 226}, 0},
+    {{10, 0, 30, 226}, 1},
+    {{10, 0, 30, 226}, 1},
+    {{0, 0, 20, 226}, 1},
+/* style 00800001 */
+    {{-2, 0, 674, 4}, 0},
+    {{-2, 0, 674, 24}, 1},
+    {{-2, 0, 674, 24}, 1},
+    {{-2, 0, 674, 24}, 1},
+/* style 00800048 */
+    {{10, 5, 510, 9}, 0},
+    {{10, 5, 510, 29}, 1},
+    {{10, 5, 510, 29}, 1},
+    {{10, 10, 110, 54}, 2},
+    {{0, 0, 0, 44}, 2},
+    {{0, 0, 0, 44}, 2},
+    {{0, 0, 0, 44}, 2},
+/* style 00800004 */
+    {{10, 5, 510, 20}, 0},
+    {{10, 5, 510, 20}, 1},
+    {{10, 10, 110, 110}, 2},
+    {{0, 0, 0, 0}, 2},
+    {{0, 0, 0, 0}, 2},
+    {{0, 0, 0, 0}, 2},
+/* style 00800002 */
+    {{-2, 5, 674, 9}, 0},
+    {{-2, 5, 674, 29}, 1},
+    {{-2, 10, 674, 34}, 1},
+    {{-2, 0, 674, 24}, 1},
+};
+
+static int resize_numtests = 0;
+
+#define comment(fmt, arg1)
+#define check_client() { \
+        RECT r; \
+        rbresize_test_result_t *res = &resize_results[resize_numtests++]; \
+        assert(resize_numtests <= sizeof(resize_results)/sizeof(resize_results[0])); \
+        GetWindowRect(hRebar, &r); \
+        MapWindowPoints(HWND_DESKTOP, hMainWnd, (LPPOINT)&r, 2); \
+        if ((dwStyles[i] & (CCS_NOPARENTALIGN|CCS_NODIVIDER)) == CCS_NOPARENTALIGN) {\
+            check_rect_no_top("client", r, res->rc); /* the top coordinate changes after every layout and very implementation-dependent */ \
+        } else { \
+            check_rect("client", r, res->rc); \
+        } \
+        expect_eq((int)SendMessage(hRebar, RB_GETROWCOUNT, 0, 0), res->iNumRows, int, "%d"); \
+    }
+
+#endif
+
+static void resize_test()
+{
+    HWND hRebar;
+    DWORD dwStyles[] = {CCS_TOP, CCS_TOP | CCS_NODIVIDER, CCS_BOTTOM, CCS_BOTTOM | CCS_NODIVIDER, CCS_VERT, CCS_RIGHT,
+        CCS_NOPARENTALIGN, CCS_NOPARENTALIGN | CCS_NODIVIDER, CCS_NORESIZE, CCS_NOMOVEY, CCS_NOMOVEY | CCS_VERT,
+        CCS_TOP | WS_BORDER, CCS_NOPARENTALIGN | CCS_NODIVIDER | WS_BORDER, CCS_NORESIZE | WS_BORDER,
+        CCS_NOMOVEY | WS_BORDER};
+
+    const int styles_count = sizeof(dwStyles) / sizeof(dwStyles[0]);
+    int i;
+
+    for (i = 0; i < styles_count; i++)
+    {
+        comment("style %08x", dwStyles[i]);
+        hRebar = CreateWindow(REBARCLASSNAME, "A", dwStyles[i] | WS_CHILD | WS_VISIBLE, 10, 5, 500, 15, hMainWnd, NULL, GetModuleHandle(NULL), 0);
+        check_client();
+        add_band_w(hRebar, NULL, 70, 100, 0);
+        if (dwStyles[i] & CCS_NOPARENTALIGN)  /* the window drifts downward for CCS_NOPARENTALIGN without CCS_NODIVIDER */
+            check_client();
+        add_band_w(hRebar, NULL, 70, 100, 0);
+        check_client();
+        MoveWindow(hRebar, 10, 10, 100, 100, TRUE);
+        check_client();
+        MoveWindow(hRebar, 0, 0, 0, 0, TRUE);
+        check_client();
+        /* try to fool the rebar by sending invalid width/height - won't work */
+        if (dwStyles[i] & (CCS_NORESIZE | CCS_NOPARENTALIGN))
+        {
+            WINDOWPOS pos;
+            pos.hwnd = hRebar;
+            pos.hwndInsertAfter = NULL;
+            pos.cx = 500;
+            pos.cy = 500;
+            pos.x = 10;
+            pos.y = 10;
+            pos.flags = 0;
+            SendMessage(hRebar, WM_WINDOWPOSCHANGING, 0, (LPARAM)&pos);
+            SendMessage(hRebar, WM_WINDOWPOSCHANGED, 0, (LPARAM)&pos);
+            check_client();
+            SendMessage(hRebar, WM_SIZE, SIZE_RESTORED, MAKELONG(500, 500));
+            check_client();
+        }
+        DestroyWindow(hRebar);
+    }
+}
+
 static void expect_band_content(UINT uBand, UINT fStyle, COLORREF clrFore,
     COLORREF clrBack, LPCSTR lpText, int iImage, HWND hwndChild,
     UINT cxMinChild, UINT cyMinChild, UINT cx, HBITMAP hbmBack, UINT wID,
@@ -550,6 +732,7 @@ START_TEST(rebar)
 
     bandinfo_test();
     layout_test();
+    resize_test();
     PostQuitMessage(0);
     while(GetMessageA(&msg,0,0,0)) {
         TranslateMessage(&msg);
-- 
1.4.4.2


More information about the wine-patches mailing list