Trackbar size fixes, take 2

Duane Clark dclark at akamail.com
Thu Jul 31 13:53:08 CDT 2003


Since no one else has submitted something, here is a second try, along 
with a long explanation of what was fixed and why.

The only difference from my previous patch is that the initial size of 
the thumb is limited to not be greater than "21". I tested on Win2K and 
found that the initial size of the thumb is always 21, though it can 
then be explicitely changed (which works correctly in Wine). However I 
have one application (earthquake) where this results in a thumb that is 
too big. I suspect there is an initialization bug in Wine relating to 
when the thumb size is set. Since shrinking the thumb size for narrow 
rectangles will likely always be desired, this hack should be fine until 
I figure out what is wrong in the initialization.

Some changes are cosmetic. Once the thumb length is set, all the rest of 
the dimensions of the thumb are determined from that. Wine has had 
several different versions of that recently, including the use of 
floating point arithmetic!, but none match Windows. This patch correctly 
sets the thumb width in proportion to the length, and correctly draws 
the bevels at 45 degrees.

The other main problem in the current code is that the channel length 
was assumed to be the difference between the first and last tic marks. 
This is incorrect. The channel length should be the length of the 
channel as drawn. The first and last tic marks then should be inset by 
half the width of the thumb. Most of this patch corrects all the places 
in the code where this problem exists.

Changelog:
	The initial size of the thumb should be a fixed number.
	Correctly draw the thumb as in Windows.
	The first and last tic marks should be inset from the
	channel length by half the thumb width.

-------------- next part --------------
Index: dlls/comctl32/trackbar.c
===================================================================
RCS file: /home/wine/wine/dlls/comctl32/trackbar.c,v
retrieving revision 1.49
diff -u -r1.49 trackbar.c
--- dlls/comctl32/trackbar.c	16 Jun 2003 19:39:27 -0000	1.49
+++ dlls/comctl32/trackbar.c	31 Jul 2003 17:47:15 -0000
@@ -139,15 +139,17 @@
 TRACKBAR_ConvertPlaceToPosition (TRACKBAR_INFO *infoPtr, int place,
                                  int vertical)
 {
-    double range, width, pos;
+    double range, width, pos, offsetthumb;
 
     range = infoPtr->lRangeMax - infoPtr->lRangeMin;
     if (vertical) {
-    	width = infoPtr->rcChannel.bottom - infoPtr->rcChannel.top;
-        pos = (range*(place - infoPtr->rcChannel.top)) / width;
+        offsetthumb = (infoPtr->rcThumb.bottom - infoPtr->rcThumb.top)/2 + 1;
+    	width = infoPtr->rcChannel.bottom - infoPtr->rcChannel.top - (offsetthumb * 2);
+        pos = (range*(place - infoPtr->rcChannel.top - offsetthumb)) / width;
     } else {
-    	width = infoPtr->rcChannel.right - infoPtr->rcChannel.left;
-        pos = (range*(place - infoPtr->rcChannel.left)) / width;
+        offsetthumb = (infoPtr->rcThumb.right - infoPtr->rcThumb.left)/2 + 1;
+    	width = infoPtr->rcChannel.right - infoPtr->rcChannel.left - (offsetthumb * 2);
+        pos = (range*(place - infoPtr->rcChannel.left - offsetthumb)) / width;
     }
     pos += infoPtr->lRangeMin;
     if (pos > infoPtr->lRangeMax)
@@ -224,22 +226,26 @@
 
     GetClientRect (infoPtr->hwndSelf, &lpRect);
 
-    offsetthumb = (int)(infoPtr->uThumbLen/4.5);
+    offsetthumb = infoPtr->uThumbLen / 4;
     offsetedge  = offsetthumb + 3;
     cyChannel   = (dwStyle & TBS_ENABLESELRANGE) ? (offsetthumb+1)*3 : 4;
     if (dwStyle & TBS_VERT) {
         channel->top    = lpRect.top + offsetedge;
         channel->bottom = lpRect.bottom - offsetedge;
-        channel->left = lpRect.left + offsetthumb - cyChannel;
-        if (dwStyle & (TBS_BOTH | TBS_LEFT))
-            channel->left += (lpRect.right-lpRect.left-offsetthumb-cyChannel)/2;
+        channel->left = lpRect.left + (infoPtr->uThumbLen / 2) - 1;
+        if (dwStyle & TBS_BOTH)
+            channel->left += 9;
+        else if (dwStyle & TBS_LEFT)
+            channel->left += 10;
         channel->right = channel->left + cyChannel;
     } else {
         channel->left = lpRect.left + offsetedge;
         channel->right = lpRect.right - offsetedge;
-        channel->top = lpRect.top + offsetedge;
-        if (dwStyle & (TBS_BOTH | TBS_TOP))
-            channel->top += (lpRect.bottom-lpRect.top-offsetedge-cyChannel)/2;
+        channel->top = lpRect.top + (infoPtr->uThumbLen / 2) - 1;
+        if (dwStyle & TBS_BOTH)
+            channel->top += 9;
+        else if (dwStyle & TBS_TOP)
+            channel->top += 10;
         channel->bottom   = channel->top + cyChannel;
     }
 }
@@ -247,43 +253,42 @@
 static void
 TRACKBAR_CalcThumb (TRACKBAR_INFO *infoPtr, LONG lPos, RECT *thumb)
 {
-    int range, width, height, thumbdepth, ticOffset = 5 + 2; /* 5 is length of tic, 2 is extra indent */
+    int range, width, height, thumbwidth;
     DWORD dwStyle = GetWindowLongW (infoPtr->hwndSelf, GWL_STYLE);
     RECT lpRect;
 
     range = infoPtr->lRangeMax - infoPtr->lRangeMin;
-    thumbdepth = ((int)(infoPtr->uThumbLen / 4.5)) + 2;
+    /* This calculates the thumb width as on Win2K */
+    thumbwidth = (infoPtr->uThumbLen / 2) | 1;
 
     if (!range) range = 1;
 
     GetClientRect(infoPtr->hwndSelf, &lpRect);
     if (dwStyle & TBS_VERT)
     {
-    	height = infoPtr->rcChannel.bottom - infoPtr->rcChannel.top;
+    	height = infoPtr->rcChannel.bottom - infoPtr->rcChannel.top - thumbwidth - 1;
 
         if (dwStyle & (TBS_BOTH | TBS_LEFT))
-            thumb->left = (lpRect.right - lpRect.left - infoPtr->uThumbLen)/2 + ticOffset;
+            thumb->left = 10;
         else
             thumb->left = 2;
-        thumb->right = thumb->left + infoPtr->uThumbLen - (ticOffset * 2);
+        thumb->right = thumb->left + infoPtr->uThumbLen;
         thumb->top = infoPtr->rcChannel.top +
-                     (height*(lPos - infoPtr->lRangeMin))/range -
-                     thumbdepth/2;
-        thumb->bottom = thumb->top + thumbdepth;
+                     (height*(lPos - infoPtr->lRangeMin))/range;
+        thumb->bottom = thumb->top + thumbwidth;
     }
     else
     {
-    	width = infoPtr->rcChannel.right - infoPtr->rcChannel.left;
+    	width = infoPtr->rcChannel.right - infoPtr->rcChannel.left - thumbwidth - 1;
 
         thumb->left = infoPtr->rcChannel.left +
-                      (width*(lPos - infoPtr->lRangeMin))/range -
-                      thumbdepth/2;
-        thumb->right = thumb->left + thumbdepth;
+                      (width*(lPos - infoPtr->lRangeMin))/range;
+        thumb->right = thumb->left + thumbwidth;
         if (dwStyle & (TBS_BOTH | TBS_TOP))
-            thumb->top = (lpRect.bottom - lpRect.top - infoPtr->uThumbLen)/2;
+            thumb->top = 10;
         else
             thumb->top = 2;
-        thumb->bottom = thumb->top + infoPtr->uThumbLen - 20; /* double the bottom padding for the ticks, chosen to resemble native control */
+        thumb->bottom = thumb->top + infoPtr->uThumbLen;
     }
 }
 
@@ -381,16 +386,6 @@
 TRACKBAR_DrawChannel (TRACKBAR_INFO *infoPtr, HDC hdc, DWORD dwStyle)
 {
     RECT rcChannel = infoPtr->rcChannel;
-    int runOver = 5;
-
-    /* make the channel slightly overrun the last tick, to make it look more like the native control, and less "clunky" */
-    if (dwStyle & TBS_VERT) {
-	rcChannel.top -= runOver;
-	rcChannel.bottom += runOver;
-    } else {
-	rcChannel.left -= runOver;
-	rcChannel.right += runOver;
-    }
 
     DrawEdge (hdc, &rcChannel, EDGE_SUNKEN, BF_RECT | BF_ADJUST);
     if (dwStyle & TBS_ENABLESELRANGE) {		 /* fill the channel */
@@ -403,19 +398,22 @@
 static void
 TRACKBAR_DrawOneTic (TRACKBAR_INFO *infoPtr, HDC hdc, LONG ticPos, int flags)
 {
-    int x, y, ox, oy, range, side, offset = 5, indent = 0, len = 3;
+    int x, y, ox, oy, range, side, indent = 0, len = 3;
+    int offsetthumb;
     RECT rcTics;
 
-    TRACE("\n");
-
-    GetClientRect(infoPtr->hwndSelf, &rcTics);
     if (flags & TBS_VERT) {
-	rcTics.top    = infoPtr->rcChannel.top;
-	rcTics.bottom = infoPtr->rcChannel.bottom;
+        offsetthumb = (infoPtr->rcThumb.bottom - infoPtr->rcThumb.top)/2 + 1;
+	rcTics.left = infoPtr->rcThumb.left - 2;
+	rcTics.right = infoPtr->rcThumb.right + 2;
+	rcTics.top    = infoPtr->rcChannel.top + offsetthumb;
+	rcTics.bottom = infoPtr->rcChannel.bottom - offsetthumb;
     } else {
-	rcTics.left   = infoPtr->rcChannel.left;
-	rcTics.right  = infoPtr->rcChannel.right;
-	rcTics.bottom -= 10; /* value obtained by guesswork and experimentation */
+        offsetthumb = (infoPtr->rcThumb.right - infoPtr->rcThumb.left)/2 + 1;
+	rcTics.left   = infoPtr->rcChannel.left + offsetthumb;
+	rcTics.right  = infoPtr->rcChannel.right - offsetthumb;
+	rcTics.top = infoPtr->rcThumb.top - 2;
+	rcTics.bottom = infoPtr->rcThumb.bottom + 2;
     }
 
     if (flags & (TBS_TOP | TBS_LEFT)) {
@@ -441,13 +439,13 @@
     if (flags & TBS_VERT) {
 	int height = rcTics.bottom - rcTics.top;
 	y = rcTics.top + (height*(ticPos - infoPtr->lRangeMin))/range;
-	x -= (offset + 2) * side;
-	y += indent;
+/*	x -= (offset + 2) * side;
+	y += indent;*/
     } else {
         int width = rcTics.right - rcTics.left;
         x = rcTics.left + (width*(ticPos - infoPtr->lRangeMin))/range;
-	x += indent;
-	y -= (offset + 2) * side;
+/*	x += indent;
+	y -= (offset + 2) * side;*/
     }
 
     ox = x;
@@ -483,7 +481,7 @@
         TRACKBAR_DrawOneTic (infoPtr, hdc, ticPos, flags | TBS_LEFT);
 
     if (!(flags & (TBS_LEFT | TBS_TOP)) || (flags & TBS_BOTH))
-        TRACKBAR_DrawOneTic (infoPtr, hdc, ticPos, flags);
+        TRACKBAR_DrawOneTic (infoPtr, hdc, ticPos, flags & ~TBS_LEFT);
 }
 
 static void
@@ -528,8 +526,8 @@
     int PointCount = 6;
     POINT points[6];
     int fillClr;
+    int PointDepth;
 
-    static INT PointDepth = 4;
     fillClr = infoPtr->flags & TB_DRAG_MODE ? COLOR_BTNHILIGHT : COLOR_BTNFACE;
     oldbr = SelectObject (hdc, GetSysColorBrush(fillClr));
     SetPolyFillMode (hdc, WINDING);
@@ -553,6 +551,7 @@
     {
         if (dwStyle & TBS_VERT)
         {
+          PointDepth = (thumb.bottom - thumb.top) / 2;
           if (dwStyle & TBS_LEFT)
           {
             points[0].x=thumb.right;
@@ -562,7 +561,7 @@
             points[2].x=thumb.left + PointDepth;
             points[2].y=thumb.bottom;
             points[3].x=thumb.left;
-            points[3].y=(thumb.bottom - thumb.top) / 2 + thumb.top;
+            points[3].y=(thumb.bottom - thumb.top) / 2 + thumb.top + 1;
             points[4].x=thumb.left + PointDepth;
             points[4].y=thumb.top;
             points[5].x=points[0].x;
@@ -572,7 +571,7 @@
           else
           {
             points[0].x=thumb.right;
-            points[0].y=(thumb.bottom - thumb.top) / 2 + thumb.top;
+            points[0].y=(thumb.bottom - thumb.top) / 2 + thumb.top + 1;
             points[1].x=thumb.right - PointDepth;
             points[1].y=thumb.bottom;
             points[2].x=thumb.left;
@@ -587,9 +586,10 @@
         }
         else
         {
+          PointDepth = (thumb.right - thumb.left) / 2;
           if (dwStyle & TBS_TOP)
           {
-            points[0].x=(thumb.right - thumb.left) / 2 + thumb.left ;
+            points[0].x=(thumb.right - thumb.left) / 2 + thumb.left + 1;
             points[0].y=thumb.top;
             points[1].x=thumb.right;
             points[1].y=thumb.top + PointDepth;
@@ -609,7 +609,7 @@
             points[0].y=thumb.top;
             points[1].x=thumb.right;
             points[1].y=thumb.bottom - PointDepth;
-            points[2].x=(thumb.right - thumb.left) / 2 + thumb.left ;
+            points[2].x=(thumb.right - thumb.left) / 2 + thumb.left + 1;
             points[2].y=thumb.bottom;
             points[3].x=thumb.left;
             points[3].y=thumb.bottom - PointDepth;
@@ -1234,8 +1234,10 @@
     if (dwStyle & TBS_VERT) {
 	infoPtr->uThumbLen = (rect.right - rect.left - 6);
     } else {
-	infoPtr->uThumbLen = (rect.bottom - rect.top);
+	infoPtr->uThumbLen = (rect.bottom - rect.top - 6);
     }
+    if (infoPtr->uThumbLen > 21)
+        infoPtr->uThumbLen = 21;
 
     TRACKBAR_CalcChannel (infoPtr);
     TRACKBAR_UpdateThumb (infoPtr);


More information about the wine-patches mailing list