瀏覽代碼

FlashProgressBar Added ShowBarAnimation; Solved Exception when closing with timer enabled

FlashProgressBar Added ShowBarAnimation;
Solved Exception when closing with timer enabled
Massimo Magnano 11 月之前
父節點
當前提交
1abc091fad
共有 3 個文件被更改,包括 147 次插入27 次删除
  1. 116 27
      bgraflashprogressbar.pas
  2. 11 0
      test/test_progressbar/umain.lfm
  3. 20 0
      test/test_progressbar/umain.pas

+ 116 - 27
bgraflashprogressbar.pas

@@ -21,6 +21,7 @@
     2025-01  Added Marquee Bounce and Stepit Method,
     2025-01  Added Marquee Bounce and Stepit Method,
              TimerPlayPause works also for Marquee (useful for debugging)
              TimerPlayPause works also for Marquee (useful for debugging)
              Added Graph Style and ShowDividers, Renamed MultiProgress properties
              Added Graph Style and ShowDividers, Renamed MultiProgress properties
+             Added ShowBarAnimation
 ***************************** END CONTRIBUTOR(S) *****************************}
 ***************************** END CONTRIBUTOR(S) *****************************}
 unit BGRAFlashProgressBar;
 unit BGRAFlashProgressBar;
 
 
@@ -52,10 +53,6 @@ type
 
 
   TBGRAFlashProgressBar = class(TBGRAGraphicCtrl)
   TBGRAFlashProgressBar = class(TBGRAGraphicCtrl)
   private
   private
-    FGraphShowYLine: Boolean;
-    FGraphYLineAfter: String;
-    FGraphYLineCaption: String;
-    FGraphYLineDigits: Integer;
     procedure SetBackgroundRandomize(AValue: boolean);
     procedure SetBackgroundRandomize(AValue: boolean);
     procedure SetBackgroundRandomizeMaxIntensity(AValue: word);
     procedure SetBackgroundRandomizeMaxIntensity(AValue: word);
     procedure SetBackgroundRandomizeMinIntensity(AValue: word);
     procedure SetBackgroundRandomizeMinIntensity(AValue: word);
@@ -72,6 +69,7 @@ type
     procedure SetGraphYLineAfter(AValue: String);
     procedure SetGraphYLineAfter(AValue: String);
     procedure SetGraphYLineCaption(AValue: String);
     procedure SetGraphYLineCaption(AValue: String);
     procedure SetGraphYLineDigits(AValue: Integer);
     procedure SetGraphYLineDigits(AValue: Integer);
+    procedure SetShowBarAnimation(AValue: Boolean);
     procedure SetShowDividers(AValue: Boolean);
     procedure SetShowDividers(AValue: Boolean);
     procedure SetMarqueeBounce(AValue: Word);
     procedure SetMarqueeBounce(AValue: Word);
     procedure SetMarqueeDirection(AValue: TBGRAPBarMarqueeDirection);
     procedure SetMarqueeDirection(AValue: TBGRAPBarMarqueeDirection);
@@ -123,15 +121,23 @@ type
     FOnChange: TNotifyEvent;
     FOnChange: TNotifyEvent;
     FRandSeed: integer;
     FRandSeed: integer;
     FStyle: TBGRAPBarStyle;
     FStyle: TBGRAPBarStyle;
-    xpos: integer;
-    internalTimer: TFPTimer;
+    FGraphShowYLine: Boolean;
+    FGraphYLineAfter: String;
+    FGraphYLineCaption: String;
+    FGraphYLineDigits: Integer;
+    FShowBarAnimation: Boolean;
+
+    xpos,
+    xposSub,
     marqueeLeft,
     marqueeLeft,
     marqueeRight,
     marqueeRight,
     marqueeCount,
     marqueeCount,
-    marqueeBCount: Integer;
+    marqueeBCount,
+    barAnimLeft: Integer;
     marqueeWall,
     marqueeWall,
     marqueeBouncing: Boolean;
     marqueeBouncing: Boolean;
     marqueeCurMode: TBGRAPBarMarqueeDirection;
     marqueeCurMode: TBGRAPBarMarqueeDirection;
+    internalTimer: TFPTimer;
     GraphValues: TGraphValues;  //array of Real Graph Values
     GraphValues: TGraphValues;  //array of Real Graph Values
     GraphPoints: array of TPointF; //array of Calculated xpos and ypos
     GraphPoints: array of TPointF; //array of Calculated xpos and ypos
 
 
@@ -170,10 +176,11 @@ type
 
 
     //Timer Restart applies only if Style is pbstTimer
     //Timer Restart applies only if Style is pbstTimer
     procedure TimerReStart;
     procedure TimerReStart;
-    //Timer Paly/Pause applies only if Style is pbstMarquee or pbstTimer
+    //Timer Play/Pause applies only if Style is pbstMarquee or pbstTimer
     procedure TimerPlayPause;
     procedure TimerPlayPause;
 
 
     property XPosition: integer read xpos;
     property XPosition: integer read xpos;
+    property XPositionSub: integer read xposSub;
 
 
   published
   published
     property Align;
     property Align;
@@ -202,6 +209,7 @@ type
     property BackgroundRandomizeMaxIntensity: Word read FBackgroundRandomizeMaxIntensity write SetBackgroundRandomizeMaxIntensity;
     property BackgroundRandomizeMaxIntensity: Word read FBackgroundRandomizeMaxIntensity write SetBackgroundRandomizeMaxIntensity;
     property BackgroundRandomize: Boolean read FBackgroundRandomize write SetBackgroundRandomize;
     property BackgroundRandomize: Boolean read FBackgroundRandomize write SetBackgroundRandomize;
     property ShowDividers: Boolean read FShowDividers write SetShowDividers default False;
     property ShowDividers: Boolean read FShowDividers write SetShowDividers default False;
+    property ShowBarAnimation: Boolean read FShowBarAnimation write SetShowBarAnimation default False;
     property Style: TBGRAPBarStyle read FStyle write SetStyle default pbstNormal;
     property Style: TBGRAPBarStyle read FStyle write SetStyle default pbstNormal;
     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;
@@ -392,6 +400,24 @@ begin
   Invalidate;
   Invalidate;
 end;
 end;
 
 
+procedure TBGRAFlashProgressBar.SetShowBarAnimation(AValue: Boolean);
+begin
+  if FShowBarAnimation=AValue then Exit;
+  FShowBarAnimation:=AValue;
+
+  if (FStyle in [pbstNormal, pbstMultiProgress, pbstGraph]) and
+     not(csLoading in ComponentState) and
+     not(csDesigning in ComponentState) then
+  begin
+    barAnimLeft:= 2;
+    if FShowBarAnimation then internalTimer.Interval:= 20;
+    internalTimer.Enabled:= FShowBarAnimation;
+  end;
+
+  if Assigned(FOnChange) then FOnChange(Self);
+  Invalidate;
+end;
+
 procedure TBGRAFlashProgressBar.SetShowDividers(AValue: Boolean);
 procedure TBGRAFlashProgressBar.SetShowDividers(AValue: Boolean);
 begin
 begin
   if FShowDividers=AValue then Exit;
   if FShowDividers=AValue then Exit;
@@ -506,6 +532,17 @@ begin
     FStyle:= AValue;
     FStyle:= AValue;
 
 
     Case FStyle of
     Case FStyle of
+      pbstNormal,
+      pbstMultiProgress: begin
+        if FShowBarAnimation and
+           not(csLoading in ComponentState) and
+           not(csDesigning in ComponentState)
+        then begin
+               internalTimer.Interval:= 20;
+               internalTimer.Enabled:= True;
+             end
+        else internalTimer.Enabled:= False;
+      end;
       pbstMarquee: begin
       pbstMarquee: begin
         SetMarqueeSpeed(FMarqueeSpeed);
         SetMarqueeSpeed(FMarqueeSpeed);
 
 
@@ -528,8 +565,16 @@ begin
       pbstGraph: begin
       pbstGraph: begin
         //Save space for the 2 points to close the polygon
         //Save space for the 2 points to close the polygon
         if (Length(GraphPoints) < 2) then SetLength(GraphPoints, 2);
         if (Length(GraphPoints) < 2) then SetLength(GraphPoints, 2);
+
+        if FShowBarAnimation and
+           not(csLoading in ComponentState) and
+           not(csDesigning in ComponentState)
+        then begin
+               internalTimer.Interval:= 20;
+               internalTimer.Enabled:= True;
+             end
+        else internalTimer.Enabled:= False;
       end;
       end;
-    else internalTimer.Enabled:= False;
     end;
     end;
 
 
     if Assigned(FOnChange) then FOnChange(Self);
     if Assigned(FOnChange) then FOnChange(Self);
@@ -563,6 +608,15 @@ end;
 procedure TBGRAFlashProgressBar.TimerOnTimer(Sender: TObject);
 procedure TBGRAFlashProgressBar.TimerOnTimer(Sender: TObject);
 begin
 begin
   Case FStyle of
   Case FStyle of
+    pbstNormal,
+    pbstMultiProgress,
+    pbstGraph: if FShowBarAnimation then begin
+      if (xpos > 8) then
+      begin
+        inc(barAnimLeft, 2);
+        if (barAnimLeft+4 > xpos) then barAnimLeft:= -6; //Wait 3 times after reached the end
+      end;
+    end;
     pbstMarquee: begin
     pbstMarquee: begin
       if (FMarqueeBounce > 0) then
       if (FMarqueeBounce > 0) then
       begin
       begin
@@ -648,6 +702,12 @@ begin
   inherited Loaded;
   inherited Loaded;
 
 
   Case FStyle of
   Case FStyle of
+    pbstNormal,
+    pbstMultiProgress,
+    pbstGraph: begin
+      if FShowBarAnimation then internalTimer.Interval:= 20;
+      internalTimer.Enabled:= FShowBarAnimation;
+    end;
     pbstMarquee: begin
     pbstMarquee: begin
       if (FMarqueeDirection = pbmdToRight)
       if (FMarqueeDirection = pbmdToRight)
       then marqueeLeft:= 2
       then marqueeLeft:= 2
@@ -661,7 +721,6 @@ begin
 
 
       if FTimerAutoRestart and not(csDesigning in ComponentState) then internalTimer.Enabled:= True;
       if FTimerAutoRestart and not(csDesigning in ComponentState) then internalTimer.Enabled:= True;
     end;
     end;
-    else internalTimer.Enabled:= False;
   end;
   end;
 end;
 end;
 
 
@@ -686,11 +745,15 @@ begin
 
 
   // Bitmap
   // Bitmap
   FBGRA := TBGRABitmap.Create(Width, Height);
   FBGRA := TBGRABitmap.Create(Width, Height);
+
   // Functionality
   // Functionality
   FMinValue := 0;
   FMinValue := 0;
   FMaxValue := 100;
   FMaxValue := 100;
   FValue := 30;
   FValue := 30;
   FValueSub := 10;
   FValueSub := 10;
+  xpos:= 0;
+  xposSub:= 0;
+
   // Functionality and Style
   // Functionality and Style
   Randomize;
   Randomize;
   FRandSeed := RandSeed;
   FRandSeed := RandSeed;
@@ -710,6 +773,8 @@ begin
   FBackgroundRandomizeMaxIntensity := 5000;
   FBackgroundRandomizeMaxIntensity := 5000;
   FShowDividers:= False;
   FShowDividers:= False;
   FGraphShowYDividers:= False;
   FGraphShowYDividers:= False;
+  FShowBarAnimation:= False;
+  barAnimLeft:= 2;
 
 
   //Marquee
   //Marquee
   FMarqueeWidth:= 0; //AutoWidth
   FMarqueeWidth:= 0; //AutoWidth
@@ -737,7 +802,7 @@ begin
   FGraphYLineAfter:= '';
   FGraphYLineAfter:= '';
   FGraphYLineDigits:= 0;
   FGraphYLineDigits:= 0;
 
 
-  internalTimer:= TFPTimer.Create(nil);
+  internalTimer:= TFPTimer.Create(Self);
   internalTimer.Enabled:= False;
   internalTimer.Enabled:= False;
   internalTimer.Interval:= 20;
   internalTimer.Interval:= 20;
   internalTimer.OnTimer:= TimerOnTimer;
   internalTimer.OnTimer:= TimerOnTimer;
@@ -745,7 +810,11 @@ end;
 
 
 destructor TBGRAFlashProgressBar.Destroy;
 destructor TBGRAFlashProgressBar.Destroy;
 begin
 begin
-  internalTimer.Free;
+  //Avoid Exception when internalTimer is Enabled
+  internalTimer.Enabled:=False;
+  CheckSynchronize(100);
+
+  FreeAndNil(internalTimer);
   GraphValues:= nil;
   GraphValues:= nil;
   GraphPoints:= nil;
   GraphPoints:= nil;
   FBGRA.Free;
   FBGRA.Free;
@@ -831,18 +900,20 @@ var
        then fx:= TBGRATextEffect.Create(ACaption, Font.Name, ABitmap.Height div 2, True)
        then fx:= TBGRATextEffect.Create(ACaption, Font.Name, ABitmap.Height div 2, True)
        else fx:= TBGRATextEffect.Create(ACaption, Font, True);
        else fx:= TBGRATextEffect.Create(ACaption, Font, True);
 
 
+       y:= (ABitmap.Height-fx.TextHeight) div 2;
+
        Case AAlign of
        Case AAlign of
          taLeftJustify: begin
          taLeftJustify: begin
-           fx.DrawOutline(ABitmap, 4, ABitmap.Height div 5, BGRABlack, taLeftJustify);
-           fx.Draw(ABitmap, 4, ABitmap.Height div 5, BGRAWhite, taLeftJustify);
+           fx.DrawOutline(ABitmap, 4, y, BGRABlack, taLeftJustify);
+           fx.Draw(ABitmap, 4, y, BGRAWhite, taLeftJustify);
          end;
          end;
          taRightJustify: begin
          taRightJustify: begin
-           fx.DrawOutline(ABitmap, tx-4, ABitmap.Height div 5, BGRABlack, taRightJustify);
-           fx.Draw(ABitmap, tx-4, ABitmap.Height div 5, BGRAWhite, taRightJustify);
+           fx.DrawOutline(ABitmap, tx-4, y, BGRABlack, taRightJustify);
+           fx.Draw(ABitmap, tx-4, y, BGRAWhite, taRightJustify);
          end;
          end;
          taCenter: begin
          taCenter: begin
-           fx.DrawOutline(ABitmap, ABitmap.Width div 2, ABitmap.Height div 5, BGRABlack, taCenter);
-           fx.Draw(ABitmap, ABitmap.Width div 2, ABitmap.Height div 5, BGRAWhite, taCenter);
+           fx.DrawOutline(ABitmap, ABitmap.Width div 2, y, BGRABlack, taCenter);
+           fx.Draw(ABitmap, ABitmap.Width div 2, y, BGRAWhite, taCenter);
          end;
          end;
        end;
        end;
 
 
@@ -923,7 +994,7 @@ var
           try
           try
              fx:= TBGRATextEffect.Create(pStr, Font.Name, 12, True);
              fx:= TBGRATextEffect.Create(pStr, Font.Name, 12, True);
 
 
-             //Write the text above the line if possible
+             //Write the text above the line if possible else write below
              if (Round(posS-fx.TextHeight) >= 2) then posS:= posS-fx.TextHeight;
              if (Round(posS-fx.TextHeight) >= 2) then posS:= posS-fx.TextHeight;
 
 
              fx.Draw(ABitmap, tx-6, Round(posS), lColB, taRightJustify);
              fx.Draw(ABitmap, tx-6, Round(posS), lColB, taRightJustify);
@@ -935,6 +1006,12 @@ var
       end;
       end;
     end;
     end;
 
 
+    if FShowBarAnimation and (barAnimLeft > 0)
+    then ABitmap.GradientFill(barAnimLeft, content.Top, barAnimLeft+4, content.Bottom,
+                              BGRA(255, 255, 255, 4), BGRA(255, 255, 255, 16), gtLinear,
+                              PointF(barAnimLeft, content.Bottom-content.Top/2), PointF(barAnimLeft+4, content.Bottom-content.Top/2),
+                              dmLinearBlend);
+
     //Draw Value Text
     //Draw Value Text
     pStr:= '';
     pStr:= '';
     if FCaptionShowPercent then
     if FCaptionShowPercent then
@@ -987,6 +1064,12 @@ begin
 
 
             if FShowDividers then DrawDividers(False);
             if FShowDividers then DrawDividers(False);
 
 
+            if FShowBarAnimation and (barAnimLeft > 0)
+            then ABitmap.GradientFill(barAnimLeft, content.Top, barAnimLeft+4, content.Bottom,
+                                      BGRA(255, 255, 255, 4), BGRA(255, 255, 255, 16), gtLinear,
+                                      PointF(barAnimLeft, content.Bottom-content.Top/2), PointF(barAnimLeft+4, content.Bottom-content.Top/2),
+                                      dmLinearBlend);
+
             //Draw Value Text
             //Draw Value Text
             pStr:= '';
             pStr:= '';
             if FCaptionShowPercent then
             if FCaptionShowPercent then
@@ -1016,21 +1099,27 @@ begin
           end;
           end;
 
 
           //Draw ValueSub Bar
           //Draw ValueSub Bar
-          xpos := round((FValueSub - FMinValue) / (FMaxValue - FMinValue) *
-                        (content.right - content.left)) + content.left;
-          if xpos > content.left then
+          xposSub := round((FValueSub - FMinValue) / (FMaxValue - FMinValue) *
+                           (content.right - content.left)) + content.left;
+          if xposSub > content.left then
           begin
           begin
-            DrawBar(rect(content.left, content.top, xpos, content.bottom), FBarColorSub);
-            if xpos < content.right then
+            DrawBar(rect(content.left, content.top, xposSub, content.bottom), FBarColorSub);
+            if xposSub < content.right then
             begin
             begin
-              ABitmap.SetPixel(xpos, content.top, BGRA(62, 62, 62));
-              ABitmap.SetVertLine(xpos, content.top + 1, content.bottom - 1, BGRA(40, 40, 40));
+              ABitmap.SetPixel(xposSub, content.top, BGRA(62, 62, 62));
+              ABitmap.SetVertLine(xposSub, content.top + 1, content.bottom - 1, BGRA(40, 40, 40));
             end;
             end;
           end;
           end;
 
 
           if FShowDividers then DrawDividers(False);
           if FShowDividers then DrawDividers(False);
 
 
-          //Draw Value Text
+          if FShowBarAnimation and (barAnimLeft > 0)
+          then ABitmap.GradientFill(barAnimLeft, content.Top, barAnimLeft+4, content.Bottom,
+                                    BGRA(255, 255, 255, 4), BGRA(255, 255, 255, 16), gtLinear,
+                                    PointF(barAnimLeft, content.Bottom-content.Top/2), PointF(barAnimLeft+4, content.Bottom-content.Top/2),
+                                    dmLinearBlend);
+
+         //Draw Value Text
           pStr:= '';
           pStr:= '';
           if FCaptionShowPercent then
           if FCaptionShowPercent then
           begin
           begin

+ 11 - 0
test/test_progressbar/umain.lfm

@@ -6,6 +6,8 @@ object Form1: TForm1
   Caption = 'Form1'
   Caption = 'Form1'
   ClientHeight = 452
   ClientHeight = 452
   ClientWidth = 523
   ClientWidth = 523
+  OnClose = FormClose
+  OnCreate = FormCreate
   OnShow = FormShow
   OnShow = FormShow
   object BGRAMaxMProgress: TBGRAFlashProgressBar
   object BGRAMaxMProgress: TBGRAFlashProgressBar
     Left = 4
     Left = 4
@@ -893,6 +895,15 @@ object Form1: TForm1
     Width = 60
     Width = 60
     Caption = 'Back Color:'
     Caption = 'Back Color:'
   end
   end
+  object cbShowBarAnimation: TCheckBox
+    Left = 361
+    Height = 19
+    Top = 124
+    Width = 126
+    Caption = 'Show Bar Animation'
+    TabOrder = 7
+    OnChange = cbShowBarAnimationChange
+  end
   object ColorDialog1: TColorDialog
   object ColorDialog1: TColorDialog
     Color = clBlack
     Color = clBlack
     CustomColors.Strings = (
     CustomColors.Strings = (

+ 20 - 0
test/test_progressbar/umain.pas

@@ -32,6 +32,7 @@ type
     cbTimerAutoStart: TCheckBox;
     cbTimerAutoStart: TCheckBox;
     cbTimerAutoStart1: TCheckBox;
     cbTimerAutoStart1: TCheckBox;
     cbRandG: TCheckBox;
     cbRandG: TCheckBox;
+    cbShowBarAnimation: TCheckBox;
     ColorDialog1: TColorDialog;
     ColorDialog1: TColorDialog;
     btBarColor: TColorSpeedButton;
     btBarColor: TColorSpeedButton;
     edCaption: TEdit;
     edCaption: TEdit;
@@ -104,6 +105,7 @@ type
     procedure cbCaptionPercentMChange(Sender: TObject);
     procedure cbCaptionPercentMChange(Sender: TObject);
     procedure cbMarqueeWidthChange(Sender: TObject);
     procedure cbMarqueeWidthChange(Sender: TObject);
     procedure cbCaptionPercentChange(Sender: TObject);
     procedure cbCaptionPercentChange(Sender: TObject);
+    procedure cbShowBarAnimationChange(Sender: TObject);
     procedure cbShowDividersChange(Sender: TObject);
     procedure cbShowDividersChange(Sender: TObject);
     procedure cbShowDividersYChange(Sender: TObject);
     procedure cbShowDividersYChange(Sender: TObject);
     procedure cbShowYLineChange(Sender: TObject);
     procedure cbShowYLineChange(Sender: TObject);
@@ -122,6 +124,8 @@ type
     procedure edYLineAfterChange(Sender: TObject);
     procedure edYLineAfterChange(Sender: TObject);
     procedure edYLineCaptionChange(Sender: TObject);
     procedure edYLineCaptionChange(Sender: TObject);
     procedure edYLineDigitsChange(Sender: TObject);
     procedure edYLineDigitsChange(Sender: TObject);
+    procedure FormClose(Sender: TObject; var CloseAction: TCloseAction);
+    procedure FormCreate(Sender: TObject);
     procedure FormShow(Sender: TObject);
     procedure FormShow(Sender: TObject);
     procedure PageControl1Change(Sender: TObject);
     procedure PageControl1Change(Sender: TObject);
     procedure rgCaptionAlignClick(Sender: TObject);
     procedure rgCaptionAlignClick(Sender: TObject);
@@ -131,6 +135,7 @@ type
   private
   private
     { private declarations }
     { private declarations }
     aCount: Integer;
     aCount: Integer;
+    Closing: Boolean;
   public
   public
     { public declarations }
     { public declarations }
   end;
   end;
@@ -189,6 +194,11 @@ begin
   BGRAMaxMProgress.CaptionShowPercent:= cbCaptionPercent.Checked;
   BGRAMaxMProgress.CaptionShowPercent:= cbCaptionPercent.Checked;
 end;
 end;
 
 
+procedure TForm1.cbShowBarAnimationChange(Sender: TObject);
+begin
+  BGRAMaxMProgress.ShowBarAnimation:= cbShowBarAnimation.Checked;
+end;
+
 procedure TForm1.cbShowDividersChange(Sender: TObject);
 procedure TForm1.cbShowDividersChange(Sender: TObject);
 begin
 begin
   BGRAMaxMProgress.ShowDividers:= cbShowDividers.Checked;
   BGRAMaxMProgress.ShowDividers:= cbShowDividers.Checked;
@@ -300,6 +310,16 @@ begin
   BGRAMaxMProgress.GraphYLineDigits:= edYLineDigits.Value;
   BGRAMaxMProgress.GraphYLineDigits:= edYLineDigits.Value;
 end;
 end;
 
 
+procedure TForm1.FormClose(Sender: TObject; var CloseAction: TCloseAction);
+begin
+  Closing:= True;
+end;
+
+procedure TForm1.FormCreate(Sender: TObject);
+begin
+  Closing:= False;
+end;
+
 procedure TForm1.FormShow(Sender: TObject);
 procedure TForm1.FormShow(Sender: TObject);
 begin
 begin
   PageControl1.ActivePage:= TabNormal;
   PageControl1.ActivePage:= TabNormal;