home *** CD-ROM | disk | FTP | other *** search
/ Chip 2001 September / Chip_2001-09_cd1.bin / zkuste / delphi / kolekce / d6 / RX275D6.ZIP / Units / Animate.pas < prev    next >
Encoding:
Pascal/Delphi Source File  |  1999-10-12  |  19.5 KB  |  812 lines

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