Animate.pas
上传用户:hylc_2004
上传日期:2014-01-23
资源大小:46800k
文件大小:20k
源码类别:

Delphi控件源码

开发平台:

Delphi

  1. {*******************************************************}
  2. {                                                       }
  3. {         Delphi VCL Extensions (RX)                    }
  4. {                                                       }
  5. {         Copyright (c) 1995, 1996 AO ROSNO             }
  6. {         Copyright (c) 1997, 1998 Master-Bank          }
  7. {                                                       }
  8. {*******************************************************}
  9. unit Animate;
  10. interface
  11. {$I RX.INC}
  12. uses Messages, {$IFDEF WIN32} Windows, {$ELSE} WinTypes, WinProcs, {$ENDIF}
  13.   SysUtils, Classes, Graphics, Controls, Forms, StdCtrls, Menus, RxTimer;
  14. type
  15. { TRxImageControl }
  16.   TRxImageControl = class(TGraphicControl)
  17.   private
  18.     FDrawing: Boolean;
  19.     FPaintBuffered: Boolean;
  20. {$IFDEF RX_D3}
  21.     FLock: TRTLCriticalSection;
  22. {$ENDIF}
  23.     procedure WMPaint(var Message: TWMPaint); message WM_PAINT;
  24.   protected
  25.     FGraphic: TGraphic;
  26.     function DoPaletteChange: Boolean;
  27. {$IFNDEF RX_D4}
  28.     procedure AdjustSize; virtual; abstract;
  29. {$ENDIF}
  30.     procedure DoPaintImage; virtual; abstract;
  31.     procedure DoPaintControl;
  32.     procedure PaintDesignRect;
  33.     procedure PaintImage;
  34.     procedure PictureChanged;
  35.     procedure Lock;
  36.     procedure Unlock;
  37.   public
  38.     constructor Create(AOwner: TComponent); override;
  39.     destructor Destroy; override;
  40.   end;
  41. { TAnimatedImage }
  42.   TGlyphOrientation = (goHorizontal, goVertical);
  43.   TAnimatedImage = class(TRxImageControl)
  44.   private
  45.     FActive: Boolean;
  46.     FGlyph: TBitmap;
  47.     FImageWidth: Integer;
  48.     FImageHeight: Integer;
  49.     FInactiveGlyph: Integer;
  50.     FOrientation: TGlyphOrientation;
  51.     FTimer: TRxTimer;
  52.     FNumGlyphs: Integer;
  53.     FGlyphNum: Integer;
  54.     FCenter: Boolean;
  55.     FStretch: Boolean;
  56.     FTransparentColor: TColor;
  57.     FOpaque: Boolean;
  58.     FTimerRepaint: Boolean;
  59.     FOnFrameChanged: TNotifyEvent;
  60.     FOnStart: TNotifyEvent;
  61.     FOnStop: TNotifyEvent;
  62. {$IFDEF RX_D3}
  63.     FAsyncDrawing: Boolean;
  64. {$ENDIF}
  65. {$IFNDEF RX_D4}
  66.     FAutoSize: Boolean;
  67.     procedure SetAutoSize(Value: Boolean);
  68. {$ENDIF}
  69.     procedure DefineBitmapSize;
  70.     procedure ResetImageBounds;
  71.     function GetInterval: Cardinal;
  72.     procedure SetInterval(Value: Cardinal);
  73.     procedure SetActive(Value: Boolean);
  74. {$IFDEF RX_D3}
  75.     procedure SetAsyncDrawing(Value: Boolean);
  76. {$ENDIF}
  77.     procedure SetCenter(Value: Boolean);
  78.     procedure SetOrientation(Value: TGlyphOrientation);
  79.     procedure SetGlyph(Value: TBitmap);
  80.     procedure SetGlyphNum(Value: Integer);
  81.     procedure SetInactiveGlyph(Value: Integer);
  82.     procedure SetNumGlyphs(Value: Integer);
  83.     procedure SetStretch(Value: Boolean);
  84.     procedure SetTransparentColor(Value: TColor);
  85.     procedure SetOpaque(Value: Boolean);
  86.     procedure ImageChanged(Sender: TObject);
  87.     procedure UpdateInactive;
  88.     procedure TimerExpired(Sender: TObject);
  89.     function TransparentStored: Boolean;
  90.     procedure WMSize(var Message: TWMSize); message WM_SIZE;
  91.   protected
  92. {$IFDEF RX_D4}
  93.     function CanAutoSize(var NewWidth, NewHeight: Integer): Boolean; override;
  94. {$ENDIF}
  95.     function GetPalette: HPALETTE; override;
  96.     procedure AdjustSize; override;
  97.     procedure Loaded; override;
  98.     procedure Paint; override;
  99.     procedure DoPaintImage; override;
  100.     procedure FrameChanged; dynamic;
  101.     procedure Start; dynamic;
  102.     procedure Stop; dynamic;
  103.   public
  104.     constructor Create(AOwner: TComponent); override;
  105.     destructor Destroy; override;
  106.   published
  107.     property Align;
  108. {$IFDEF RX_D4}
  109.     property Anchors;
  110.     property Constraints;
  111.     property DragKind;
  112.     property AutoSize default True;
  113. {$ELSE}
  114.     property AutoSize: Boolean read FAutoSize write SetAutoSize default True;
  115. {$ENDIF}
  116. {$IFDEF RX_D3}
  117.     property AsyncDrawing: Boolean read FAsyncDrawing write SetAsyncDrawing default False;
  118. {$ENDIF}
  119.     property Active: Boolean read FActive write SetActive default False;
  120.     property Center: Boolean read FCenter write SetCenter default False;
  121.     property Orientation: TGlyphOrientation read FOrientation write SetOrientation
  122.       default goHorizontal;
  123.     property Glyph: TBitmap read FGlyph write SetGlyph;
  124.     property GlyphNum: Integer read FGlyphNum write SetGlyphNum default 0;
  125.     property Interval: Cardinal read GetInterval write SetInterval default 100;
  126.     property NumGlyphs: Integer read FNumGlyphs write SetNumGlyphs default 1;
  127.     property InactiveGlyph: Integer read FInactiveGlyph write SetInactiveGlyph default -1;
  128.     property TransparentColor: TColor read FTransparentColor write SetTransparentColor
  129.       stored TransparentStored;
  130.     property Opaque: Boolean read FOpaque write SetOpaque default False;
  131.     property Color;
  132.     property Cursor;
  133.     property DragCursor;
  134.     property DragMode;
  135.     property ParentColor default True;
  136.     property ParentShowHint;
  137.     property PopupMenu;
  138.     property ShowHint;
  139.     property Stretch: Boolean read FStretch write SetStretch default True;
  140.     property Visible;
  141.     property OnClick;
  142.     property OnDblClick;
  143.     property OnMouseMove;
  144.     property OnMouseDown;
  145.     property OnMouseUp;
  146.     property OnDragOver;
  147.     property OnDragDrop;
  148.     property OnEndDrag;
  149. {$IFDEF WIN32}
  150.     property OnStartDrag;
  151. {$ENDIF}
  152. {$IFDEF RX_D4}
  153.     property OnEndDock;
  154.     property OnStartDock;
  155. {$ENDIF}
  156. {$IFDEF RX_D5}
  157.     property OnContextPopup;
  158. {$ENDIF}
  159.     property OnFrameChanged: TNotifyEvent read FOnFrameChanged write FOnFrameChanged;
  160.     property OnStart: TNotifyEvent read FOnStart write FOnStart;
  161.     property OnStop: TNotifyEvent read FOnStop write FOnStop;
  162.   end;
  163. {$IFDEF RX_D3}
  164. procedure HookBitmap;
  165. {$ENDIF}
  166. implementation
  167. uses RxConst, {$IFDEF RX_D3} RxHook, {$ENDIF} VCLUtils;
  168. {$IFDEF RX_D3}
  169. { THackBitmap }
  170. type
  171.   THackBitmap = class(TBitmap)
  172.   protected
  173.     procedure Draw(ACanvas: TCanvas; const Rect: TRect); override;
  174.   end;
  175. procedure THackBitmap.Draw(ACanvas: TCanvas; const Rect: TRect);
  176. begin
  177.   if not Empty then Canvas.Lock;
  178.   try
  179.     inherited Draw(ACanvas, Rect);
  180.   finally
  181.     if not Empty then Canvas.Unlock;
  182.   end;
  183. end;
  184. type
  185.   THack = class(TBitmap);
  186. var
  187.   Hooked: Boolean = False;
  188. procedure HookBitmap;
  189. var
  190.   Index: Integer;
  191. begin
  192.   if Hooked then Exit;
  193.   Index := FindVirtualMethodIndex(THack, @THack.Draw);
  194.   SetVirtualMethodAddress(TBitmap, Index, @THackBitmap.Draw);
  195.   Hooked := True;
  196. end;
  197. {$ENDIF RX_D3}
  198. { TRxImageControl }
  199. constructor TRxImageControl.Create(AOwner: TComponent);
  200. begin
  201.   inherited Create(AOwner);
  202. {$IFDEF RX_D3}
  203.   InitializeCriticalSection(FLock);
  204. {$ENDIF}
  205.   ControlStyle := ControlStyle + [csClickEvents, csCaptureMouse, csOpaque,
  206.     {$IFDEF WIN32} csReplicatable, {$ENDIF} csDoubleClicks];
  207.   Height := 105;
  208.   Width := 105;
  209.   ParentColor := True;
  210. end;
  211. destructor TRxImageControl.Destroy;
  212. begin
  213. {$IFDEF RX_D3}
  214.   DeleteCriticalSection(FLock);
  215. {$ENDIF}
  216.   inherited Destroy;
  217. end;
  218. procedure TRxImageControl.Lock;
  219. begin
  220. {$IFDEF RX_D3}
  221.   EnterCriticalSection(FLock);
  222. {$ENDIF}
  223. end;
  224. procedure TRxImageControl.Unlock;
  225. begin
  226. {$IFDEF RX_D3}
  227.   LeaveCriticalSection(FLock);
  228. {$ENDIF}
  229. end;
  230. procedure TRxImageControl.PaintImage;
  231. var
  232.   Save: Boolean;
  233. begin
  234.   with Canvas do begin
  235.     Brush.Color := Color;
  236.     FillRect(Bounds(0, 0, ClientWidth, ClientHeight));
  237.   end;
  238.   Save := FDrawing;
  239.   FDrawing := True;
  240.   try
  241.     DoPaintImage;
  242.   finally
  243.     FDrawing := Save;
  244.   end;
  245. end;
  246. procedure TRxImageControl.WMPaint(var Message: TWMPaint);
  247. var
  248.   DC, MemDC: HDC;
  249.   MemBitmap, OldBitmap: HBITMAP;
  250. begin
  251.   if FPaintBuffered then
  252.     inherited
  253.   else if Message.DC <> 0 then begin
  254. {$IFDEF RX_D3}
  255.     Canvas.Lock;
  256.     try
  257. {$ENDIF}
  258.       DC := Message.DC;
  259.       MemDC := GetDC(0);
  260.       MemBitmap := CreateCompatibleBitmap(MemDC, ClientWidth, ClientHeight);
  261.       ReleaseDC(0, MemDC);
  262.       MemDC := CreateCompatibleDC(0);
  263.       OldBitmap := SelectObject(MemDC, MemBitmap);
  264.       try
  265.         FPaintBuffered := True;
  266.         try
  267.           Message.DC := MemDC;
  268.           WMPaint(Message);
  269.           Message.DC := 0;
  270.         finally
  271.           FPaintBuffered := False;
  272.         end;
  273.         BitBlt(DC, 0, 0, ClientWidth, ClientHeight, MemDC, 0, 0, SRCCOPY);
  274.       finally
  275.         SelectObject(MemDC, OldBitmap);
  276.         DeleteDC(MemDC);
  277.         DeleteObject(MemBitmap);
  278.       end;
  279. {$IFDEF RX_D3}
  280.     finally
  281.       Canvas.Unlock;
  282.     end;
  283. {$ENDIF}
  284.   end;
  285. end;
  286. procedure TRxImageControl.PaintDesignRect;
  287. begin
  288.   if csDesigning in ComponentState then
  289.     with Canvas do begin
  290.       Pen.Style := psDash;
  291.       Brush.Style := bsClear;
  292.       Rectangle(0, 0, Width, Height);
  293.     end;
  294. end;
  295. procedure TRxImageControl.DoPaintControl;
  296. var
  297.   DC: HDC;
  298. begin
  299. {$IFDEF RX_D3}
  300.   if GetCurrentThreadID = MainThreadID then begin
  301.     Repaint;
  302.     Exit;
  303.   end;
  304. {$ENDIF}
  305.   DC := GetDC(Parent.Handle);
  306.   try
  307.     IntersectClipRect(DC, Left, Top, Left + Width, Top + Height);
  308.     MoveWindowOrg(DC, Left, Top);
  309.     Perform(WM_PAINT, DC, 0);
  310.   finally
  311.     ReleaseDC(Parent.Handle, DC);
  312.   end;
  313. end;
  314. function TRxImageControl.DoPaletteChange: Boolean;
  315. var
  316.   ParentForm: TCustomForm;
  317.   Tmp: TGraphic;
  318. begin
  319.   Result := False;
  320.   Tmp := FGraphic;
  321.   if Visible and (not (csLoading in ComponentState)) and (Tmp <> nil)
  322.     {$IFDEF RX_D3} and (Tmp.PaletteModified) {$ENDIF} then
  323.   begin
  324.     if (GetPalette <> 0) then begin
  325.       ParentForm := GetParentForm(Self);
  326.       if Assigned(ParentForm) and ParentForm.Active and ParentForm.HandleAllocated then
  327.       begin
  328.         if FDrawing then
  329.           ParentForm.Perform(WM_QUERYNEWPALETTE, 0, 0)
  330.         else
  331.           PostMessage(ParentForm.Handle, WM_QUERYNEWPALETTE, 0, 0);
  332.         Result := True;
  333. {$IFDEF RX_D3}
  334.         Tmp.PaletteModified := False;
  335. {$ENDIF}
  336.       end;
  337.     end
  338. {$IFDEF RX_D3}
  339.     else begin
  340.       Tmp.PaletteModified := False;
  341.     end;
  342. {$ENDIF}
  343.   end;
  344. end;
  345. procedure TRxImageControl.PictureChanged;
  346. begin
  347.   if not (csDestroying in ComponentState) then begin
  348.     AdjustSize;
  349.     if (FGraphic <> nil) then
  350.       if DoPaletteChange and FDrawing then Update;
  351.     if not FDrawing then Invalidate;
  352.   end;
  353. end;
  354. { TAnimatedImage }
  355. constructor TAnimatedImage.Create(AOwner: TComponent);
  356. begin
  357.   inherited Create(AOwner);
  358.   FTimer := TRxTimer.Create(Self);
  359.   with FTimer do begin
  360.     Enabled := False;
  361.     Interval := 100;
  362.   end;
  363.   AutoSize := True;
  364.   FGlyph := TBitmap.Create;
  365.   FGraphic := FGlyph;
  366.   FGlyph.OnChange := ImageChanged;
  367.   FNumGlyphs := 1;
  368.   FInactiveGlyph := -1;
  369.   FTransparentColor := clNone;
  370.   FOrientation := goHorizontal;
  371.   FStretch := True;
  372. end;
  373. destructor TAnimatedImage.Destroy;
  374. begin
  375.   Destroying;
  376.   FOnFrameChanged := nil;
  377.   FOnStart := nil;
  378.   FOnStop := nil;
  379.   FGlyph.OnChange := nil;
  380.   Active := False;
  381.   FGlyph.Free;
  382.   inherited Destroy;
  383. end;
  384. procedure TAnimatedImage.Loaded;
  385. begin
  386.   inherited Loaded;
  387.   ResetImageBounds;
  388.   UpdateInactive;
  389. end;
  390. function TAnimatedImage.GetPalette: HPALETTE;
  391. begin
  392.   Result := 0;
  393.   if not FGlyph.Empty then Result := FGlyph.Palette;
  394. end;
  395. procedure TAnimatedImage.ImageChanged(Sender: TObject);
  396. begin
  397.   Lock;
  398.   try
  399.     FTransparentColor := FGlyph.TransparentColor and not PaletteMask;
  400.   finally
  401.     Unlock;
  402.   end;
  403.   DefineBitmapSize;
  404.   PictureChanged;
  405. end;
  406. procedure TAnimatedImage.UpdateInactive;
  407. begin
  408.   if (not Active) and (FInactiveGlyph >= 0) and
  409.     (FInactiveGlyph < FNumGlyphs) and (FGlyphNum <> FInactiveGlyph) then
  410.   begin
  411.     Lock;
  412.     try
  413.       FGlyphNum := FInactiveGlyph;
  414.     finally
  415.       Unlock;
  416.     end;
  417.   end;
  418. end;
  419. function TAnimatedImage.TransparentStored: Boolean;
  420. begin
  421.   Result := (FGlyph.Empty and (FTransparentColor <> clNone)) or
  422.     ((FGlyph.TransparentColor and not PaletteMask) <>
  423.     FTransparentColor);
  424. end;
  425. procedure TAnimatedImage.SetOpaque(Value: Boolean);
  426. begin
  427.   if Value <> FOpaque then begin
  428.     Lock;
  429.     try
  430.       FOpaque := Value;
  431.     finally
  432.       Unlock;
  433.     end;
  434.     PictureChanged;
  435.   end;
  436. end;
  437. procedure TAnimatedImage.SetTransparentColor(Value: TColor);
  438. begin
  439.   if Value <> TransparentColor then begin
  440.     Lock;
  441.     try
  442.       FTransparentColor := Value;
  443.     finally
  444.       Unlock;
  445.     end;
  446.     PictureChanged;
  447.   end;
  448. end;
  449. procedure TAnimatedImage.SetOrientation(Value: TGlyphOrientation);
  450. begin
  451.   if FOrientation <> Value then begin
  452.     Lock;
  453.     try
  454.       FOrientation := Value;
  455.     finally
  456.       Unlock;
  457.     end;
  458.     ImageChanged(FGlyph);
  459.   end;
  460. end;
  461. procedure TAnimatedImage.SetGlyph(Value: TBitmap);
  462. begin
  463.   Lock;
  464.   try
  465.     FGlyph.Assign(Value);
  466.   finally
  467.     Unlock;
  468.   end;
  469. end;
  470. procedure TAnimatedImage.SetStretch(Value: Boolean);
  471. begin
  472.   if Value <> FStretch then begin
  473.     Lock;
  474.     try
  475.       FStretch := Value;
  476.     finally
  477.       Unlock;
  478.     end;
  479.     PictureChanged;
  480.     if Active then Repaint;
  481.   end;
  482. end;
  483. procedure TAnimatedImage.SetCenter(Value: Boolean);
  484. begin
  485.   if Value <> FCenter then begin
  486.     Lock;
  487.     try
  488.       FCenter := Value;
  489.     finally
  490.       Unlock;
  491.     end;
  492.     PictureChanged;
  493.     if Active then Repaint;
  494.   end;
  495. end;
  496. procedure TAnimatedImage.SetGlyphNum(Value: Integer);
  497. begin
  498.   if Value <> FGlyphNum then begin
  499.     if (Value < FNumGlyphs) and (Value >= 0) then begin
  500.       Lock;
  501.       try
  502.         FGlyphNum := Value;
  503.       finally
  504.         Unlock;
  505.       end;
  506.       UpdateInactive;
  507.       FrameChanged;
  508.       PictureChanged;
  509.     end;
  510.   end;
  511. end;
  512. procedure TAnimatedImage.SetInactiveGlyph(Value: Integer);
  513. begin
  514.   if Value < 0 then Value := -1;
  515.   if Value <> FInactiveGlyph then begin
  516.     if (Value < FNumGlyphs) or (csLoading in ComponentState) then begin
  517.       Lock;
  518.       try
  519.         FInactiveGlyph := Value;
  520.         UpdateInactive;
  521.       finally
  522.         Unlock;
  523.       end;
  524.       FrameChanged;
  525.       PictureChanged;
  526.     end;
  527.   end;
  528. end;
  529. procedure TAnimatedImage.SetNumGlyphs(Value: Integer);
  530. begin
  531.   Lock;
  532.   try
  533.     FNumGlyphs := Value;
  534.     if FInactiveGlyph >= FNumGlyphs then begin
  535.       FInactiveGlyph := -1;
  536.       FGlyphNum := 0;
  537.     end
  538.     else UpdateInactive;
  539.     ResetImageBounds;
  540.   finally
  541.     Unlock;
  542.   end;
  543.   FrameChanged;
  544.   PictureChanged;
  545. end;
  546. procedure TAnimatedImage.DefineBitmapSize;
  547. begin
  548.   Lock;
  549.   try
  550.     FNumGlyphs := 1;
  551.     FGlyphNum := 0;
  552.     FImageWidth := 0;
  553.     FImageHeight := 0;
  554.     if (FOrientation = goHorizontal) and (FGlyph.Height > 0) and
  555.       (FGlyph.Width mod FGlyph.Height = 0) then
  556.       FNumGlyphs := FGlyph.Width div FGlyph.Height
  557.     else if (FOrientation = goVertical) and (FGlyph.Width > 0) and
  558.       (FGlyph.Height mod FGlyph.Width = 0) then
  559.       FNumGlyphs := FGlyph.Height div FGlyph.Width;
  560.     ResetImageBounds;
  561.   finally
  562.     Unlock;
  563.   end;
  564. end;
  565. procedure TAnimatedImage.ResetImageBounds;
  566. begin
  567.   if FNumGlyphs < 1 then FNumGlyphs := 1;
  568.   if FOrientation = goHorizontal then begin
  569.     FImageHeight := FGlyph.Height;
  570.     FImageWidth := FGlyph.Width div FNumGlyphs;
  571.   end
  572.   else {if Orientation = goVertical then} begin
  573.     FImageWidth := FGlyph.Width;
  574.     FImageHeight := FGlyph.Height div FNumGlyphs;
  575.   end;
  576. end;
  577. procedure TAnimatedImage.AdjustSize;
  578. begin
  579.   if not (csReading in ComponentState) then begin
  580.     if AutoSize and (FImageWidth > 0) and (FImageHeight > 0) then
  581.       SetBounds(Left, Top, FImageWidth, FImageHeight);
  582.   end;
  583. end;
  584. procedure TAnimatedImage.DoPaintImage;
  585. var
  586.   BmpIndex: Integer;
  587.   SrcRect, DstRect: TRect;
  588.   {Origin: TPoint;}
  589. begin
  590.   if (not Active) and (FInactiveGlyph >= 0) and
  591.     (FInactiveGlyph < FNumGlyphs) then BmpIndex := FInactiveGlyph
  592.   else BmpIndex := FGlyphNum;
  593.   { copy image from parent and back-level controls }
  594.   if not FOpaque then CopyParentImage(Self, Canvas);
  595.   if (FImageWidth > 0) and (FImageHeight > 0) then begin
  596.     if Orientation = goHorizontal then
  597.       SrcRect := Bounds(BmpIndex * FImageWidth, 0, FImageWidth, FImageHeight)
  598.     else {if Orientation = goVertical then}
  599.       SrcRect := Bounds(0, BmpIndex * FImageHeight, FImageWidth, FImageHeight);
  600.     if Stretch then DstRect := ClientRect
  601.     else if Center then
  602.       DstRect := Bounds((ClientWidth - FImageWidth) div 2,
  603.         (ClientHeight - FImageHeight) div 2, FImageWidth, FImageHeight)
  604.     else
  605.       DstRect := Rect(0, 0, FImageWidth, FImageHeight);
  606.     with DstRect do
  607.       StretchBitmapRectTransparent(Canvas, Left, Top, Right - Left,
  608.         Bottom - Top, SrcRect, FGlyph, FTransparentColor);
  609.   end;
  610. end;
  611. procedure TAnimatedImage.Paint;
  612. begin
  613.   PaintImage;
  614.   if (not Opaque) or FGlyph.Empty then
  615.     PaintDesignRect;
  616. end;
  617. procedure TAnimatedImage.TimerExpired(Sender: TObject);
  618. begin
  619. {$IFDEF RX_D3}
  620.   if csPaintCopy in ControlState then Exit;
  621. {$ENDIF}
  622.   if Visible and (FNumGlyphs > 1) and (Parent <> nil) and
  623.     Parent.HandleAllocated then
  624.   begin
  625.     Lock;
  626.     try
  627.       if FGlyphNum < FNumGlyphs - 1 then Inc(FGlyphNum)
  628.       else FGlyphNum := 0;
  629.       if (FGlyphNum = FInactiveGlyph) and (FNumGlyphs > 1) then begin
  630.         if FGlyphNum < FNumGlyphs - 1 then Inc(FGlyphNum)
  631.         else FGlyphNum := 0;
  632.       end;
  633. {$IFDEF RX_D3}
  634.       Canvas.Lock;
  635.       try
  636.         FTimerRepaint := True;
  637.         if AsyncDrawing and Assigned(FOnFrameChanged) then
  638.           FTimer.Synchronize(FrameChanged)
  639.         else FrameChanged;
  640.         DoPaintControl;
  641.       finally
  642.         FTimerRepaint := False;
  643.         Canvas.Unlock;
  644.       end;
  645. {$ELSE}
  646.       FTimerRepaint := True;
  647.       try
  648.         FrameChanged;
  649.         Repaint;
  650.       finally
  651.         FTimerRepaint := False;
  652.       end;
  653. {$ENDIF}
  654.     finally
  655.       Unlock;
  656.     end;
  657.   end;
  658. end;
  659. procedure TAnimatedImage.FrameChanged;
  660. begin
  661.   if Assigned(FOnFrameChanged) then FOnFrameChanged(Self);
  662. end;
  663. procedure TAnimatedImage.Stop;
  664. begin
  665.   if not (csReading in ComponentState) then
  666.     if Assigned(FOnStop) then FOnStop(Self);
  667. end;
  668. procedure TAnimatedImage.Start;
  669. begin
  670.   if not (csReading in ComponentState) then
  671.     if Assigned(FOnStart) then FOnStart(Self);
  672. end;
  673. {$IFNDEF RX_D4}
  674. procedure TAnimatedImage.SetAutoSize(Value: Boolean);
  675. begin
  676.   if Value <> FAutoSize then begin
  677.     FAutoSize := Value;
  678.     PictureChanged;
  679.   end;
  680. end;
  681. {$ENDIF}
  682. {$IFDEF RX_D4}
  683. function TAnimatedImage.CanAutoSize(var NewWidth, NewHeight: Integer): Boolean;
  684. begin
  685.   Result := True;
  686.   if not (csDesigning in ComponentState) and (FImageWidth > 0) and
  687.     (FImageHeight > 0) then
  688.   begin
  689.     if Align in [alNone, alLeft, alRight] then
  690.       NewWidth := FImageWidth;
  691.     if Align in [alNone, alTop, alBottom] then
  692.       NewHeight := FImageHeight;
  693.   end;
  694. end;
  695. {$ENDIF}
  696. procedure TAnimatedImage.SetInterval(Value: Cardinal);
  697. begin
  698.   FTimer.Interval := Value;
  699. end;
  700. function TAnimatedImage.GetInterval: Cardinal;
  701. begin
  702.   Result := FTimer.Interval;
  703. end;
  704. procedure TAnimatedImage.SetActive(Value: Boolean);
  705. begin
  706.   if FActive <> Value then begin
  707.     if Value then begin
  708.       FTimer.OnTimer := TimerExpired;
  709.       FTimer.Enabled := True;
  710.       FActive := FTimer.Enabled;
  711.       Start;
  712.     end
  713.     else begin
  714.       FTimer.Enabled := False;
  715.       FTimer.OnTimer := nil;
  716.       FActive := False;
  717.       UpdateInactive;
  718.       FrameChanged;
  719.       Stop;
  720.       PictureChanged;
  721.     end;
  722.   end;
  723. end;
  724. {$IFDEF RX_D3}
  725. procedure TAnimatedImage.SetAsyncDrawing(Value: Boolean);
  726. begin
  727.   if FAsyncDrawing <> Value then begin
  728.     Lock;
  729.     try
  730.       if Value then HookBitmap;
  731.       if Assigned(FTimer) then FTimer.SyncEvent := not Value;
  732.       FAsyncDrawing := Value;
  733.     finally
  734.       Unlock;
  735.     end;
  736.   end;
  737. end;
  738. {$ENDIF}
  739. procedure TAnimatedImage.WMSize(var Message: TWMSize);
  740. begin
  741.   inherited;
  742. {$IFNDEF RX_D4}
  743.   AdjustSize;
  744. {$ENDIF}
  745. end;
  746. end.