home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
PC World 1999 February
/
PCWorld_1999-02_cd.bin
/
temacd
/
HotKeys
/
AniIcons.pas
< prev
next >
Wrap
Pascal/Delphi Source File
|
1998-06-28
|
12KB
|
447 lines
unit AniIcons;
interface
uses Windows, Classes, Graphics, SysUtils, TmrPool;
type
EIconListError = class(Exception);
TNewFrameEvent = procedure(Sender: TObject; Frame: Integer) of object;
TIconSize = (is16x16, is32x32);
TAnimatedIcons = class;
TAnimatedIcon = class(TIcon)
private
FDisplayTime: Longint;
public
procedure Assign(Source: TPersistent); override;
procedure LoadFromStream(Stream: TStream); override;
procedure SaveToStream(Stream: TStream); override;
property DisplayTime: Longint read FDisplayTime write FDisplayTime;
end;
TAnimatedIcons = class(TPersistent)
private
{ property variables }
FAuthor : String;
FIcons : TList;
FIconIndex : Integer;
FIconSize : TIconSize;
FPlaying : Boolean;
FTitle : String;
{ Event variables }
FOnNewFrame : TNewFrameEvent;
FOnStopped : TNotifyEvent;
{ Private variables }
FBrush : TBrush;
FDrawSize : Integer;
FCurrentTiming: Integer;
FCurrentLoop : Integer;
FTotalLoops : Integer;
{ Private routines (property get/set) }
procedure SetIconIndex(Value: Integer);
{ Private routines (object streaming) }
procedure WriteString(Stream: TStream; Value: String);
function ReadString(Stream: TStream): String;
procedure ReadData(Stream: TStream);
procedure WriteData(Stream: TStream);
protected
{ Protected routines }
procedure cmTimerElapsed(var Msg: TCMTimerElapsed); message CM_TIMERELAPSED;
procedure SetDrawSize;
procedure DefineProperties(Filer: TFiler); override;
function Get(Index: Integer): TAnimatedIcon;
function GetCount: Integer;
procedure Put(Index: Integer; const Icon: TAnimatedIcon);
public
{ constructor / destructor }
constructor Create(Size: TIconSize);
destructor Destroy; override;
{ public methods }
function Add(const Icon: TAnimatedIcon): Integer;
function AddIcon: TAnimatedIcon;
procedure AddIcons(Icons: TAnimatedIcons);
procedure Assign(Source: TPersistent); override;
procedure Clear;
procedure Delete(Index: Integer);
function Equals(Icons: TAnimatedIcons): Boolean;
procedure Exchange(Index1, Index2: Integer);
procedure Insert(Index: Integer; const Icon: TAnimatedIcon);
procedure Move(CurIndex, NewIndex: Integer);
procedure LoadFromFile(const FileName: string);
procedure LoadFromStream(Stream: TStream);
procedure SaveToFile(const FileName: string);
procedure SaveToStream(Stream: TStream);
procedure Play(NrOfTimes: Integer);
procedure Stop;
procedure DrawIcon(Canvas: TCanvas; X, Y, Index: Integer; MaskColor: TColor);
{ properties }
property Count: Integer read GetCount;
property IconIndex: Integer read FIconIndex write SetIconIndex;
property IconSize: TIconSize read FIconSize;
property Icons[Index: Integer]: TAnimatedIcon read Get write Put; default;
published
property Author: String read FAuthor write FAuthor;
property Playing: Boolean read FPlaying default False;
property Title: String read FTitle write FTitle;
{ animation event }
property OnNewFrame: TNewFrameEvent read FOnNewFrame write FOnNewFrame;
property OnStopped: TNotifyEvent read FOnStopped write FOnStopped;
end;
implementation
{ TAnimatedIcon }
procedure TAnimatedIcon.Assign(Source: TPersistent);
begin
if Source is TAnimatedIcon then DisplayTime := TAnimatedIcon(Source).DisplayTime;
inherited Assign(Source);
end;
procedure TAnimatedIcon.LoadFromStream(Stream: TStream);
var
MStream: TMemoryStream;
lSize : Longint;
P : PChar;
begin
Stream.Read(FDisplayTime, sizeof(Longint));
Stream.Read(lSize, sizeof(Longint));
if lSize>0 then
begin
MStream := TMemoryStream.Create;
try
P := StrAlloc(lSize+1);
try
Stream.Read(P^, lSize);
MStream.Write(P^, lSize);
finally
StrDispose(P);
end;
MStream.Position := 0;
inherited LoadFromStream(MStream);
finally
MStream.Free;
end;
end;
end;
procedure TAnimatedIcon.SaveToStream(Stream: TStream);
var
MStream: TMemoryStream;
lSize : Longint;
P : PChar;
begin
Stream.Write(FDisplayTime, sizeof(Longint));
MStream := TMemoryStream.Create;
try
inherited SaveToStream(MStream);
lSize := MStream.Size;
Stream.Write(lSize, sizeof(LongInt));
MStream.Position := 0;
P := StrAlloc(lSize+1);
try
MStream.Read(P^, lSize);
Stream.Write(P^, lSize);
finally
StrDispose(P);
end;
finally
MStream.Free;
end;
end;
{ TAnimatedIcons }
constructor TAnimatedIcons.Create(Size: TIconSize);
begin
inherited Create;
FIconSize := Size;
SetDrawSize;
FIcons := TList.Create;
FBrush := TBrush.Create;
TimerPool.NotifyRegister(Self, False);
end;
destructor TAnimatedIcons.Destroy;
begin
TimerPool.NotifyUnregister(Self);
Clear;
FIcons.Free;
FBrush.Free;
inherited Destroy;
end;
procedure TAnimatedIcons.SetIconIndex(Value: Integer);
begin
if FIconIndex<>Value then
begin
if (Value>=0) and (Value<Count) then
FIconIndex := Value
else
raise EIconListError.Create('Icon list index out of bounds');
end;
end;
function TAnimatedIcons.Add(const Icon: TAnimatedIcon): Integer;
begin
Result := GetCount;
Insert(Result, Icon);
end;
function TAnimatedIcons.AddIcon: TAnimatedIcon;
begin
Result := TAnimatedIcon.Create;
FIcons.Add(Result);
end;
procedure TAnimatedIcons.AddIcons(Icons: TAnimatedIcons);
var
I: Integer;
begin
for I := 0 to Icons.Count - 1 do Add(Icons[I]);
end;
procedure TAnimatedIcons.Assign(Source: TPersistent);
begin
if Source is TAnimatedIcons then
begin
FAuthor := TAnimatedIcons(Source).Author;
FTitle := TAnimatedIcons(Source).Title;
FIconSize := TAnimatedIcons(Source).IconSize;
SetDrawSize;
Clear;
AddIcons(TAnimatedIcons(Source));
end
else
inherited Assign(Source);
end;
procedure TAnimatedIcons.DefineProperties(Filer: TFiler);
function DoWrite: Boolean;
begin
if Filer.Ancestor <> nil then
begin
Result := True;
if Filer.Ancestor is TAnimatedIcons then
Result := not Equals(TAnimatedIcons(Filer.Ancestor))
end
else Result := Count > 0;
end;
begin
Filer.DefineBinaryProperty('Icons', ReadData, WriteData, DoWrite);
end;
function TAnimatedIcons.Equals(Icons: TAnimatedIcons): Boolean;
var
I, Count: Integer;
begin
Result := False;
Count := GetCount;
if Count <> Icons.GetCount then Exit;
for I := 0 to Count - 1 do if Get(I) <> Icons.Get(I) then Exit;
Result := True;
end;
procedure TAnimatedIcons.Exchange(Index1, Index2: Integer);
begin
FIcons.Exchange(Index1, Index2);
end;
procedure TAnimatedIcons.Move(CurIndex, NewIndex: Integer);
begin
FIcons.Move(CurIndex, NewIndex);
end;
function TAnimatedIcons.GetCount: Integer;
begin
Result := FIcons.Count;
end;
function TAnimatedIcons.Get(Index: Integer): TAnimatedIcon;
begin
Result := TAnimatedIcon(FIcons[Index]);
end;
procedure TAnimatedIcons.Put(Index: Integer; const Icon: TAnimatedIcon);
begin
Delete(Index);
Insert(Index, Icon);
end;
procedure TAnimatedIcons.Clear;
begin
while Count>0 do Delete(0);
end;
procedure TAnimatedIcons.Delete(Index: Integer);
begin
TAnimatedIcon(FIcons[Index]).Free;
FIcons.Delete(Index);
FIcons.Pack;
end;
procedure TAnimatedIcons.Insert(Index: Integer; const Icon: TAnimatedIcon);
var
NewIcon: TAnimatedIcon;
begin
NewIcon := TAnimatedIcon.Create;
NewIcon.Assign(Icon);
FIcons.Insert(Index, NewIcon);
end;
procedure TAnimatedIcons.LoadFromFile(const FileName: string);
var
Stream: TStream;
begin
Stream := TFileStream.Create(FileName, fmOpenRead);
try
LoadFromStream(Stream);
finally
Stream.Free;
end;
end;
function TAnimatedIcons.ReadString(Stream: TStream): String;
var
i, iCount : Integer;
cLetter : Char;
begin
Result := '';
with Stream do
begin
Read(iCount, sizeof(Longint));
for i:=1 to iCount do
begin
Read(cLetter, sizeof(Char));
Result := Result + cLetter;
end;
end;
end;
procedure TAnimatedIcons.WriteString(Stream: TStream; Value: String);
var
i, iCount : Integer;
begin
iCount := Length(Value);
with Stream do
begin
Write(iCount, sizeof(Longint));
for i:=1 to iCount do
Write(Value[i], sizeof(Char));
end;
end;
procedure TAnimatedIcons.LoadFromStream(Stream: TStream);
var
i, iCount: Longint;
begin
FTitle := ReadString(Stream);
FAuthor := ReadString(Stream);
Stream.Read(FIconSize, sizeof(TIconSize));
SetDrawSize;
Stream.Read(iCount, sizeof(LongInt));
Clear;
for i:=0 to iCount-1 do
AddIcon.LoadFromStream(Stream);
end;
procedure TAnimatedIcons.ReadData(Stream: TStream);
begin
LoadFromStream(Stream);
end;
procedure TAnimatedIcons.SaveToFile(const FileName: string);
var
Stream: TStream;
begin
Stream := TFileStream.Create(FileName, fmCreate);
try
SaveToStream(Stream);
finally
Stream.Free;
end;
end;
procedure TAnimatedIcons.SaveToStream(Stream: TStream);
var
i, iCount: Integer;
begin
iCount := Count;
WriteString(Stream, FTitle);
WriteString(Stream, FAuthor);
Stream.Write(FIconSize, sizeof(TIconSize));
Stream.Write(iCount, sizeof(LongInt));
for I := 0 to iCount - 1 do
Icons[I].SaveToStream(Stream);
end;
procedure TAnimatedIcons.WriteData(Stream: TStream);
begin
SaveToStream(Stream);
end;
procedure TAnimatedIcons.cmTimerElapsed(var Msg: TCMTimerElapsed);
begin
if (FIconIndex>=FIcons.Count) then
begin
FIconIndex := 0;
if (FIcons.Count = 0) then Exit;
end;
inc(FCurrentTiming, Msg.MilliSeconds);
if FCurrentTiming>=Icons[FIconIndex].DisplayTime*10 then
begin
if Assigned(FOnNewFrame) then FOnNewFrame(Self, FIconIndex);
inc(FIconIndex);
if FIconIndex>=Count then
begin
FIconIndex := 0;
if FTotalLoops>0 then
begin
inc(FCurrentLoop);
if FCurrentLoop = FTotalLoops then Stop;
end;
end;
FCurrentTiming := 0;
end;
end;
procedure TAnimatedIcons.Play(NrOfTimes: Integer);
begin
if not Assigned(FOnNewFrame) or (Count=0) then Exit;
FIconIndex := 0;
FCurrentTiming := 0;
FPlaying := True;
FTotalLoops := NrOfTimes;
FCurrentLoop := 0;
TimerPool.NotifyRegister(Self, True);
end;
procedure TAnimatedIcons.Stop;
begin
TimerPool.NotifyRegister(Self, False);
FPlaying := False;
if Assigned(FOnStopped) then FOnStopped(Self);
end;
procedure TAnimatedIcons.SetDrawSize;
begin
if FIconSize=is16x16 then FDrawSize := 16 else FDrawSize := 32;
end;
procedure TAnimatedIcons.DrawIcon(Canvas: TCanvas; X, Y, Index: Integer; MaskColor: TColor);
begin
if not Assigned(Canvas) then Exit;
if (Index>=0) and (Index<FIcons.Count) then
begin
FBrush.Color := MaskColor;
DrawIconEx(Canvas.Handle, X, Y, TIcon(FIcons[Index]).Handle, FDrawSize, FDrawSize, 0,
FBrush.Handle, DI_NORMAL);
end;
end;
end.