Problem with Pager control

Susan Farley susan at codeweavers.com
Wed Feb 7 09:33:29 CST 2001


This patch greatly improves the page scroller.  I was kind of
waiting til my last patch was accepted before submitting more. 
(This one includes those changes too, so it ought to apply to the
tip of winehq.)  Maybe it will fix the problem.  Otherwise, please
do send me traces (+pager,+win).  

thanks,
sue



"Guy L. Albertelli" wrote:
> 
> While working on ComboEx with the 1/29/2001 CVS, IE4 no longer displays its
> menu bar. (Well, not really a menu bar, it is a Rebar with a Pager as the
> child and a Toolbar as a child of the Pager. The Toolbar buttons are the
> "menu" items.) If I revert the Pager code to the 12/29/2000 version (very
> limited functionality) then the "menu" appears and is usable. If you need
> traces, I can provide them.
> 
> This is with preinstalled copy of IE4.
> 
> Thanks,
> 
> Guy Albertelli  <<galberte at neo.lrun.com>>
-------------- next part --------------
Index: include/commctrl.h
===================================================================
RCS file: /home/wine/wine/include/commctrl.h,v
retrieving revision 1.69
diff -u -r1.69 commctrl.h
--- include/commctrl.h	2000/12/19 02:08:35	1.69
+++ include/commctrl.h	2001/02/07 16:18:46
@@ -1754,7 +1754,7 @@
     INT  iXpos;
     INT  iYpos;
     INT  iScroll;
-} NMPGSCROLL, *LPNMPGSCROLL;
+} WINE_PACKED NMPGSCROLL, *LPNMPGSCROLL;
 
 typedef struct
 {
Index: dlls/comctl32/commctrl.c
===================================================================
RCS file: /home/wine/wine/dlls/comctl32/commctrl.c,v
retrieving revision 1.37
diff -u -r1.37 commctrl.c
--- dlls/comctl32/commctrl.c	2001/01/09 20:50:13	1.37
+++ dlls/comctl32/commctrl.c	2001/02/07 16:18:47
@@ -127,6 +127,7 @@
 		TRACKBAR_Register ();
 		TREEVIEW_Register ();
 		UPDOWN_Register ();
+		PAGER_Register ();
 	    }
 	    COMCTL32_dwProcessesAttached++;
 	    break;
Index: dlls/comctl32/pager.c
===================================================================
RCS file: /home/wine/wine/dlls/comctl32/pager.c,v
retrieving revision 1.21
diff -u -r1.21 pager.c
--- dlls/comctl32/pager.c	2001/01/26 20:43:41	1.21
+++ dlls/comctl32/pager.c	2001/02/07 16:18:47
@@ -24,12 +24,12 @@
 typedef struct
 {
     HWND   hwndChild;  /* handle of the contained wnd */
+    BOOL   bNoResize;  /* set when created with CCS_NORESIZE */
     BOOL   bHorizontal;/* orientation of the control */
     COLORREF clrBk;    /* background color */
     INT    nBorder;    /* border size for the control */
     INT    nButtonSize;/* size of the pager btns */
     INT    nPos;       /* scroll position */
-    INT    nDelta;     /* scroll delta */
     INT    nWidth;     /* from child wnd's response to PGN_CALCSIZE */
     INT    nHeight;    /* from child wnd's response to PGN_CALCSIZE */ 
     BOOL   bForward;   /* forward WM_MOUSEMOVE msgs to the contained wnd */
@@ -309,12 +309,12 @@
             SetWindowPos(infoPtr->hwndChild, 0,
                          -nPos, 0,
                          infoPtr->nWidth, infoPtr->nHeight,
-    	     SWP_NOZORDER);
+                         SWP_NOZORDER);
         }
         else
         {
             TRACE("[%04x] SWP %dx%d at (%d,%d)\n", hwnd, 
-	         infoPtr->nWidth, infoPtr->nHeight,
+                         infoPtr->nWidth, infoPtr->nHeight,
                          0, -nPos);
             SetWindowPos(infoPtr->hwndChild, 0,
                          0, -nPos,
@@ -350,6 +350,7 @@
             childSize = infoPtr->nHeight;
         }
 
+        TRACE("childSize = %d,  wndSize = %d\n", childSize, wndSize);
         if (childSize > wndSize)
             scrollRange = childSize - wndSize + infoPtr->nButtonSize;
     }
@@ -457,45 +458,141 @@
     PAGER_INFO *infoPtr = PAGER_GetInfoPtr (hwnd);
     INT scrollRange = PAGER_GetScrollRange(hwnd, infoPtr);
 
-    if (scrollRange <= 0)
-        newPos = 0;
-    else if (newPos < 0)
-        newPos = 0;
+    if ((scrollRange <= 0) || (newPos < 0))
+        infoPtr->nPos = 0;
     else if (newPos > scrollRange)
-        newPos = scrollRange;
+        infoPtr->nPos = scrollRange;
+    else
+        infoPtr->nPos = newPos;
+
+    TRACE("[%04x] pos=%d\n", hwnd, infoPtr->nPos);
 
-    if (newPos != infoPtr->nPos)
+    /* gray and restore btns, and if from WM_SETPOS, hide the gray btns */
+    PAGER_UpdateBtns(hwnd, infoPtr, scrollRange, !fromBtnPress);
+    PAGER_PositionChildWnd(hwnd, infoPtr);
+
+    return 0;
+}
+
+static LRESULT
+PAGER_HandleWindowPosChanging(HWND hwnd, WINDOWPOS *winpos)
+{
+    PAGER_INFO *infoPtr = PAGER_GetInfoPtr (hwnd);
+
+    if (infoPtr->bNoResize && !(winpos->flags & SWP_NOSIZE))
     {
-        infoPtr->nPos = newPos;
-        TRACE("[%04x] pos=%d\n", hwnd, infoPtr->nPos);
+        RECT wndRect;
+        INT cx, cy;
+
+        /* don't let the app resize the nonscrollable dimension of a control
+         * that was created with CCS_NORESIZE style
+         * (i.e. height for a horizontal pager, or width for a vertical one) */
+
+        GetWindowRect(hwnd, &wndRect);
 
-        /* gray and restore btns, and if from WM_SETPOS, hide the gray btns */
-        PAGER_UpdateBtns(hwnd, infoPtr, scrollRange, !fromBtnPress);
+        cx = wndRect.right - wndRect.left;
+        cy = wndRect.bottom - wndRect.top;
 
-        PAGER_PositionChildWnd(hwnd, infoPtr);
+        if (infoPtr->bHorizontal)
+        {
+            winpos->cy = infoPtr->nHeight;
+        }
+        else
+        {
+            winpos->cx = infoPtr->nWidth;
+        }
     }
 
     return 0;
 }
 
+static void 
+PAGER_SetFixedWidth(HWND hwnd, PAGER_INFO* infoPtr)
+{
+  /* Must set the non-scrollable dimension to be less than the full height/width
+   * so that NCCalcSize is called.  The Msoft docs mention 3/4 factor for button
+   * size, and experimentation shows that affect is almost right. */
+
+    RECT wndRect;
+    INT delta, h;
+    GetWindowRect(hwnd, &wndRect);
+
+    /* see what the app says for btn width */
+    PAGER_CalcSize(hwnd, &infoPtr->nWidth, TRUE);
+
+    if (infoPtr->bNoResize)
+    {
+        delta = wndRect.right - wndRect.left - infoPtr->nWidth;
+        if (delta > infoPtr->nButtonSize)
+            infoPtr->nWidth += 4 * infoPtr->nButtonSize / 3;
+        else if (delta > 0)
+            infoPtr->nWidth +=  infoPtr->nButtonSize / 3;
+    }
+
+    h = wndRect.bottom - wndRect.top;
+
+    /* adjust non-scrollable dimension to fit the child */
+    SetWindowPos(hwnd, 0, 0,0, infoPtr->nWidth, h, 
+                 SWP_FRAMECHANGED | SWP_NOMOVE | SWP_NOZORDER);
+
+
+    TRACE("[%04x] infoPtr->nWidth set to %d\n",
+	       hwnd, infoPtr->nWidth);
+}
+
+static void 
+PAGER_SetFixedHeight(HWND hwnd, PAGER_INFO* infoPtr)
+{
+  /* Must set the non-scrollable dimension to be less than the full height/width
+   * so that NCCalcSize is called.  The Msoft docs mention 3/4 factor for button
+   * size, and experimentation shows that affect is almost right. */
+
+    RECT wndRect;
+    INT delta, w;
+    GetWindowRect(hwnd, &wndRect);
+
+    /* see what the app says for btn height */
+    PAGER_CalcSize(hwnd, &infoPtr->nHeight, FALSE);
+
+    if (infoPtr->bNoResize)
+    {
+        delta = wndRect.bottom - wndRect.top - infoPtr->nHeight;
+        if (delta > infoPtr->nButtonSize)
+            infoPtr->nHeight += 4 * infoPtr->nButtonSize / 3;
+        else if (delta > 0)
+            infoPtr->nHeight +=  infoPtr->nButtonSize / 3;
+    }
+
+    w = wndRect.right - wndRect.left;
+
+    /* adjust non-scrollable dimension to fit the child */
+    SetWindowPos(hwnd, 0, 0,0, w, infoPtr->nHeight, 
+                 SWP_FRAMECHANGED | SWP_NOMOVE | SWP_NOZORDER);
+
+    TRACE("[%04x] infoPtr->nHeight set to %d\n",
+	       hwnd, infoPtr->nHeight);
+}
+
 static LRESULT
 PAGER_RecalcSize(HWND hwnd)
 {
     PAGER_INFO *infoPtr = PAGER_GetInfoPtr (hwnd);
-    INT scrollRange;
-
     TRACE("[%04x]\n", hwnd);
-    scrollRange = PAGER_GetScrollRange(hwnd, infoPtr);
 
-    if (scrollRange <= 0)
-    PAGER_SetPos(hwnd, 0, FALSE);
-    else 
+    if (infoPtr->hwndChild)
     {
-        PAGER_UpdateBtns(hwnd, infoPtr, scrollRange, TRUE);
-        PAGER_PositionChildWnd(hwnd, infoPtr);
+        INT scrollRange = PAGER_GetScrollRange(hwnd, infoPtr);
+
+        if (scrollRange <= 0)
+            PAGER_SetPos(hwnd, 0, FALSE);
+        else 
+        {
+            PAGER_UpdateBtns(hwnd, infoPtr, scrollRange, TRUE);
+            PAGER_PositionChildWnd(hwnd, infoPtr);
+        }
     }
 
-    return 0;
+    return 1;
 }
 
 
@@ -544,7 +641,6 @@
 }
 
 
-
 static LRESULT
 PAGER_SetChild (HWND hwnd, WPARAM wParam, LPARAM lParam)
 {
@@ -554,28 +650,12 @@
 
     if (infoPtr->hwndChild)
     {
-        RECT wndRect;
-        INT wndSizeScrollable;
-
         TRACE("[%04x] hwndChild=%04x\n", hwnd, infoPtr->hwndChild);
 
-        GetWindowRect(hwnd, &wndRect);
-        wndSizeScrollable = infoPtr->bHorizontal ?
-                            wndRect.right - wndRect.left :
-                            wndRect.bottom - wndRect.top;
-
-        infoPtr->nPos = 0;
-        infoPtr->nDelta = wndSizeScrollable;
-
-        PAGER_CalcSize(hwnd, &infoPtr->nWidth, TRUE);
-        PAGER_CalcSize(hwnd, &infoPtr->nHeight, FALSE);
-
-        /* adjust non-scrollable dimension to fit the child */
-        SetWindowPos(hwnd, 0,
-                     0,0,
-                     infoPtr->bHorizontal ? wndSizeScrollable : infoPtr->nWidth,
-                     infoPtr->bHorizontal ? infoPtr->nHeight : wndSizeScrollable, 
-                     SWP_FRAMECHANGED | SWP_NOMOVE | SWP_NOZORDER);
+        if (infoPtr->bHorizontal)
+            PAGER_SetFixedHeight(hwnd, infoPtr);
+        else
+           PAGER_SetFixedWidth(hwnd, infoPtr);
 
         /* position child within the page scroller */
         SetWindowPos(infoPtr->hwndChild, HWND_TOP,
@@ -593,6 +673,7 @@
 {
     PAGER_INFO *infoPtr = PAGER_GetInfoPtr (hwnd);
     NMPGSCROLL nmpgScroll;
+	RECT rcWnd;
 
     if (infoPtr->hwndChild)
     {
@@ -601,32 +682,36 @@
         nmpgScroll.hdr.idFrom   = GetWindowLongA (hwnd, GWL_ID);
         nmpgScroll.hdr.code = PGN_SCROLL;
 
+        GetWindowRect(hwnd, &rcWnd);  
         GetClientRect(hwnd, &nmpgScroll.rcParent);  
         nmpgScroll.iXpos = nmpgScroll.iYpos = 0;
         nmpgScroll.iDir = dir;
-        nmpgScroll.iScroll = infoPtr->nDelta;
 
         if (infoPtr->bHorizontal)
+        {
+            nmpgScroll.iScroll = rcWnd.right - rcWnd.left;
             nmpgScroll.iXpos = infoPtr->nPos;
+        }
         else
-            nmpgScroll.iYpos = infoPtr->nPos;
-
-        TRACE("[%04x] sending PGN_SCROLL\n", hwnd);
+        {
+            nmpgScroll.iScroll = rcWnd.bottom - rcWnd.top;
+              nmpgScroll.iYpos = infoPtr->nPos;
+        }
+        nmpgScroll.iScroll -= 2*infoPtr->nButtonSize;
+  
         SendMessageA (hwnd, WM_NOTIFY,
                     (WPARAM)nmpgScroll.hdr.idFrom, (LPARAM)&nmpgScroll);
+  
+        TRACE("[%04x] PGN_SCROLL returns iScroll=%d\n", hwnd, nmpgScroll.iScroll);
 
-        if (infoPtr->nDelta != nmpgScroll.iScroll)
+        if (nmpgScroll.iScroll > 0)
         {
-            TRACE("delta changing from %d to %d\n",
-            infoPtr->nDelta, nmpgScroll.iScroll);
-            infoPtr->nDelta = nmpgScroll.iScroll;
+            if (dir == PGF_SCROLLLEFT || dir == PGF_SCROLLUP)
+                PAGER_SetPos(hwnd, infoPtr->nPos - nmpgScroll.iScroll, TRUE);
+            else
+                PAGER_SetPos(hwnd, infoPtr->nPos + nmpgScroll.iScroll, TRUE);
         }
-
-        if (dir == PGF_SCROLLLEFT || dir == PGF_SCROLLUP)
-            PAGER_SetPos(hwnd, infoPtr->nPos - infoPtr->nDelta, TRUE);
-        else
-            PAGER_SetPos(hwnd, infoPtr->nPos + infoPtr->nDelta, TRUE);
-    }
+	}
 }
 
 static LRESULT
@@ -634,6 +719,8 @@
 {
     PAGER_INFO *infoPtr;
     DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
+    RECT rect;
+
     SetWindowLongA(hwnd, GWL_STYLE, dwStyle & WS_CLIPCHILDREN);
 
     /* allocate memory for info structure */
@@ -642,6 +729,7 @@
 
     /* set default settings */
     infoPtr->hwndChild = (HWND)NULL;
+    infoPtr->bNoResize = dwStyle & CCS_NORESIZE;
     infoPtr->clrBk = GetSysColor(COLOR_BTNFACE);
     infoPtr->nBorder = 0;
     infoPtr->nButtonSize = 12;
@@ -667,6 +755,20 @@
 
     infoPtr->bHorizontal = dwStyle & PGS_HORZ;
 
+    GetWindowRect(hwnd, &rect);
+    if (infoPtr->bHorizontal)
+    {
+        infoPtr->nHeight = rect.bottom - rect.top;
+        TRACE("height = %d %s\n", infoPtr->nHeight,
+		        infoPtr->bNoResize ? "CCS_NORESIZE" : "");
+    }
+    else
+    {
+        infoPtr->nWidth = rect.right - rect.left;
+        TRACE("width = %d %s\n", infoPtr->nWidth,
+		        infoPtr->bNoResize ? "CCS_NORESIZE" : "");
+    }
+
     TRACE("[%04x] orientation = %s\n", hwnd,
                   infoPtr->bHorizontal ? "PGS_HORZ" : "PGS_VERT");
 
@@ -687,15 +789,15 @@
 static LRESULT
 PAGER_NCCalcSize(HWND hwnd, WPARAM wParam, LPARAM lParam)
 {
-    PAGER_INFO *infoPtr = PAGER_GetInfoPtr (hwnd);                                                                         
+    PAGER_INFO *infoPtr = PAGER_GetInfoPtr (hwnd);
+    LPRECT lpRect = (LPRECT)lParam;
     /*
      * lParam points to a RECT struct.  On entry, the struct
      * contains the proposed wnd rectangle for the window. 
      * On exit, the struct should contain the screen
      * coordinates of the corresponding window's client area.
      */
-    LPRECT lpRect = (LPRECT)lParam;
-
+	
     if (infoPtr->bHorizontal)
     {
         if (infoPtr->TLbtnState) /* != PGF_INVISIBLE */
@@ -913,9 +1015,6 @@
 
     TRACE("[%04x]\n", hwnd);
 	
-    if (infoPtr->nDelta <= 0)
-        return FALSE;
-
     hit = PAGER_HitTest(hwnd, &pt);
 
     /* put btn in DEPRESSED state */
@@ -985,24 +1084,19 @@
 
 
 static LRESULT
-PAGER_Size (HWND hwnd)
+PAGER_Size (HWND hwnd, WPARAM wParam, LPARAM lParam)
 {
     /* note that WM_SIZE is sent whenever NCCalcSize resizes the client wnd */
 
     PAGER_INFO *infoPtr = PAGER_GetInfoPtr (hwnd);
-    RECT wndRect;
-    GetWindowRect(hwnd, &wndRect);
+    TRACE("[%04x] %dx%d\n", hwnd, LOWORD(lParam), HIWORD(lParam));
 
-    infoPtr->nDelta = infoPtr->bHorizontal ?
-                      wndRect.right - wndRect.left :
-                      wndRect.bottom - wndRect.top;
-    infoPtr->nDelta -= 2*infoPtr->nButtonSize;
-	
-    TRACE("[%04x] nDelta=%d\n", hwnd, infoPtr->nDelta);
+    if (infoPtr->bHorizontal)
+        infoPtr->nHeight = HIWORD(lParam);
+    else
+        infoPtr->nWidth = LOWORD(lParam);
 
-    PAGER_PositionChildWnd(hwnd, infoPtr);
-	
-    return TRUE;
+    return PAGER_RecalcSize(hwnd);
 }
 
 
@@ -1061,10 +1155,13 @@
             return PAGER_Destroy (hwnd, wParam, lParam);
 
         case WM_SIZE:
-            return PAGER_Size (hwnd);
+            return PAGER_Size (hwnd, wParam, lParam);
 
         case WM_NCPAINT:
             return PAGER_NCPaint (hwnd, wParam, lParam);
+
+        case WM_WINDOWPOSCHANGING:
+            return PAGER_HandleWindowPosChanging (hwnd, (WINDOWPOS*)lParam);
 
         case WM_NCCALCSIZE:
             return PAGER_NCCalcSize (hwnd, wParam, lParam);




More information about the wine-devel mailing list