📄 animate.pas
字号:
{*******************************************************}
{ }
{ Delphi VCL Extensions (RX) }
{ }
{ Copyright (c) 2001,2002 SGB Software }
{ Copyright (c) 1997, 1998 Fedor Koshevnikov, }
{ Igor Pavluk and Serge Korolev }
{ }
{*******************************************************}
unit Animate;
interface
{$I RX.INC}
uses Messages, {$IFDEF WIN32} Windows, {$ELSE} WinTypes, WinProcs, {$ENDIF}
SysUtils, Classes, Graphics, Controls, Forms, StdCtrls, Menus, RxTimer;
type
{ TRxImageControl }
TRxImageControl = class(TGraphicControl)
private
FDrawing: Boolean;
FPaintBuffered: Boolean;
{$IFDEF RX_D3}
FLock: TRTLCriticalSection;
{$ENDIF}
procedure WMPaint(var Message: TWMPaint); message WM_PAINT;
protected
FGraphic: TGraphic;
function DoPaletteChange: Boolean;
{$IFNDEF RX_D4}
procedure AdjustSize; virtual; abstract;
{$ENDIF}
procedure DoPaintImage; virtual; abstract;
procedure DoPaintControl;
procedure PaintDesignRect;
procedure PaintImage;
procedure PictureChanged;
procedure Lock;
procedure Unlock;
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
end;
{ TAnimatedImage }
TGlyphOrientation = (goHorizontal, goVertical);
TAnimatedImage = class(TRxImageControl)
private
FActive: Boolean;
FGlyph: TBitmap;
FImageWidth: Integer;
FImageHeight: Integer;
FInactiveGlyph: Integer;
FOrientation: TGlyphOrientation;
FTimer: TRxTimer;
FNumGlyphs: Integer;
FGlyphNum: Integer;
FCenter: Boolean;
FStretch: Boolean;
FTransparentColor: TColor;
FOpaque: Boolean;
FTimerRepaint: Boolean;
FOnFrameChanged: TNotifyEvent;
FOnStart: TNotifyEvent;
FOnStop: TNotifyEvent;
{$IFDEF RX_D3}
FAsyncDrawing: Boolean;
{$ENDIF}
{$IFNDEF RX_D4}
FAutoSize: Boolean;
procedure SetAutoSize(Value: Boolean);
{$ENDIF}
procedure DefineBitmapSize;
procedure ResetImageBounds;
function GetInterval: Cardinal;
procedure SetInterval(Value: Cardinal);
procedure SetActive(Value: Boolean);
{$IFDEF RX_D3}
procedure SetAsyncDrawing(Value: Boolean);
{$ENDIF}
procedure SetCenter(Value: Boolean);
procedure SetOrientation(Value: TGlyphOrientation);
procedure SetGlyph(Value: TBitmap);
procedure SetGlyphNum(Value: Integer);
procedure SetInactiveGlyph(Value: Integer);
procedure SetNumGlyphs(Value: Integer);
procedure SetStretch(Value: Boolean);
procedure SetTransparentColor(Value: TColor);
procedure SetOpaque(Value: Boolean);
procedure ImageChanged(Sender: TObject);
procedure UpdateInactive;
procedure TimerExpired(Sender: TObject);
function TransparentStored: Boolean;
procedure WMSize(var Message: TWMSize); message WM_SIZE;
protected
{$IFDEF RX_D4}
function CanAutoSize(var NewWidth, NewHeight: Integer): Boolean; override;
{$ENDIF}
function GetPalette: HPALETTE; override;
procedure AdjustSize; override;
procedure Loaded; override;
procedure Paint; override;
procedure DoPaintImage; override;
procedure FrameChanged; dynamic;
procedure Start; dynamic;
procedure Stop; dynamic;
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
published
property Align;
{$IFDEF RX_D4}
property Anchors;
property Constraints;
property DragKind;
property AutoSize default True;
{$ELSE}
property AutoSize: Boolean read FAutoSize write SetAutoSize default True;
{$ENDIF}
{$IFDEF RX_D3}
property AsyncDrawing: Boolean read FAsyncDrawing write SetAsyncDrawing default False;
{$ENDIF}
property Active: Boolean read FActive write SetActive default False;
property Center: Boolean read FCenter write SetCenter default False;
property Orientation: TGlyphOrientation read FOrientation write SetOrientation
default goHorizontal;
property Glyph: TBitmap read FGlyph write SetGlyph;
property GlyphNum: Integer read FGlyphNum write SetGlyphNum default 0;
property Interval: Cardinal read GetInterval write SetInterval default 100;
property NumGlyphs: Integer read FNumGlyphs write SetNumGlyphs default 1;
property InactiveGlyph: Integer read FInactiveGlyph write SetInactiveGlyph default -1;
property TransparentColor: TColor read FTransparentColor write SetTransparentColor
stored TransparentStored;
property Opaque: Boolean read FOpaque write SetOpaque default False;
property Color;
property Cursor;
property DragCursor;
property DragMode;
property ParentColor default True;
property ParentShowHint;
property PopupMenu;
property ShowHint;
property Stretch: Boolean read FStretch write SetStretch default True;
property Visible;
property OnClick;
property OnDblClick;
property OnMouseMove;
property OnMouseDown;
property OnMouseUp;
property OnDragOver;
property OnDragDrop;
property OnEndDrag;
{$IFDEF WIN32}
property OnStartDrag;
{$ENDIF}
{$IFDEF RX_D4}
property OnEndDock;
property OnStartDock;
{$ENDIF}
{$IFDEF RX_D5}
property OnContextPopup;
{$ENDIF}
property OnFrameChanged: TNotifyEvent read FOnFrameChanged write FOnFrameChanged;
property OnStart: TNotifyEvent read FOnStart write FOnStart;
property OnStop: TNotifyEvent read FOnStop write FOnStop;
end;
{$IFDEF RX_D3}
procedure HookBitmap;
{$ENDIF}
implementation
uses RxConst, {$IFDEF RX_D3} RxHook, {$ENDIF} VCLUtils;
{$IFDEF RX_D3}
{ THackBitmap }
type
THackBitmap = class(TBitmap)
protected
procedure Draw(ACanvas: TCanvas; const Rect: TRect); override;
end;
procedure THackBitmap.Draw(ACanvas: TCanvas; const Rect: TRect);
begin
if not Empty then Canvas.Lock;
try
inherited Draw(ACanvas, Rect);
finally
if not Empty then Canvas.Unlock;
end;
end;
type
THack = class(TBitmap);
var
Hooked: Boolean = False;
procedure HookBitmap;
var
Index: Integer;
begin
if Hooked then Exit;
Index := FindVirtualMethodIndex(THack, @THack.Draw);
SetVirtualMethodAddress(TBitmap, Index, @THackBitmap.Draw);
Hooked := True;
end;
{$ENDIF RX_D3}
{ TRxImageControl }
constructor TRxImageControl.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
{$IFDEF RX_D3}
InitializeCriticalSection(FLock);
{$ENDIF}
ControlStyle := ControlStyle + [csClickEvents, csCaptureMouse, csOpaque,
{$IFDEF WIN32} csReplicatable, {$ENDIF} csDoubleClicks];
Height := 105;
Width := 105;
ParentColor := True;
end;
destructor TRxImageControl.Destroy;
begin
{$IFDEF RX_D3}
DeleteCriticalSection(FLock);
{$ENDIF}
inherited Destroy;
end;
procedure TRxImageControl.Lock;
begin
{$IFDEF RX_D3}
EnterCriticalSection(FLock);
{$ENDIF}
end;
procedure TRxImageControl.Unlock;
begin
{$IFDEF RX_D3}
LeaveCriticalSection(FLock);
{$ENDIF}
end;
procedure TRxImageControl.PaintImage;
var
Save: Boolean;
begin
with Canvas do begin
Brush.Color := Color;
FillRect(Bounds(0, 0, ClientWidth, ClientHeight));
end;
Save := FDrawing;
FDrawing := True;
try
DoPaintImage;
finally
FDrawing := Save;
end;
end;
procedure TRxImageControl.WMPaint(var Message: TWMPaint);
var
DC, MemDC: HDC;
MemBitmap, OldBitmap: HBITMAP;
begin
if FPaintBuffered then
inherited
else if Message.DC <> 0 then begin
{$IFDEF RX_D3}
Canvas.Lock;
try
{$ENDIF}
DC := Message.DC;
MemDC := GetDC(0);
MemBitmap := CreateCompatibleBitmap(MemDC, ClientWidth, ClientHeight);
ReleaseDC(0, MemDC);
MemDC := CreateCompatibleDC(0);
OldBitmap := SelectObject(MemDC, MemBitmap);
try
FPaintBuffered := True;
try
Message.DC := MemDC;
WMPaint(Message);
Message.DC := 0;
finally
FPaintBuffered := False;
end;
BitBlt(DC, 0, 0, ClientWidth, ClientHeight, MemDC, 0, 0, SRCCOPY);
finally
SelectObject(MemDC, OldBitmap);
DeleteDC(MemDC);
DeleteObject(MemBitmap);
end;
{$IFDEF RX_D3}
finally
Canvas.Unlock;
end;
{$ENDIF}
end;
end;
procedure TRxImageControl.PaintDesignRect;
begin
if csDesigning in ComponentState then
with Canvas do begin
Pen.Style := psDash;
Brush.Style := bsClear;
Rectangle(0, 0, Width, Height);
end;
end;
procedure TRxImageControl.DoPaintControl;
var
DC: HDC;
begin
{$IFDEF RX_D3}
if GetCurrentThreadID = MainThreadID then begin
Repaint;
Exit;
end;
{$ENDIF}
DC := GetDC(Parent.Handle);
try
IntersectClipRect(DC, Left, Top, Left + Width, Top + Height);
MoveWindowOrg(DC, Left, Top);
Perform(WM_PAINT, DC, 0);
finally
ReleaseDC(Parent.Handle, DC);
end;
end;
function TRxImageControl.DoPaletteChange: Boolean;
var
ParentForm: TCustomForm;
Tmp: TGraphic;
begin
Result := False;
Tmp := FGraphic;
if Visible and (not (csLoading in ComponentState)) and (Tmp <> nil)
{$IFDEF RX_D3} and (Tmp.PaletteModified) {$ENDIF} then
begin
if (GetPalette <> 0) then begin
ParentForm := GetParentForm(Self);
if Assigned(ParentForm) and ParentForm.Active and ParentForm.HandleAllocated then
begin
if FDrawing then
ParentForm.Perform(WM_QUERYNEWPALETTE, 0, 0)
else
PostMessage(ParentForm.Handle, WM_QUERYNEWPALETTE, 0, 0);
Result := True;
{$IFDEF RX_D3}
Tmp.PaletteModified := False;
{$ENDIF}
end;
end
{$IFDEF RX_D3}
else begin
Tmp.PaletteModified := False;
end;
{$ENDIF}
end;
end;
procedure TRxImageControl.PictureChanged;
begin
if not (csDestroying in ComponentState) then begin
AdjustSize;
if (FGraphic <> nil) then
if DoPaletteChange and FDrawing then Update;
if not FDrawing then Invalidate;
end;
end;
{ TAnimatedImage }
constructor TAnimatedImage.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
FTimer := TRxTimer.Create(Self);
with FTimer do begin
Enabled := False;
Interval := 100;
end;
AutoSize := True;
FGlyph := TBitmap.Create;
FGraphic := FGlyph;
FGlyph.OnChange := ImageChanged;
FNumGlyphs := 1;
FInactiveGlyph := -1;
FTransparentColor := clNone;
FOrientation := goHorizontal;
FStretch := True;
end;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -