Trackbar updates

Dimitrie O. Paun dpaun at rogers.com
Thu Sep 12 16:34:31 CDT 2002


Uff. These updates complete the trackbar (feature wise).

I've worked like a dog for days to complete this beast,
and I've started with a working version! It just proves,
once again, the 80/20 rule, I guess, but it also shows
how much work, and effort is required to complete things,
(particularly in Wine).

And mind you: while the features are all there (as of
commctrl 6.0), some of them are untested (e.g. custom draw),
as I don't have apps using them, so I can not even say,
after all this work, that it's bug free!

The stupid thing is over 1700 lines, with almost no
comments in the source, and a compact coding style.
If this is what it takes to get a 100% feature complete
control, what's gonna happen to the listview? End up
with 100,000 lines?

I am tired. Here it goes:

ChangeLog
  -- implement custom draw support
  -- fix thumb drawing
  -- some cleanups, reorganizations, etc.

Index: dlls/comctl32/trackbar.c
===================================================================
RCS file: /var/cvs/wine/dlls/comctl32/trackbar.c,v
retrieving revision 1.38
diff -u -r1.38 trackbar.c
--- dlls/comctl32/trackbar.c	12 Sep 2002 00:51:29 -0000	1.38
+++ dlls/comctl32/trackbar.c	12 Sep 2002 21:05:29 -0000
@@ -19,8 +19,6 @@
  * License along with this library; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  *
- * TODO:
- *   - custom draw notifications
  */
 
 #include <stdio.h>
@@ -88,6 +86,14 @@
 
 static BOOL TRACKBAR_SendNotify (TRACKBAR_INFO *infoPtr, UINT code);
 
+static inline int 
+notify_customdraw(NMCUSTOMDRAW *pnmcd, int stage)
+{
+    pnmcd->dwDrawStage = stage;
+    return SendMessageW (GetParent(pnmcd->hdr.hwndFrom), WM_NOTIFY, 
+		         pnmcd->hdr.idFrom, (LPARAM)pnmcd);
+}
+
 static void TRACKBAR_RecalculateTics (TRACKBAR_INFO *infoPtr)
 {
     int i, tic, nrTics;
@@ -283,17 +289,21 @@
 }
 
 static void
-TRACKBAR_InvalidateThumbMove (TRACKBAR_INFO *infoPtr, LONG oldPos, LONG newPos)
+TRACKBAR_InvalidateThumb (TRACKBAR_INFO *infoPtr, LONG thumbPos)
 {
-    RECT oldThumb;
-    RECT newThumb;
+    RECT rcThumb;
+
+    TRACKBAR_CalcThumb(infoPtr, thumbPos, &rcThumb);
+    InflateRect(&rcThumb, 1, 1);
+    InvalidateRect(infoPtr->hwndSelf, &rcThumb, FALSE);
+}
 
-    TRACKBAR_CalcThumb(infoPtr, oldPos, &oldThumb);
-    TRACKBAR_CalcThumb(infoPtr, newPos, &newThumb);
-    InflateRect(&oldThumb, 1, 1);
-    InflateRect(&newThumb, 1, 1);
-    InvalidateRect(infoPtr->hwndSelf, &oldThumb, FALSE);
-    InvalidateRect(infoPtr->hwndSelf, &newThumb, FALSE);
+static inline void
+TRACKBAR_InvalidateThumbMove (TRACKBAR_INFO *infoPtr, LONG oldPos, LONG newPos)
+{
+    TRACKBAR_InvalidateThumb (infoPtr, oldPos);
+    if (newPos != oldPos)
+        TRACKBAR_InvalidateThumb (infoPtr, newPos);
 }
 
 static BOOL inline
@@ -356,10 +366,21 @@
 
 /* Trackbar drawing code. I like my spaghetti done milanese.  */
 
-/* ticPos is in tic-units, not in pixels */
+static void
+TRACKBAR_DrawChannel (TRACKBAR_INFO *infoPtr, HDC hdc, DWORD dwStyle)
+{
+    RECT rcChannel = infoPtr->rcChannel;
+
+    DrawEdge (hdc, &rcChannel, EDGE_SUNKEN, BF_RECT | BF_ADJUST);
+    if (dwStyle & TBS_ENABLESELRANGE) {		 /* fill the channel */
+        FillRect (hdc, &rcChannel, GetStockObject(WHITE_BRUSH));
+	if (TRACKBAR_HasSelection(infoPtr))
+	    FillRect (hdc, &infoPtr->rcSelection, GetSysColorBrush(COLOR_HIGHLIGHT));
+    }
+}
 
 static void
-TRACKBAR_DrawTic (TRACKBAR_INFO *infoPtr, HDC hdc, LONG ticPos, int flags)
+TRACKBAR_DrawOneTic (TRACKBAR_INFO *infoPtr, HDC hdc, LONG ticPos, int flags)
 {
     int x, y, ox, oy, range, side, offset = 5, indent = 0, len = 3;
     RECT rcTics;
@@ -431,16 +452,46 @@
 }
 
 
-static void
-TRACKBAR_DrawTics (TRACKBAR_INFO *infoPtr, HDC hdc, LONG ticPos, int flags)
+static inline void
+TRACKBAR_DrawTic (TRACKBAR_INFO *infoPtr, HDC hdc, LONG ticPos, int flags)
 {
-    TRACE("\n");
-
     if ((flags & (TBS_LEFT | TBS_TOP)) || (flags & TBS_BOTH))
-        TRACKBAR_DrawTic (infoPtr, hdc, ticPos, flags | TBS_LEFT);
+        TRACKBAR_DrawOneTic (infoPtr, hdc, ticPos, flags | TBS_LEFT);
 
     if (!(flags & (TBS_LEFT | TBS_TOP)) || (flags & TBS_BOTH))
-        TRACKBAR_DrawTic (infoPtr, hdc, ticPos, flags);
+        TRACKBAR_DrawOneTic (infoPtr, hdc, ticPos, flags);
+}
+
+static void
+TRACKBAR_DrawTics (TRACKBAR_INFO *infoPtr, HDC hdc, DWORD dwStyle)
+{
+    int i, ticFlags = dwStyle & 0x0f;
+    LOGPEN ticPen = { PS_SOLID, {1, 0}, GetSysColor (COLOR_3DDKSHADOW) };
+    HPEN hOldPen, hTicPen;
+    
+    /* create the pen to draw the tics with */   
+    hTicPen = CreatePenIndirect(&ticPen);
+    hOldPen = hTicPen ? SelectObject(hdc, hTicPen) : 0;
+
+    /* actually draw the tics */
+    for (i=0; i<infoPtr->uNumTics; i++)
+        TRACKBAR_DrawTic (infoPtr, hdc, infoPtr->tics[i], ticFlags);
+
+    TRACKBAR_DrawTic (infoPtr, hdc, infoPtr->lRangeMin, ticFlags | TIC_EDGE);
+    TRACKBAR_DrawTic (infoPtr, hdc, infoPtr->lRangeMax, ticFlags | TIC_EDGE);
+
+    if ((dwStyle & TBS_ENABLESELRANGE) && TRACKBAR_HasSelection(infoPtr)) {
+        TRACKBAR_DrawTic (infoPtr, hdc, infoPtr->lSelMin,
+                          ticFlags | TIC_SELECTIONMARKMIN);
+        TRACKBAR_DrawTic (infoPtr, hdc, infoPtr->lSelMax,
+                          ticFlags | TIC_SELECTIONMARKMAX);
+    }
+    
+    /* clean up the pen, if we created one */
+    if (hTicPen) {
+	SelectObject(hdc, hOldPen);
+	DeleteObject(hTicPen);
+    }
 }
 
 static void
@@ -452,10 +503,12 @@
     int BlackUntil = 3;
     int PointCount = 6;
     POINT points[6];
+    int fillClr;
 
     static INT PointDepth = 4;
 
-    oldbr = SelectObject (hdc, GetSysColorBrush(COLOR_BTNFACE));
+    fillClr = infoPtr->flags & TB_DRAG_MODE ? COLOR_BTNHILIGHT : COLOR_BTNFACE;
+    oldbr = SelectObject (hdc, GetSysColorBrush(fillClr));
     SetPolyFillMode (hdc, WINDING);
 
     if (dwStyle & TBS_BOTH)
@@ -619,10 +672,11 @@
 TRACKBAR_Refresh (TRACKBAR_INFO *infoPtr, HDC hdcDst)
 {
     DWORD dwStyle = GetWindowLongW (infoPtr->hwndSelf, GWL_STYLE);
-    RECT rcClient, rcChannel = infoPtr->rcChannel;
+    RECT rcClient;
     HDC hdc;
     HBITMAP hOldBmp = 0, hOffScreenBmp = 0;
-    int i;
+    NMCUSTOMDRAW nmcd;
+    int gcdrf, icdrf;
 
     if (infoPtr->flags & TB_THUMBCHANGED) {
         TRACKBAR_UpdateThumb (infoPtr);
@@ -635,6 +689,8 @@
     if (infoPtr->flags & TB_DRAG_MODE)
         TRACKBAR_UpdateToolTip (infoPtr);
 
+    infoPtr->flags &= ~ (TB_THUMBCHANGED | TB_SELECTIONCHANGED);
+
     GetClientRect (infoPtr->hwndSelf, &rcClient);
     
     /* try to render offscreen, if we fail, carrry onscreen */
@@ -651,48 +707,74 @@
 	hdc = hdcDst;
     }
 
-    infoPtr->flags &= ~ (TB_THUMBCHANGED | TB_SELECTIONCHANGED);
-
+    ZeroMemory(&nmcd, sizeof(nmcd));
+    nmcd.hdr.hwndFrom = infoPtr->hwndSelf;
+    nmcd.hdr.idFrom = GetWindowLongW (infoPtr->hwndSelf, GWL_ID);
+    nmcd.hdr.code = NM_CUSTOMDRAW;
+    nmcd.hdc = hdc;
+
+    /* start the paint cycle */
+    nmcd.rc = rcClient;
+    gcdrf = notify_customdraw(&nmcd, CDDS_PREPAINT);
+    if (gcdrf & CDRF_SKIPDEFAULT) goto cleanup;
+    
     /* Erase backbround */
-    FillRect (hdc, &rcClient, GetSysColorBrush(COLOR_BTNFACE));
+    if (gcdrf == CDRF_DODEFAULT ||
+        notify_customdraw(&nmcd, CDDS_PREERASE) != CDRF_SKIPDEFAULT) {
+	FillRect (hdc, &rcClient, GetSysColorBrush(COLOR_BTNFACE));
+        if (gcdrf != CDRF_DODEFAULT)
+	    notify_customdraw(&nmcd, CDDS_POSTERASE);
+    }
     
     /* draw channel */
-    DrawEdge (hdc, &rcChannel, EDGE_SUNKEN, BF_RECT | BF_ADJUST);
-    if (dwStyle & TBS_ENABLESELRANGE) {		 /* fill the channel */
-        FillRect (hdc, &rcChannel, GetStockObject(WHITE_BRUSH));
-	if (TRACKBAR_HasSelection(infoPtr))
-	    FillRect (hdc, &infoPtr->rcSelection, GetSysColorBrush(COLOR_HIGHLIGHT));
+    if (gcdrf & CDRF_NOTIFYITEMDRAW) {
+        nmcd.dwItemSpec = TBCD_CHANNEL;
+	nmcd.uItemState = CDIS_DEFAULT;
+	nmcd.rc = infoPtr->rcChannel;
+	icdrf = notify_customdraw(&nmcd, CDDS_ITEMPREPAINT);
+    } else icdrf = CDRF_DODEFAULT;
+    if ( !(icdrf & CDRF_SKIPDEFAULT) ) {
+	TRACKBAR_DrawChannel (infoPtr, hdc, dwStyle);
+	if (icdrf & CDRF_NOTIFYPOSTPAINT)
+	    notify_customdraw(&nmcd, CDDS_ITEMPOSTPAINT);
     }
 
 
     /* draw tics */
     if (!(dwStyle & TBS_NOTICKS)) {
-        int ticFlags = dwStyle & 0x0f;
-	LOGPEN ticPen = { PS_SOLID, {1, 0}, GetSysColor (COLOR_3DDKSHADOW) };
-	HPEN hOldPen, hTicPen;
-       
-	hTicPen = CreatePenIndirect(&ticPen);
-	hOldPen = hTicPen ? SelectObject(hdc, hTicPen) : 0;
-
-        for (i=0; i<infoPtr->uNumTics; i++)
-            TRACKBAR_DrawTics (infoPtr, hdc, infoPtr->tics[i], ticFlags);
-
-    	TRACKBAR_DrawTics (infoPtr, hdc, infoPtr->lRangeMin, ticFlags | TIC_EDGE);
-    	TRACKBAR_DrawTics (infoPtr, hdc, infoPtr->lRangeMax, ticFlags | TIC_EDGE);
-
-        if ((dwStyle & TBS_ENABLESELRANGE) && TRACKBAR_HasSelection(infoPtr)) {
-            TRACKBAR_DrawTics (infoPtr, hdc, infoPtr->lSelMin,
-                               ticFlags | TIC_SELECTIONMARKMIN);
-            TRACKBAR_DrawTics (infoPtr, hdc, infoPtr->lSelMax,
-                               ticFlags | TIC_SELECTIONMARKMAX);
-        }
-	if (hTicPen) SelectObject(hdc, hOldPen);
+    	if (gcdrf & CDRF_NOTIFYITEMDRAW) {
+            nmcd.dwItemSpec = TBCD_TICS;
+	    nmcd.uItemState = CDIS_DEFAULT;
+	    nmcd.rc = rcClient;
+	    icdrf = notify_customdraw(&nmcd, CDDS_ITEMPREPAINT);
+        } else icdrf = CDRF_DODEFAULT;
+	if ( !(icdrf & CDRF_SKIPDEFAULT) ) {
+	    TRACKBAR_DrawTics (infoPtr, hdc, dwStyle);
+	    if (icdrf & CDRF_NOTIFYPOSTPAINT)
+		notify_customdraw(&nmcd, CDDS_ITEMPOSTPAINT);
+	}
     }
-
+    
     /* draw thumb */
-    if (!(dwStyle & TBS_NOTHUMB))
-        TRACKBAR_DrawThumb(infoPtr, hdc, dwStyle);
+    if (!(dwStyle & TBS_NOTHUMB)) {
+	if (gcdrf & CDRF_NOTIFYITEMDRAW) {
+	    nmcd.dwItemSpec = TBCD_THUMB;
+	    nmcd.uItemState = infoPtr->flags & TB_DRAG_MODE ? CDIS_HOT : CDIS_DEFAULT;
+	    nmcd.rc = infoPtr->rcThumb;
+	    icdrf = notify_customdraw(&nmcd, CDDS_ITEMPREPAINT);
+	} else icdrf = CDRF_DODEFAULT;
+	if ( !(icdrf & CDRF_SKIPDEFAULT) ) {
+            TRACKBAR_DrawThumb(infoPtr, hdc, dwStyle);
+	    if (icdrf & CDRF_NOTIFYPOSTPAINT)
+		notify_customdraw(&nmcd, CDDS_ITEMPOSTPAINT);
+	}
+    }
 
+    /* finish up the painting */
+    if (gcdrf & CDRF_NOTIFYPOSTPAINT)
+	notify_customdraw(&nmcd, CDDS_POSTPAINT);
+    
+cleanup:
     /* cleanup, if we rendered offscreen */
     if (hdc != hdcDst) {
 	BitBlt(hdcDst, 0, 0, rcClient.right, rcClient.bottom, hdc, 0, 0, SRCCOPY);
@@ -1226,6 +1308,7 @@
         SetCapture (infoPtr->hwndSelf);
 	TRACKBAR_UpdateToolTip (infoPtr);
 	TRACKBAR_ActivateToolTip (infoPtr, TRUE);
+	TRACKBAR_InvalidateThumb(infoPtr, infoPtr->lPos);
     } else {
 	LONG dir = TRACKBAR_GetAutoPageDirection(infoPtr, clickPoint);
 	if (dir == 0) return 0;
@@ -1248,6 +1331,7 @@
         ReleaseCapture ();
 	notify_releasedcapture(infoPtr);
         TRACKBAR_ActivateToolTip(infoPtr, FALSE);
+	TRACKBAR_InvalidateThumb(infoPtr, infoPtr->lPos);
     }
     if (infoPtr->flags & TB_AUTO_PAGE) {
 	KillTimer (infoPtr->hwndSelf, TB_REFRESH_TIMER);




More information about the wine-patches mailing list