Advertisement
Guest User

Show activity indicator while the main thread is blocked

a guest
Sep 25th, 2014
726
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Delphi 5.97 KB | None | 0 0
  1. unit AniThread;
  2.  
  3. interface
  4.  
  5. uses Windows, Classes, Graphics, Controls, Math;
  6.  
  7. const
  8.   ANI_GRAD_FG_COLOR_BAGIN = $00CDFFCD;
  9.   ANI_GRAD_FG_COLOR_END   = $0024B105;
  10.   ANI_GRAD_BK_COLOR_BAGIN = $00F5F5F5;
  11.   ANI_GRAD_BK_COLOR_END   = $00BDBDBD;
  12.  
  13. type
  14.   TAnimationThread = class(TThread)
  15.   private
  16.     FWnd: HWND;
  17.     FPaintRect: TRect;
  18.     FInterval: Integer;
  19.     FfgPattern, FbkPattern: TBitmap;
  20.     FBitmap: TBitmap;
  21.     FImageRect: TRect;
  22.     procedure UpdatePattern(Pattern: TBitmap; ColorBegin, ColorEnd: TColor);
  23.     function CreatePatternBitmap(AColorBegin, AColorEnd: TColor): TBitmap;
  24.     procedure PaintTargetWindow;
  25.   protected
  26.     procedure Execute; override;
  27.   public
  28.     procedure Animate;
  29.     constructor Create(
  30.       PaintSurface: TWinControl; { Control to paint on }
  31.       PaintRect: TRect;          { area for animation bar }
  32.       Interval: Integer;         { wait in msecs between paints}
  33.       CreateSuspended: Boolean=False);
  34.     destructor Destroy; override;
  35.   end;
  36.  
  37. implementation
  38.  
  39. constructor TAnimationThread.Create(
  40.   PaintSurface: TWinControl;
  41.   PaintRect: TRect;
  42.   Interval: Integer;
  43.   CreateSuspended: Boolean);
  44. begin
  45.   FreeOnterminate := True;
  46.   FInterval := Interval;
  47.   FWnd := PaintSurface.Handle;
  48.   FPaintRect := PaintRect;
  49.   FfgPattern := CreatePatternBitmap(ANI_GRAD_FG_COLOR_BAGIN, ANI_GRAD_FG_COLOR_END);
  50.   FbkPattern := CreatePatternBitmap(ANI_GRAD_BK_COLOR_BAGIN, ANI_GRAD_BK_COLOR_END);
  51.   FBitmap := TBitmap.Create;
  52.   inherited Create(CreateSuspended);
  53.   Priority := tpHigher;
  54. end;
  55.  
  56. destructor TAnimationThread.Destroy;
  57. begin
  58.   FfgPattern.Free;
  59.   FbkPattern.Free;
  60.   FBitmap.Free;
  61.   inherited Destroy;
  62. end;
  63.  
  64. procedure TAnimationThread.Animate;
  65. begin
  66.   if Suspended then
  67.   begin
  68.     Resume;
  69.     Sleep(0);
  70.   end;
  71. end;
  72.  
  73. function TAnimationThread.CreatePatternBitmap(AColorBegin, AColorEnd: TColor): TBitmap;
  74. begin
  75.   Result := TBitmap.Create;
  76.   Result.PixelFormat := pf24bit;
  77.   UpdatePattern(Result, AColorBegin, AColorEnd);
  78. end;
  79.  
  80. type
  81.   PRGBTripleArray = ^TRGBTripleArray;
  82.   TRGBTripleArray = array[0..32767] of TRGBTriple;
  83.   TGradientColors = array[0..255] of TRGBTriple;
  84.  
  85. procedure PatternBuilder(const Colors: TGradientColors; Pattern: TBitmap);
  86. var
  87.   Y: Integer;
  88.   Row: PRGBTripleArray;
  89. begin
  90.   Pattern.Width := 1;
  91.   Pattern.Height := 256;
  92.   for Y := 0 to 127 do
  93.   begin
  94.     Row := PRGBTripleArray(Pattern.ScanLine[Y]);
  95.     Row[0] := Colors[Y];
  96.     Row := PRGBTripleArray(Pattern.ScanLine[Y + 128]);
  97.     Row[0] := Colors[255 - Y];
  98.   end;
  99. end;
  100.  
  101. procedure TAnimationThread.UpdatePattern(Pattern: TBitmap; ColorBegin, ColorEnd: TColor);
  102. var
  103.   Colors: TGradientColors;
  104.   dRed, dGreen, dBlue: Integer;
  105.   RGBColor1, RGBColor2: TColor;
  106.   RGB1, RGB2: TRGBTriple;
  107.   Index: Integer;
  108. begin
  109.   Pattern.Canvas.Lock;
  110.   try
  111.     RGBColor1 := ColorToRGB(ColorBegin);
  112.     RGBColor2 := ColorToRGB(ColorEnd);
  113.  
  114.     RGB1.rgbtRed := GetRValue(RGBColor1);
  115.     RGB1.rgbtGreen := GetGValue(RGBColor1);
  116.     RGB1.rgbtBlue := GetBValue(RGBColor1);
  117.  
  118.     RGB2.rgbtRed := GetRValue(RGBColor2);
  119.     RGB2.rgbtGreen := GetGValue(RGBColor2);
  120.     RGB2.rgbtBlue := GetBValue(RGBColor2);
  121.  
  122.     dRed := RGB2.rgbtRed - RGB1.rgbtRed;
  123.     dGreen := RGB2.rgbtGreen - RGB1.rgbtGreen;
  124.     dBlue := RGB2.rgbtBlue - RGB1.rgbtBlue;
  125.  
  126.     for Index := 0 to 255 do
  127.       with Colors[Index] do
  128.       begin
  129.         rgbtRed := RGB1.rgbtRed + (Index * dRed) div 255;
  130.         rgbtGreen := RGB1.rgbtGreen + (Index * dGreen) div 255;
  131.         rgbtBlue := RGB1.rgbtBlue + (Index * dBlue) div 255;
  132.       end;
  133.  
  134.     PatternBuilder(Colors, Pattern);
  135.   finally
  136.     Pattern.Canvas.Unlock;
  137.   end;
  138. end;
  139.  
  140. procedure TAnimationThread.PaintTargetWindow;
  141. var
  142.   DC: HDC;
  143. begin
  144.   DC := GetDC(FWnd);
  145.   if DC <> 0 then
  146.   try
  147.     BitBlt(DC,
  148.       FPaintRect.Left,
  149.       FPaintRect.Top,
  150.       FImageRect.Right,
  151.       FImageRect.Bottom,
  152.       FBitmap.Canvas.Handle,
  153.       0, 0,
  154.       SRCCOPY);
  155.   finally
  156.     ReleaseDC(FWnd, DC);
  157.   end;
  158. end;
  159.  
  160. procedure TAnimationThread.Execute;
  161. var
  162.   Left, Right: Integer;
  163.   Increment: Integer;
  164.   State: (incRight, incLeft, decLeft, decRight);
  165. begin
  166.   FBitmap.Canvas.Lock;
  167.   FbkPattern.Canvas.Lock;
  168.   FfgPattern.Canvas.Lock;
  169.   try
  170.     InvalidateRect(FWnd, nil, True);
  171.     with FBitmap do
  172.     begin
  173.       Width := FPaintRect.Right - FPaintRect.Left;
  174.       Height := FPaintRect.Bottom - FPaintRect.Top;
  175.       FImageRect := Rect(0, 0, Width, Height);
  176.     end;
  177.     Left := 0;
  178.     Right := 0;
  179.     Increment := FImageRect.Right div 50;
  180.     State := Low(State);
  181.     while not Terminated do
  182.     begin
  183.       with FBitmap.Canvas do
  184.       begin
  185.         StretchDraw(FImageRect, FbkPattern);
  186.         case State of
  187.           incRight:
  188.             begin
  189.               Inc(Right, Increment);
  190.               if Right > FImageRect.Right then begin
  191.                 Right := FImageRect.Right;
  192.                 Inc(State);
  193.               end;
  194.             end;
  195.           incLeft:
  196.             begin
  197.               Inc(Left, Increment);
  198.               if Left >= Right then begin
  199.                 Left := Right;
  200.                 Inc(State);
  201.               end;
  202.             end;
  203.           decLeft:
  204.             begin
  205.               Dec(Left, Increment);
  206.               if Left <= 0 then begin
  207.                 Left := 0;
  208.                 Inc(State);
  209.               end;
  210.             end;
  211.           decRight:
  212.             begin
  213.               Dec(Right, Increment);
  214.               if Right <= 0 then begin
  215.                 Right := 0;
  216.                 State := incRight;
  217.               end;
  218.             end;
  219.         end;
  220.  
  221.         StretchDraw(Rect(Left, FImageRect.Top, Right, FImageRect.Bottom), FfgPattern);
  222.       end; { with FBitmap.Canvas }
  223.  
  224.       // Synchronize(PaintTargetWindow); // not painting when the main thread is blocked
  225.       PaintTargetWindow;
  226.  
  227.       SleepEx(FInterval, False);
  228.     end; { While not Terminated }
  229.   finally
  230.     FfgPattern.Canvas.Unlock;
  231.     FbkPattern.Canvas.Unlock;
  232.     FBitmap.Canvas.Unlock;
  233.   end;
  234. end;
  235.  
  236. end.
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement