Browse Source

ProgressBar Added Marquee Bounce and Stepit Method,TimerPlayPause works also for Marquee (useful for debugging)

ProgressBar Added Marquee Bounce and Stepit Method,TimerPlayPause works also for Marquee (useful for debugging)
Massimo Magnano 11 months ago
parent
commit
aa33f65d79
3 changed files with 217 additions and 81 deletions
  1. 102 28
      bgraflashprogressbar.pas
  2. 97 52
      test/test_progressbar/umain.lfm
  3. 18 1
      test/test_progressbar/umain.pas

+ 102 - 28
bgraflashprogressbar.pas

@@ -18,6 +18,8 @@
              Deleted Unit BGRADrawerFlashProgressBar;
              Deleted Unit BGRADrawerFlashProgressBar;
              New Test with all Features
              New Test with all Features
              Added Timer Style
              Added Timer Style
+    2025-01  Added Marquee Bounce and Stepit Method,
+             TimerPlayPause works also for Marquee (useful for debugging)
 ***************************** END CONTRIBUTOR(S) *****************************}
 ***************************** END CONTRIBUTOR(S) *****************************}
 unit BGRAFlashProgressBar;
 unit BGRAFlashProgressBar;
 
 
@@ -78,7 +80,11 @@ type
     xpos: integer;
     xpos: integer;
     internalTimer: TFPTimer;
     internalTimer: TFPTimer;
     marqueeLeft,
     marqueeLeft,
-    marqueeRight: Integer;
+    marqueeRight,
+    marqueeCount,
+    marqueeBCount: Integer;
+    marqueeWall,
+    marqueeBouncing: Boolean;
 
 
     procedure SetBackgroundRandomize(AValue: boolean);
     procedure SetBackgroundRandomize(AValue: boolean);
     procedure SetBackgroundRandomizeMaxIntensity(AValue: word);
     procedure SetBackgroundRandomizeMaxIntensity(AValue: word);
@@ -130,8 +136,14 @@ type
 
 
     procedure Draw(ABitmap: TBGRABitmap);
     procedure Draw(ABitmap: TBGRABitmap);
 
 
-    //Timer Methods applies only if Style is pbstTimer
+    //Step It, if Style is pbstNormal then Inc/Dec Value,
+    //         if pbstMarquee then do next Animation Step (AIncrement is ignored)
+    //         if pbstTimer then Value is decremented of 100ms (AIncrement is ignored)
+    procedure StepIt(AIncrement: Double);
+
+    //Timer Restart applies only if Style is pbstTimer
     procedure TimerReStart;
     procedure TimerReStart;
+    //Timer Paly/Pause applies only if Style is pbstMarquee or pbstTimer
     procedure TimerPlayPause;
     procedure TimerPlayPause;
 
 
     property XPosition: integer read xpos;
     property XPosition: integer read xpos;
@@ -164,8 +176,6 @@ type
     property MarqueeWidth: Word read FMarqueeWidth write SetMarqueeWidth default 0;
     property MarqueeWidth: Word read FMarqueeWidth write SetMarqueeWidth default 0;
     property MarqueeSpeed: TBGRAPBarMarqueeSpeed read FMarqueeSpeed write SetMarqueeSpeed default pbmsMedium;
     property MarqueeSpeed: TBGRAPBarMarqueeSpeed read FMarqueeSpeed write SetMarqueeSpeed default pbmsMedium;
     property MarqueeDirection: TBGRAPBarMarqueeDirection read FMarqueeDirection write SetMarqueeDirection default pbmdToRight;
     property MarqueeDirection: TBGRAPBarMarqueeDirection read FMarqueeDirection write SetMarqueeDirection default pbmdToRight;
-
-    { #todo 5 -oMaxM : I'm implementing this in the new year }
     property MarqueeBounce: Word read FMarqueeBounce write SetMarqueeBounce;
     property MarqueeBounce: Word read FMarqueeBounce write SetMarqueeBounce;
 
 
     property TimerInterval: Cardinal read FTimerInterval write SetTimerInterval default 100;
     property TimerInterval: Cardinal read FTimerInterval write SetTimerInterval default 100;
@@ -312,6 +322,7 @@ end;
 
 
 procedure TBGRAFlashProgressBar.SetMarqueeBounce(AValue: Word);
 procedure TBGRAFlashProgressBar.SetMarqueeBounce(AValue: Word);
 begin
 begin
+  marqueeBCount:= AValue;
   if FMarqueeBounce=AValue then Exit;
   if FMarqueeBounce=AValue then Exit;
   FMarqueeBounce:=AValue;
   FMarqueeBounce:=AValue;
 
 
@@ -395,9 +406,13 @@ begin
     Case FStyle of
     Case FStyle of
       pbstMarquee: begin
       pbstMarquee: begin
         SetMarqueeSpeed(FMarqueeSpeed);
         SetMarqueeSpeed(FMarqueeSpeed);
-        marqueeLeft:= 0;
 
 
-        if not(csLoading in ComponentState) and
+        if (FMarqueeDirection = pbmdToRight)
+        then marqueeLeft:= 2
+        else marqueeLeft:= -FMarqueeWidth;
+
+        if FTimerAutoRestart and
+           not(csLoading in ComponentState) and
            not(csDesigning in ComponentState) then internalTimer.Enabled:= True;
            not(csDesigning in ComponentState) then internalTimer.Enabled:= True;
       end;
       end;
       pbstTimer: begin
       pbstTimer: begin
@@ -455,12 +470,40 @@ procedure TBGRAFlashProgressBar.TimerOnTimer(Sender: TObject);
 begin
 begin
   Case FStyle of
   Case FStyle of
     pbstMarquee: begin
     pbstMarquee: begin
+      if (FMarqueeBounce > 0) then
+      begin
+        if marqueeBouncing then
+        begin
+          if (marqueeCount = 0) //we've reached the rebound wall
+          then begin
+                 marqueeCount:= 3; //Set the bounce length (3*2pixels)
+
+                 if (marqueeCurMode = pbmdToRight)
+                 then marqueeCurMode:= pbmdToLeft
+                 else marqueeCurMode:= pbmdToRight;
+
+                 //decreases the rebound counter only if we are in the real wall
+                 if marqueeWall then dec(marqueeBCount);
+
+                 if (marqueeBCount > 0)
+                 then marqueeBouncing:= True
+                 else begin
+                        //Stop Bouncing
+                        if marqueeWall then marqueeBCount:= FMarqueeBounce;
+                        marqueeBouncing:= False;
+                      end;
+               end
+          else dec(marqueeCount);
+        end;
+      end;
+
+      //Move the bar 2 pixels
       if (marqueeCurMode = pbmdToRight)
       if (marqueeCurMode = pbmdToRight)
       then inc(marqueeLeft, 2)
       then inc(marqueeLeft, 2)
       else dec(marqueeLeft, 2);
       else dec(marqueeLeft, 2);
     end;
     end;
     pbstTimer: begin
     pbstTimer: begin
-      //FValue:= TTime(, FTimerInterval);
+      { #note -oMaxM : If we had to be more precise we should keep the Start time and subtract the current time }
       FValue:= IncMilliSecond(FValue, -internalTimer.Interval);
       FValue:= IncMilliSecond(FValue, -internalTimer.Interval);
       if (FValue <= 0)
       if (FValue <= 0)
       then begin
       then begin
@@ -511,13 +554,19 @@ begin
   inherited Loaded;
   inherited Loaded;
 
 
   Case FStyle of
   Case FStyle of
-    pbstMarquee: if not(csDesigning in ComponentState) then internalTimer.Enabled:= True;
+    pbstMarquee: begin
+      if (FMarqueeDirection = pbmdToRight)
+      then marqueeLeft:= 2
+      else marqueeLeft:= -FMarqueeWidth;
+
+      if FTimerAutoRestart and not(csDesigning in ComponentState) then internalTimer.Enabled:= True;
+    end;
     pbstTimer: begin
     pbstTimer: begin
-                 FValue:= FMaxValue;
-                 internalTimer.Interval:= FTimerInterval;
+      FValue:= FMaxValue;
+      internalTimer.Interval:= FTimerInterval;
 
 
-                 if FTimerAutoRestart and not(csDesigning in ComponentState) then internalTimer.Enabled:= True;
-               end;
+      if FTimerAutoRestart and not(csDesigning in ComponentState) then internalTimer.Enabled:= True;
+    end;
     else internalTimer.Enabled:= False;
     else internalTimer.Enabled:= False;
   end;
   end;
 end;
 end;
@@ -573,6 +622,7 @@ begin
   marqueeCurMode:= pbmdToRight;
   marqueeCurMode:= pbmdToRight;
   marqueeLeft:= 0;
   marqueeLeft:= 0;
   marqueeRight:= 0;
   marqueeRight:= 0;
+  marqueeBouncing:= False;
 
 
   //Timer
   //Timer
   FTimerInterval:= 100;
   FTimerInterval:= 100;
@@ -791,26 +841,31 @@ begin
         if (marqueeCurMode = pbmdToRight)
         if (marqueeCurMode = pbmdToRight)
         then begin
         then begin
                //check if the whole bar is out put it back to the beginning
                //check if the whole bar is out put it back to the beginning
-               if (marqueeLeft >= tx-2) then
-               begin
-                 marqueeLeft:= 2;
-               end;
+               if (marqueeLeft >= content.Right) then marqueeLeft:= content.Left;
 
 
                //Calculate the Right
                //Calculate the Right
                marqueeRight:= marqueeLeft+(rMarqueeWidth-1);
                marqueeRight:= marqueeLeft+(rMarqueeWidth-1);
 
 
                //Check if part of the bar is out calculate the visible piece on the left
                //Check if part of the bar is out calculate the visible piece on the left
                marqueeOver:= 0;
                marqueeOver:= 0;
-               if (marqueeRight > tx-2) then
+               marqueeWall:= (marqueeRight >= content.Right-1);
+               if marqueeWall then
                begin
                begin
-                 marqueeOver:= marqueeRight-(tx-2);
+                 if (FMarqueeBounce > 0)
+                 then begin
+                        //Put perfectly on the Right edge
+                        marqueeRight:= content.Right-1;
+                        marqueeLeft:= marqueeRight-(rMarqueeWidth-1);
+                        marqueeBouncing:= True;
+                      end
+                 else marqueeOver:= marqueeRight-(content.Right-1);
                end;
                end;
              end
              end
         else begin
         else begin
                //check if the whole bar is out put it back to the end
                //check if the whole bar is out put it back to the end
-               if (marqueeLeft <= -(rMarqueeWidth+2)) then
+               if (marqueeLeft <= -rMarqueeWidth) then //(rMarqueeWidth+2)) then
                begin
                begin
-                 marqueeLeft:= tx-2-rMarqueeWidth;
+                 marqueeLeft:= content.Right-rMarqueeWidth;
                end;
                end;
 
 
                //Calculate the Right
                //Calculate the Right
@@ -818,9 +873,17 @@ begin
 
 
                //check if part of the bar is out then the visible piece on the left is equal to marqueeRight
                //check if part of the bar is out then the visible piece on the left is equal to marqueeRight
                marqueeOver:= 0;
                marqueeOver:= 0;
-               if (marqueeRight < rMarqueeWidth) then
+               marqueeWall:= (marqueeRight-1 <= rMarqueeWidth);
+               if marqueeWall then
                begin
                begin
-                 marqueeOver:= marqueeRight;
+                 if (FMarqueeBounce > 0)
+                 then begin
+                        //Put perfectly on the Left edge
+                        marqueeLeft:= content.Left;
+                        marqueeRight:= marqueeLeft+(rMarqueeWidth-1);
+                        marqueeBouncing:= True;
+                      end
+                 else marqueeOver:= marqueeRight;
                end;
                end;
              end;
              end;
 
 
@@ -835,15 +898,14 @@ begin
              end
              end
         else begin
         else begin
                //Draw visible piece on the Left
                //Draw visible piece on the Left
-               DrawBar(rect(2, content.top, marqueeOver, content.bottom), FBarColor);
+               DrawBar(rect(content.Left, content.top, marqueeOver, content.bottom), FBarColor);
                ABitmap.SetPixel(marqueeOver, content.top, BGRA(62, 62, 62));
                ABitmap.SetPixel(marqueeOver, content.top, BGRA(62, 62, 62));
                ABitmap.SetVertLine(marqueeOver, content.top + 1, content.bottom - 1, BGRA(40, 40, 40));
                ABitmap.SetVertLine(marqueeOver, content.top + 1, content.bottom - 1, BGRA(40, 40, 40));
                //Draw visible piece on the Right
                //Draw visible piece on the Right
-               DrawBar(rect(tx-2-(rMarqueeWidth+1-marqueeOver), content.top, tx-2, content.bottom), FBarColor);
-               ABitmap.SetPixel(tx-2-(rMarqueeWidth+1-marqueeOver), content.top, BGRA(62, 62, 62));
-               ABitmap.SetVertLine(tx-2-(rMarqueeWidth+1-marqueeOver), content.top + 1, content.bottom - 1, BGRA(40, 40, 40));
+               DrawBar(rect(content.Right-(rMarqueeWidth+1-marqueeOver), content.top, tx-2, content.bottom), FBarColor);
+               ABitmap.SetPixel(content.Right-(rMarqueeWidth+1-marqueeOver), content.top, BGRA(62, 62, 62));
+               ABitmap.SetVertLine(content.Right-(rMarqueeWidth+1-marqueeOver), content.top + 1, content.bottom - 1, BGRA(40, 40, 40));
              end;
              end;
-
       end;
       end;
       pbstTimer: begin
       pbstTimer: begin
         if FMaxValue > FMinValue then
         if FMaxValue > FMinValue then
@@ -873,6 +935,18 @@ begin
   end;
   end;
 end;
 end;
 
 
+procedure TBGRAFlashProgressBar.StepIt(AIncrement: Double);
+begin
+  Case FStyle of
+    pbstMarquee,
+    pbstTimer: begin
+      internalTimer.Enabled:= False;
+      TimerOnTimer(nil);
+    end
+  else Value:= Value+AIncrement;
+  end;
+end;
+
 procedure TBGRAFlashProgressBar.TimerReStart;
 procedure TBGRAFlashProgressBar.TimerReStart;
 begin
 begin
   if (FStyle = pbstTimer) then
   if (FStyle = pbstTimer) then
@@ -888,7 +962,7 @@ end;
 
 
 procedure TBGRAFlashProgressBar.TimerPlayPause;
 procedure TBGRAFlashProgressBar.TimerPlayPause;
 begin
 begin
-  if (FStyle = pbstTimer) then
+  if (FStyle in [pbstMarquee, pbstTimer]) then
   begin
   begin
     internalTimer.Enabled:= not(internalTimer.Enabled);
     internalTimer.Enabled:= not(internalTimer.Enabled);
     Invalidate;
     Invalidate;

+ 97 - 52
test/test_progressbar/umain.lfm

@@ -1,15 +1,15 @@
 object Form1: TForm1
 object Form1: TForm1
   Left = 357
   Left = 357
-  Height = 374
+  Height = 418
   Top = 179
   Top = 179
-  Width = 541
+  Width = 506
   Caption = 'Form1'
   Caption = 'Form1'
-  ClientHeight = 374
-  ClientWidth = 541
+  ClientHeight = 418
+  ClientWidth = 506
   object btStyleMarquee: TBGRASpeedButton
   object btStyleMarquee: TBGRASpeedButton
-    Left = 99
+    Left = 112
     Height = 22
     Height = 22
-    Top = 160
+    Top = 152
     Width = 64
     Width = 64
     Caption = 'Marquee'
     Caption = 'Marquee'
     OnClick = btStyleMarqueeClick
     OnClick = btStyleMarqueeClick
@@ -37,10 +37,10 @@ object Form1: TForm1
     OnTimerEnd = BGRAMaxMProgressTimerEnd
     OnTimerEnd = BGRAMaxMProgressTimerEnd
   end
   end
   object rgMarqueeSpeed: TRadioGroup
   object rgMarqueeSpeed: TRadioGroup
-    Left = 115
+    Left = 112
     Height = 65
     Height = 65
-    Top = 228
-    Width = 79
+    Top = 246
+    Width = 77
     AutoFill = True
     AutoFill = True
     Caption = 'Speed'
     Caption = 'Speed'
     ChildSizing.LeftRightSpacing = 6
     ChildSizing.LeftRightSpacing = 6
@@ -51,7 +51,7 @@ object Form1: TForm1
     ChildSizing.Layout = cclLeftToRightThenTopToBottom
     ChildSizing.Layout = cclLeftToRightThenTopToBottom
     ChildSizing.ControlsPerLine = 1
     ChildSizing.ControlsPerLine = 1
     ClientHeight = 45
     ClientHeight = 45
-    ClientWidth = 75
+    ClientWidth = 73
     ItemIndex = 1
     ItemIndex = 1
     Items.Strings = (
     Items.Strings = (
       'Slow'
       'Slow'
@@ -62,9 +62,9 @@ object Form1: TForm1
     OnClick = rgMarqueeSpeedClick
     OnClick = rgMarqueeSpeedClick
   end
   end
   object edMarqueeWidth: TBCTrackbarUpdown
   object edMarqueeWidth: TBCTrackbarUpdown
-    Left = 130
+    Left = 131
     Height = 26
     Height = 26
-    Top = 343
+    Top = 389
     Width = 64
     Width = 64
     AllowNegativeValues = False
     AllowNegativeValues = False
     BarExponent = 1
     BarExponent = 1
@@ -139,16 +139,16 @@ object Form1: TForm1
     UseDockManager = False
     UseDockManager = False
   end
   end
   object Label1: TLabel
   object Label1: TLabel
-    Left = 115
+    Left = 116
     Height = 15
     Height = 15
-    Top = 304
+    Top = 350
     Width = 38
     Width = 38
     Caption = 'Width :'
     Caption = 'Width :'
   end
   end
   object btStyleMultiP: TBGRASpeedButton
   object btStyleMultiP: TBGRASpeedButton
-    Left = 239
+    Left = 248
     Height = 22
     Height = 22
-    Top = 160
+    Top = 152
     Width = 79
     Width = 79
     Caption = 'MultiProgress'
     Caption = 'MultiProgress'
     OnClick = btStyleMultiPClick
     OnClick = btStyleMultiPClick
@@ -161,16 +161,16 @@ object Form1: TForm1
     Caption = 'Value :'
     Caption = 'Value :'
   end
   end
   object Label3: TLabel
   object Label3: TLabel
-    Left = 255
+    Left = 248
     Height = 15
     Height = 15
-    Top = 191
+    Top = 183
     Width = 48
     Width = 48
     Caption = 'Value M :'
     Caption = 'Value M :'
   end
   end
   object cbMarqueeWidth: TCheckBox
   object cbMarqueeWidth: TCheckBox
-    Left = 130
+    Left = 131
     Height = 19
     Height = 19
-    Top = 320
+    Top = 366
     Width = 44
     Width = 44
     Caption = 'Auto'
     Caption = 'Auto'
     Checked = True
     Checked = True
@@ -181,7 +181,7 @@ object Form1: TForm1
   object edCaption: TEdit
   object edCaption: TEdit
     Left = 60
     Left = 60
     Height = 23
     Height = 23
-    Top = 80
+    Top = 72
     Width = 80
     Width = 80
     TabOrder = 3
     TabOrder = 3
     OnChange = edCaptionChange
     OnChange = edCaptionChange
@@ -189,30 +189,30 @@ object Form1: TForm1
   object Label4: TLabel
   object Label4: TLabel
     Left = 8
     Left = 8
     Height = 15
     Height = 15
-    Top = 84
+    Top = 76
     Width = 48
     Width = 48
     Caption = 'Caption :'
     Caption = 'Caption :'
   end
   end
   object cbCaptionPercent: TCheckBox
   object cbCaptionPercent: TCheckBox
-    Left = 4
+    Left = 233
     Height = 19
     Height = 19
-    Top = 186
-    Width = 90
-    Caption = 'Show Percent'
+    Top = 76
+    Width = 119
+    Caption = 'Show Total Percent'
     TabOrder = 4
     TabOrder = 4
     OnChange = cbCaptionPercentChange
     OnChange = cbCaptionPercentChange
   end
   end
   object Label6: TLabel
   object Label6: TLabel
-    Left = 8
+    Left = 233
     Height = 15
     Height = 15
-    Top = 206
+    Top = 98
     Width = 36
     Width = 36
     Caption = 'Digits :'
     Caption = 'Digits :'
   end
   end
   object edCaptionDigits: TSpinEdit
   object edCaptionDigits: TSpinEdit
-    Left = 48
+    Left = 277
     Height = 23
     Height = 23
-    Top = 206
+    Top = 96
     Width = 50
     Width = 50
     MaxValue = 30
     MaxValue = 30
     TabOrder = 5
     TabOrder = 5
@@ -232,9 +232,9 @@ object Form1: TForm1
     OnChange = edValueChange
     OnChange = edValueChange
   end
   end
   object edMultiPValueM: TFloatSpinEdit
   object edMultiPValueM: TFloatSpinEdit
-    Left = 304
+    Left = 297
     Height = 23
     Height = 23
-    Top = 186
+    Top = 178
     Width = 80
     Width = 80
     Font.Color = clWindowText
     Font.Color = clWindowText
     Font.Name = 'Arial'
     Font.Name = 'Arial'
@@ -286,7 +286,7 @@ object Form1: TForm1
   object rgCaptionAlign: TRadioGroup
   object rgCaptionAlign: TRadioGroup
     Left = 147
     Left = 147
     Height = 65
     Height = 65
-    Top = 80
+    Top = 72
     Width = 79
     Width = 79
     AutoFill = True
     AutoFill = True
     Caption = 'Align'
     Caption = 'Align'
@@ -309,18 +309,18 @@ object Form1: TForm1
     OnClick = rgCaptionAlignClick
     OnClick = rgCaptionAlignClick
   end
   end
   object cbCaptionPercentM: TCheckBox
   object cbCaptionPercentM: TCheckBox
-    Left = 255
+    Left = 248
     Height = 19
     Height = 19
-    Top = 216
-    Width = 90
-    Caption = 'Show Percent'
+    Top = 208
+    Width = 133
+    Caption = 'Show ValueM Percent'
     TabOrder = 11
     TabOrder = 11
     OnChange = cbCaptionPercentMChange
     OnChange = cbCaptionPercentMChange
   end
   end
   object rgCaptionAlignM: TRadioGroup
   object rgCaptionAlignM: TRadioGroup
-    Left = 271
+    Left = 264
     Height = 65
     Height = 65
-    Top = 238
+    Top = 230
     Width = 79
     Width = 79
     AutoFill = True
     AutoFill = True
     Caption = 'Align'
     Caption = 'Align'
@@ -343,9 +343,9 @@ object Form1: TForm1
     OnClick = rgCaptionAlignMClick
     OnClick = rgCaptionAlignMClick
   end
   end
   object rgMarqueeDirection: TRadioGroup
   object rgMarqueeDirection: TRadioGroup
-    Left = 119
+    Left = 116
     Height = 41
     Height = 41
-    Top = 181
+    Top = 312
     Width = 107
     Width = 107
     AutoFill = True
     AutoFill = True
     Caption = 'Direction'
     Caption = 'Direction'
@@ -370,7 +370,7 @@ object Form1: TForm1
   object btStyleNormal: TBGRASpeedButton
   object btStyleNormal: TBGRASpeedButton
     Left = 4
     Left = 4
     Height = 22
     Height = 22
-    Top = 160
+    Top = 152
     Width = 79
     Width = 79
     Caption = 'Normal'
     Caption = 'Normal'
     OnClick = btStyleNormalClick
     OnClick = btStyleNormalClick
@@ -378,7 +378,7 @@ object Form1: TForm1
   object btStyleTimer: TBGRASpeedButton
   object btStyleTimer: TBGRASpeedButton
     Left = 392
     Left = 392
     Height = 22
     Height = 22
-    Top = 160
+    Top = 152
     Width = 79
     Width = 79
     Caption = 'Timer'
     Caption = 'Timer'
     OnClick = btStyleTimerClick
     OnClick = btStyleTimerClick
@@ -386,15 +386,15 @@ object Form1: TForm1
   object btTimerStart: TBGRASpeedButton
   object btTimerStart: TBGRASpeedButton
     Left = 408
     Left = 408
     Height = 22
     Height = 22
-    Top = 238
+    Top = 230
     Width = 63
     Width = 63
     Caption = 'ReStart'
     Caption = 'ReStart'
     OnClick = btTimerStartClick
     OnClick = btTimerStartClick
   end
   end
   object cbTimerAutoStart: TCheckBox
   object cbTimerAutoStart: TCheckBox
-    Left = 400
+    Left = 392
     Height = 19
     Height = 19
-    Top = 216
+    Top = 176
     Width = 71
     Width = 71
     Caption = 'Auto Start'
     Caption = 'Auto Start'
     Checked = True
     Checked = True
@@ -405,15 +405,15 @@ object Form1: TForm1
   object btTimerPlayPause: TBGRASpeedButton
   object btTimerPlayPause: TBGRASpeedButton
     Left = 408
     Left = 408
     Height = 22
     Height = 22
-    Top = 262
+    Top = 254
     Width = 63
     Width = 63
     Caption = 'Play/Pause'
     Caption = 'Play/Pause'
     OnClick = btTimerPlayPauseClick
     OnClick = btTimerPlayPauseClick
   end
   end
   object TimeEdit1: TTimeEdit
   object TimeEdit1: TTimeEdit
-    Left = 400
+    Left = 392
     Height = 23
     Height = 23
-    Top = 186
+    Top = 196
     Width = 103
     Width = 103
     ButtonWidth = 23
     ButtonWidth = 23
     NumGlyphs = 1
     NumGlyphs = 1
@@ -424,7 +424,7 @@ object Form1: TForm1
   object cbCaptionPercent1: TCheckBox
   object cbCaptionPercent1: TCheckBox
     Left = 400
     Left = 400
     Height = 19
     Height = 19
-    Top = 296
+    Top = 288
     Width = 80
     Width = 80
     Caption = 'Show Timer'
     Caption = 'Show Timer'
     TabOrder = 16
     TabOrder = 16
@@ -433,7 +433,7 @@ object Form1: TForm1
   object edCaptionTimerFormat: TEdit
   object edCaptionTimerFormat: TEdit
     Left = 408
     Left = 408
     Height = 23
     Height = 23
-    Top = 318
+    Top = 310
     Width = 80
     Width = 80
     TabOrder = 17
     TabOrder = 17
     Text = 'nn:ss.zzz'
     Text = 'nn:ss.zzz'
@@ -442,11 +442,56 @@ object Form1: TForm1
   object lbCount: TLabel
   object lbCount: TLabel
     Left = 400
     Left = 400
     Height = 25
     Height = 25
-    Top = 344
+    Top = 336
     Width = 8
     Width = 8
     Caption = '_'
     Caption = '_'
     Font.Color = clRed
     Font.Color = clRed
     Font.Height = -19
     Font.Height = -19
     ParentFont = False
     ParentFont = False
   end
   end
+  object btTimerPlayPause1: TBGRASpeedButton
+    Left = 116
+    Height = 22
+    Top = 197
+    Width = 63
+    Caption = 'Play/Pause'
+    OnClick = btTimerPlayPauseClick
+  end
+  object btTimerPlayPause2: TBGRASpeedButton
+    Left = 180
+    Height = 22
+    Top = 197
+    Width = 40
+    Caption = 'StepIt'
+    OnClick = btTimerPlayPause2Click
+  end
+  object cbTimerAutoStart1: TCheckBox
+    Left = 116
+    Height = 19
+    Top = 176
+    Width = 71
+    Caption = 'Auto Start'
+    Checked = True
+    State = cbChecked
+    TabOrder = 18
+    OnChange = cbTimerAutoStartChange
+  end
+  object edMarqueeBounce: TSpinEdit
+    Left = 170
+    Height = 23
+    Hint = '0 = Normal Marquee;'#13#10'>0 Bounce'
+    Top = 224
+    Width = 50
+    MaxValue = 10
+    ParentShowHint = False
+    TabOrder = 19
+    OnChange = edMarqueeBounceChange
+  end
+  object Label8: TLabel
+    Left = 119
+    Height = 15
+    Top = 226
+    Width = 43
+    Caption = 'Bounce:'
+  end
 end
 end

+ 18 - 1
test/test_progressbar/umain.pas

@@ -16,6 +16,8 @@ type
     btStyleMultiP: TBGRASpeedButton;
     btStyleMultiP: TBGRASpeedButton;
     btStyleNormal: TBGRASpeedButton;
     btStyleNormal: TBGRASpeedButton;
     btStyleTimer: TBGRASpeedButton;
     btStyleTimer: TBGRASpeedButton;
+    btTimerPlayPause1: TBGRASpeedButton;
+    btTimerPlayPause2: TBGRASpeedButton;
     btTimerStart: TBGRASpeedButton;
     btTimerStart: TBGRASpeedButton;
     btTimerPlayPause: TBGRASpeedButton;
     btTimerPlayPause: TBGRASpeedButton;
     cbCaptionPercent1: TCheckBox;
     cbCaptionPercent1: TCheckBox;
@@ -23,6 +25,7 @@ type
     cbMarqueeWidth: TCheckBox;
     cbMarqueeWidth: TCheckBox;
     cbCaptionPercent: TCheckBox;
     cbCaptionPercent: TCheckBox;
     cbTimerAutoStart: TCheckBox;
     cbTimerAutoStart: TCheckBox;
+    cbTimerAutoStart1: TCheckBox;
     edCaption: TEdit;
     edCaption: TEdit;
     edCaptionTimerFormat: TEdit;
     edCaptionTimerFormat: TEdit;
     edMarqueeWidth: TBCTrackbarUpdown;
     edMarqueeWidth: TBCTrackbarUpdown;
@@ -39,12 +42,14 @@ type
     Label5: TLabel;
     Label5: TLabel;
     Label6: TLabel;
     Label6: TLabel;
     Label7: TLabel;
     Label7: TLabel;
+    Label8: TLabel;
     lbCount: TLabel;
     lbCount: TLabel;
     rgCaptionAlignM: TRadioGroup;
     rgCaptionAlignM: TRadioGroup;
     rgMarqueeSpeed: TRadioGroup;
     rgMarqueeSpeed: TRadioGroup;
     edCaptionDigits: TSpinEdit;
     edCaptionDigits: TSpinEdit;
     rgCaptionAlign: TRadioGroup;
     rgCaptionAlign: TRadioGroup;
     rgMarqueeDirection: TRadioGroup;
     rgMarqueeDirection: TRadioGroup;
+    edMarqueeBounce: TSpinEdit;
     TimeEdit1: TTimeEdit;
     TimeEdit1: TTimeEdit;
     procedure BCTrackbarUpdown1Change(Sender: TObject; AByUser: boolean);
     procedure BCTrackbarUpdown1Change(Sender: TObject; AByUser: boolean);
     procedure BGRAMaxMProgressTimerEnd(Sender: TObject);
     procedure BGRAMaxMProgressTimerEnd(Sender: TObject);
@@ -52,6 +57,7 @@ type
     procedure btStyleMultiPClick(Sender: TObject);
     procedure btStyleMultiPClick(Sender: TObject);
     procedure btStyleNormalClick(Sender: TObject);
     procedure btStyleNormalClick(Sender: TObject);
     procedure btStyleTimerClick(Sender: TObject);
     procedure btStyleTimerClick(Sender: TObject);
+    procedure btTimerPlayPause2Click(Sender: TObject);
     procedure btTimerPlayPauseClick(Sender: TObject);
     procedure btTimerPlayPauseClick(Sender: TObject);
     procedure btTimerStartClick(Sender: TObject);
     procedure btTimerStartClick(Sender: TObject);
     procedure cbCaptionPercentMChange(Sender: TObject);
     procedure cbCaptionPercentMChange(Sender: TObject);
@@ -60,6 +66,7 @@ type
     procedure cbTimerAutoStartChange(Sender: TObject);
     procedure cbTimerAutoStartChange(Sender: TObject);
     procedure edCaptionChange(Sender: TObject);
     procedure edCaptionChange(Sender: TObject);
     procedure edCaptionDigitsChange(Sender: TObject);
     procedure edCaptionDigitsChange(Sender: TObject);
+    procedure edMarqueeBounceChange(Sender: TObject);
     procedure edMaxChange(Sender: TObject);
     procedure edMaxChange(Sender: TObject);
     procedure edMinChange(Sender: TObject);
     procedure edMinChange(Sender: TObject);
     procedure edMultiPValueMChange(Sender: TObject; AByUser: boolean);
     procedure edMultiPValueMChange(Sender: TObject; AByUser: boolean);
@@ -113,6 +120,11 @@ begin
   BGRAMaxMProgress.Style:= pbstTimer;
   BGRAMaxMProgress.Style:= pbstTimer;
 end;
 end;
 
 
+procedure TForm1.btTimerPlayPause2Click(Sender: TObject);
+begin
+  BGRAMaxMProgress.StepIt(0);
+end;
+
 procedure TForm1.btTimerPlayPauseClick(Sender: TObject);
 procedure TForm1.btTimerPlayPauseClick(Sender: TObject);
 begin
 begin
   BGRAMaxMProgress.TimerPlayPause;
   BGRAMaxMProgress.TimerPlayPause;
@@ -148,7 +160,7 @@ end;
 
 
 procedure TForm1.cbTimerAutoStartChange(Sender: TObject);
 procedure TForm1.cbTimerAutoStartChange(Sender: TObject);
 begin
 begin
-  BGRAMaxMProgress.TimerAutoRestart:= cbTimerAutoStart.Checked;
+  BGRAMaxMProgress.TimerAutoRestart:= TCheckBox(Sender).Checked;
 end;
 end;
 
 
 procedure TForm1.edCaptionChange(Sender: TObject);
 procedure TForm1.edCaptionChange(Sender: TObject);
@@ -161,6 +173,11 @@ begin
   BGRAMaxMProgress.CaptionPercentDigits:= edCaptionDigits.Value;
   BGRAMaxMProgress.CaptionPercentDigits:= edCaptionDigits.Value;
 end;
 end;
 
 
+procedure TForm1.edMarqueeBounceChange(Sender: TObject);
+begin
+  BGRAMaxMProgress.MarqueeBounce:= edMarqueeBounce.Value;
+end;
+
 procedure TForm1.edMaxChange(Sender: TObject);
 procedure TForm1.edMaxChange(Sender: TObject);
 begin
 begin
   BGRAMaxMProgress.MaxValue:=edMax.Value;
   BGRAMaxMProgress.MaxValue:=edMax.Value;