Support PBS_MARQUE for progress bars

Thomas Weidenmueller wine-patches at reactsoft.com
Sun Jul 25 07:27:49 CDT 2004


Sorry, this patch should compile.
-------------- next part --------------
Index: dlls/comctl32/progress.c
===================================================================
RCS file: /home/wine/wine/dlls/comctl32/progress.c,v
retrieving revision 1.36
diff -u -r1.36 progress.c
--- dlls/comctl32/progress.c	11 Mar 2004 00:39:53 -0000	1.36
+++ dlls/comctl32/progress.c	25 Jul 2004 12:26:33 -0000
@@ -26,9 +26,6 @@
  * Unless otherwise noted, we believe this code to be complete, as per
  * the specification mentioned above.
  * If you discover missing features, or bugs, please note them below.
- * 
- * TODO
- *   --support PBS_MARQUE
  *
  */
 
@@ -59,7 +56,9 @@
 
 /* Control configuration constants */
 
-#define LED_GAP    2
+#define LED_GAP           2
+#define MARQUEE_LEDS      5
+#define ID_MARQUEE_TIMER  1
 
 /***********************************************************************
  * PROGRESS_Invalidate
@@ -156,51 +155,215 @@
     {
         if (dwStyle & PBS_VERTICAL)
         {
-            INT old_top = rect.top;
-            rect.top = rightBar;
-            FillRect(hdc, &rect, hbrBar);
-            rect.bottom = rect.top;
-            rect.top = old_top;
-            FillRect(hdc, &rect, hbrBk);
+            if (dwStyle & PBS_MARQUEE)
+            {
+                INT old_top, old_bottom;
+                old_top = rect.top;
+                old_bottom = rect.bottom;
+
+                leds = rect.bottom - rect.top;
+                ledMStart = (infoPtr->MarqueePos + MARQUEE_LEDS) - leds;
+                
+                if(ledMStart > 0)
+                {
+                    rect.top = max(rect.bottom - ledMStart, old_top);
+                    FillRect(hdc, &rect, hbrBar);
+                    rect.bottom = rect.top;
+                }
+                if(infoPtr->MarqueePos > 0)
+                {
+                    rect.top = max(old_bottom - infoPtr->MarqueePos, old_top);
+                    FillRect(hdc, &rect, hbrBk);
+                    rect.bottom = rect.top;
+                }
+                if(rect.top >= old_top)
+                {
+                    rect.top = max(rect.bottom - MARQUEE_LEDS, old_top);
+                    FillRect(hdc, &rect, hbrBar);
+                    rect.bottom = rect.top;
+                }
+                if(rect.top >= old_top)
+                {
+                    rect.top = old_top;
+                    FillRect(hdc, &rect, hbrBk);
+                }
+            }
+            else
+            {
+                INT old_top = rect.top;
+                rect.top = rightBar;
+                FillRect(hdc, &rect, hbrBar);
+                rect.bottom = rect.top;
+                rect.top = old_top;
+                FillRect(hdc, &rect, hbrBk);
+            }
         }
         else
         {
-            INT old_right = rect.right;
-            rect.right = rightBar;
-            FillRect(hdc, &rect, hbrBar);
-            rect.left = rect.right;
-            rect.right = old_right;
-            FillRect(hdc, &rect, hbrBk);
+            if (dwStyle & PBS_MARQUEE)
+            {
+                INT old_left, old_right;
+                old_left = rect.left;
+                old_right = rect.right;
+
+                leds = rect.right - rect.left;
+                ledMStart = (infoPtr->MarqueePos + MARQUEE_LEDS) - leds;
+                rect.right = rect.left;
+                
+                if(ledMStart > 0)
+                {
+                    rect.right = min(rect.left + ledMStart, old_right);
+                    FillRect(hdc, &rect, hbrBar);
+                    rect.left = rect.right;
+                }
+                if(infoPtr->MarqueePos > 0)
+                {
+                    rect.right = min(old_left + infoPtr->MarqueePos, old_right);
+                    FillRect(hdc, &rect, hbrBk);
+                    rect.left = rect.right;
+                }
+                if(rect.right < old_right)
+                {
+                    rect.right = min(rect.left + MARQUEE_LEDS, old_right);
+                    FillRect(hdc, &rect, hbrBar);
+                    rect.left = rect.right;
+                }
+                if(rect.right < old_right)
+                {
+                    rect.right = old_right;
+                    FillRect(hdc, &rect, hbrBk);
+                }
+            }
+            else
+            {
+                INT old_right = rect.right;
+                rect.right = rightBar;
+                FillRect(hdc, &rect, hbrBar);
+                rect.left = rect.right;
+                rect.right = old_right;
+                FillRect(hdc, &rect, hbrBk);
+            }
         }
     } else {
         if (dwStyle & PBS_VERTICAL) {
-            while(rect.bottom > rightBar) {
-                rect.top = rect.bottom - ledWidth;
-                if (rect.top < rightMost)
-                    rect.top = rightMost;
-                FillRect(hdc, &rect, hbrBar);
-                rect.bottom = rect.top;
-                rect.top -= LED_GAP;
-                if (rect.top <= rightBar) break;
-                FillRect(hdc, &rect, hbrBk);
-                rect.bottom = rect.top;
+            if (dwStyle & PBS_MARQUEE)
+            {
+                INT i, old_top, old_bottom;
+                old_top = rect.top;
+                old_bottom = rect.bottom;
+
+                leds = ((rect.bottom - rect.top) + (ledWidth + LED_GAP) - 1) / (ledWidth + LED_GAP);
+                ledMStart = (infoPtr->MarqueePos + MARQUEE_LEDS) - leds;
+                
+                while(ledMStart > 0)
+                {
+                    rect.top = max(rect.bottom - ledWidth, old_top);
+                    FillRect(hdc, &rect, hbrBar);
+                    rect.bottom = rect.top;
+                    rect.top -= LED_GAP;
+                    if (rect.top <= old_top) break;
+                    FillRect(hdc, &rect, hbrBk);
+                    rect.bottom = rect.top;
+                    ledMStart--;
+                }
+                if(infoPtr->MarqueePos > 0)
+                {
+                    rect.top = max(old_bottom - (infoPtr->MarqueePos * (ledWidth + LED_GAP)), old_top);
+                    FillRect(hdc, &rect, hbrBk);
+                    rect.bottom = rect.top;
+                }
+                for(i = 0; i < MARQUEE_LEDS && rect.top >= old_top; i++)
+                {
+                    rect.top = max(rect.bottom - ledWidth, old_top);
+                    FillRect(hdc, &rect, hbrBar);
+                    rect.bottom = rect.top;
+                    rect.top -= LED_GAP;
+                    if (rect.top <= old_top) break;
+                    FillRect(hdc, &rect, hbrBk);
+                    rect.bottom = rect.top;
+                }
+                if(rect.top >= old_top)
+                {
+                    rect.top = old_top;
+                    FillRect(hdc, &rect, hbrBk);
+                }
+            }
+            else
+            {
+                while(rect.bottom > rightBar) {
+                    rect.top = rect.bottom - ledWidth;
+                    if (rect.top < rightMost)
+                        rect.top = rightMost;
+                    FillRect(hdc, &rect, hbrBar);
+                    rect.bottom = rect.top;
+                    rect.top -= LED_GAP;
+                    if (rect.top <= rightBar) break;
+                    FillRect(hdc, &rect, hbrBk);
+                    rect.bottom = rect.top;
+                }
             }
             rect.top = rightMost;
             FillRect(hdc, &rect, hbrBk);
         } else {
-            while(rect.left < rightBar) {
-                rect.right = rect.left + ledWidth;
-                if (rect.right > rightMost)
-                    rect.right = rightMost;
-                FillRect(hdc, &rect, hbrBar);
-                rect.left = rect.right;
-                rect.right += LED_GAP;
-                if (rect.right >= rightBar) break;
+            if (dwStyle & PBS_MARQUEE)
+            {
+                INT i, old_right, old_left;
+                old_left = rect.left;
+                old_right = rect.right;
+
+                leds = ((rect.right - rect.left) + ledWidth - 1) / (ledWidth + LED_GAP);
+                ledMStart = (infoPtr->MarqueePos + MARQUEE_LEDS) - leds;
+                rect.right = rect.left;
+                
+                while(ledMStart > 0)
+                {
+                    rect.right = min(rect.left + ledWidth, old_right);
+                    FillRect(hdc, &rect, hbrBar);
+                    rect.left = rect.right;
+                    rect.right += LED_GAP;
+                    if (rect.right > old_right) break;
+                    FillRect(hdc, &rect, hbrBk);
+                    rect.left = rect.right;
+                    ledMStart--;
+                }
+                if(infoPtr->MarqueePos > 0)
+                {
+                    rect.right = min(old_left + (infoPtr->MarqueePos * (ledWidth + LED_GAP)), old_right);
+                    FillRect(hdc, &rect, hbrBk);
+                    rect.left = rect.right;
+                }
+                for(i = 0; i < MARQUEE_LEDS && rect.right < old_right; i++)
+                {
+                    rect.right = min(rect.left + ledWidth, old_right);
+                    FillRect(hdc, &rect, hbrBar);
+                    rect.left = rect.right;
+                    rect.right += LED_GAP;
+                    if (rect.right > old_right) break;
+                    FillRect(hdc, &rect, hbrBk);
+                    rect.left = rect.right;
+                }
+                if(rect.right < old_right)
+                {
+                    rect.right = old_right;
+                    FillRect(hdc, &rect, hbrBk);
+                }
+            }
+            else
+            {
+                while(rect.left < rightBar) {
+                    rect.right = rect.left + ledWidth;
+                    if (rect.right > rightMost)
+                        rect.right = rightMost;
+                    FillRect(hdc, &rect, hbrBar);
+                    rect.left = rect.right;
+                    rect.right += LED_GAP;
+                    if (rect.right >= rightBar) break;
+                    FillRect(hdc, &rect, hbrBk);
+                    rect.left = rect.right;
+                }
+                rect.right = rightMost;
                 FillRect(hdc, &rect, hbrBk);
-                rect.left = rect.right;
             }
-            rect.right = rightMost;
-            FillRect(hdc, &rect, hbrBk);
         }
     }
 
@@ -229,6 +392,63 @@
 
 
 /***********************************************************************
+ * PROGRESS_Timer
+ * Handle the marquee timer messages
+ */
+static LRESULT PROGRESS_Timer (PROGRESS_INFO *infoPtr, INT idTimer)
+{
+    if(idTimer == ID_MARQUEE_TIMER)
+    {
+        LONG style = GetWindowLongW (infoPtr->Self, GWL_STYLE);
+        RECT rect;
+        int ledWidth, leds;
+
+        GetClientRect (infoPtr->Self, &rect);
+        InflateRect(&rect, -1, -1);
+
+        if(!(style & PBS_SMOOTH))
+        {
+            int width, height;
+
+            if(style & PBS_VERTICAL)
+            {
+                width = rect.bottom - rect.top;
+                height = rect.right - rect.left;
+            }
+            else
+            {
+                height = rect.bottom - rect.top;
+                width = rect.right - rect.left;
+            }
+            ledWidth = MulDiv (height, 2, 3);
+            leds = (width + ledWidth - 1) / (ledWidth + LED_GAP);
+        }
+        else
+        {
+            ledWidth = 1;
+            if(style & PBS_VERTICAL)
+            {
+                leds = rect.bottom - rect.top;
+            }
+            else
+            {
+                leds = rect.right - rect.left;
+            }
+        }
+
+        /* increment the marquee progress */
+        if(++infoPtr->MarqueePos >= leds)
+        {
+            infoPtr->MarqueePos = 0;
+        }
+
+        InvalidateRect(infoPtr->Self, &rect, TRUE);
+    }
+    return 0;
+}
+
+
+/***********************************************************************
  *           PROGRESS_CoercePos
  * Makes sure the current position (CurVal) is within bounds.
  */
@@ -304,6 +524,8 @@
         infoPtr->MaxVal = 100;
         infoPtr->CurVal = 0;
         infoPtr->Step = 10;
+        infoPtr->MarqueePos = 0;
+        infoPtr->Marquee = FALSE;
         infoPtr->ColorBar = CLR_DEFAULT;
         infoPtr->ColorBk = CLR_DEFAULT;
         infoPtr->Font = 0;
@@ -326,6 +548,9 @@
     case WM_PAINT:
         return PROGRESS_Paint (infoPtr, (HDC)wParam);
 
+    case WM_TIMER:
+        return PROGRESS_Timer (infoPtr, (INT)wParam);
+
     case PBM_DELTAPOS:
     {
 	INT oldVal;
@@ -400,6 +625,19 @@
         infoPtr->ColorBk = (COLORREF)lParam;
 	InvalidateRect(hwnd, NULL, TRUE);
 	return 0;
+
+    case PBM_SETMARQUEE:
+	if(wParam != 0)
+        {
+            infoPtr->Marquee = TRUE;
+            SetTimer(infoPtr->Self, ID_MARQUEE_TIMER, (UINT)lParam, NULL);
+        }
+        else
+        {
+            infoPtr->Marquee = FALSE;
+            KillTimer(infoPtr->Self, ID_MARQUEE_TIMER);
+        }
+	return infoPtr->Marquee;
 
     default:
         if ((message >= WM_USER) && (message < WM_APP))
Index: include/commctrl.h
===================================================================
RCS file: /home/wine/wine/include/commctrl.h,v
retrieving revision 1.134
diff -u -r1.134 commctrl.h
--- include/commctrl.h	6 Jul 2004 21:02:36 -0000	1.134
+++ include/commctrl.h	25 Jul 2004 12:13:28 -0000
@@ -456,10 +456,12 @@
 #define PBM_GETRANGE        (WM_USER+7)
 #define PBM_GETPOS          (WM_USER+8)
 #define PBM_SETBARCOLOR     (WM_USER+9)
+#define PBM_SETMARQUEE      (WM_USER+10)
 #define PBM_SETBKCOLOR      CCM_SETBKCOLOR
 
 #define PBS_SMOOTH          0x01
 #define PBS_VERTICAL        0x04
+#define PBS_MARQUEE         0x08
 
 typedef struct
 {


More information about the wine-devel mailing list