home *** CD-ROM | disk | FTP | other *** search
/ BUG 15 / BUGCD1998_06.ISO / desktop / hotkey / hotkey95.exe / Source / Components / AniIcons.pas < prev    next >
Pascal/Delphi Source File  |  1997-04-11  |  11KB  |  444 lines

  1. unit AniIcons;
  2.  
  3. interface
  4.  
  5. uses Windows, Classes, Graphics, SysUtils, TmrPool;
  6.  
  7. type
  8.   EIconListError = class(Exception);
  9.   
  10.   TNewFrameEvent = procedure(Sender: TObject; Frame: Integer) of object;
  11.  
  12.   TIconSize = (is16x16, is32x32);
  13.  
  14.   TAnimatedIcons = class;
  15.  
  16.   TAnimatedIcon = class(TIcon)
  17.   private
  18.     FDisplayTime: Longint;
  19.   public
  20.     procedure Assign(Source: TPersistent); override;
  21.     procedure LoadFromStream(Stream: TStream); override;
  22.     procedure SaveToStream(Stream: TStream); override;
  23.     property DisplayTime: Longint read FDisplayTime write FDisplayTime;
  24.   end;
  25.  
  26.   TAnimatedIcons = class(TPersistent)
  27.   private
  28.     { property variables }
  29.     FAuthor       : String;
  30.     FIcons        : TList;
  31.     FIconIndex    : Integer;
  32.     FIconSize     : TIconSize;
  33.     FPlaying      : Boolean;
  34.     FTitle        : String;
  35.     { Event variables }
  36.     FOnNewFrame   : TNewFrameEvent;
  37.     FOnStopped    : TNotifyEvent;
  38.     { Private variables }
  39.     FBrush        : TBrush;
  40.     FDrawSize     : Integer;
  41.     FCurrentTiming: Integer;
  42.     FCurrentLoop  : Integer;
  43.     FTotalLoops   : Integer;
  44.     { Private routines (property get/set) }
  45.     procedure SetIconIndex(Value: Integer);
  46.     { Private routines (object streaming) }
  47.     procedure WriteString(Stream: TStream; Value: String);
  48.     function  ReadString(Stream: TStream): String;
  49.     procedure ReadData(Stream: TStream);
  50.     procedure WriteData(Stream: TStream);
  51.   protected
  52.     { Protected routines }
  53.     procedure cmTimerElapsed(var Msg: TCMTimerElapsed); message CM_TIMERELAPSED;
  54.     procedure SetDrawSize;
  55.     procedure DefineProperties(Filer: TFiler); override;
  56.     function  Get(Index: Integer): TAnimatedIcon;
  57.     function  GetCount: Integer;
  58.     procedure Put(Index: Integer; const Icon: TAnimatedIcon);
  59.   public
  60.     { constructor / destructor }
  61.     constructor Create(Size: TIconSize);
  62.     destructor Destroy; override;
  63.     { public methods }
  64.     function  Add(const Icon: TAnimatedIcon): Integer;
  65.     procedure AddIcons(Icons: TAnimatedIcons);
  66.     procedure Assign(Source: TPersistent); override;
  67.     procedure Clear;
  68.     procedure Delete(Index: Integer);
  69.     function  Equals(Icons: TAnimatedIcons): Boolean;
  70.     procedure Exchange(Index1, Index2: Integer);
  71.     procedure Insert(Index: Integer; const Icon: TAnimatedIcon);
  72.     procedure Move(CurIndex, NewIndex: Integer);
  73.     procedure LoadFromFile(const FileName: string);
  74.     procedure LoadFromStream(Stream: TStream);
  75.     procedure SaveToFile(const FileName: string);
  76.     procedure SaveToStream(Stream: TStream);
  77.     procedure Play(NrOfTimes: Integer);
  78.     procedure Stop;
  79.     procedure DrawIcon(Canvas: TCanvas; X, Y, Index: Integer; MaskColor: TColor);
  80.     { properties }
  81.     property  Count: Integer read GetCount;
  82.     property  IconIndex: Integer read FIconIndex write SetIconIndex;
  83.     property  IconSize: TIconSize read FIconSize;
  84.     property  Icons[Index: Integer]: TAnimatedIcon read Get write Put; default;
  85.   published
  86.     property  Author: String read FAuthor write FAuthor;
  87.     property  Playing: Boolean read FPlaying default False;
  88.     property  Title: String read FTitle write FTitle;
  89.     { animation event }
  90.     property  OnNewFrame: TNewFrameEvent read FOnNewFrame write FOnNewFrame;
  91.     property  OnStopped: TNotifyEvent read FOnStopped write FOnStopped;
  92.   end;
  93.  
  94. implementation
  95.  
  96. { TAnimatedIcon }
  97. procedure TAnimatedIcon.Assign(Source: TPersistent);
  98. begin
  99.   if Source is TAnimatedIcon then DisplayTime := TAnimatedIcon(Source).DisplayTime;
  100.   inherited Assign(Source);
  101. end;
  102.  
  103. procedure TAnimatedIcon.LoadFromStream(Stream: TStream);
  104. var
  105.   MStream: TMemoryStream;
  106.   lSize  : Longint;
  107.   P      : PChar;
  108. begin
  109.   Stream.Read(FDisplayTime, sizeof(Longint));
  110.   Stream.Read(lSize, sizeof(Longint));
  111.   if lSize>0 then
  112.    begin
  113.      MStream := TMemoryStream.Create;
  114.      try
  115.        P := StrAlloc(lSize+1);
  116.        try
  117.          Stream.Read(P^, lSize);
  118.          MStream.Write(P^, lSize);
  119.        finally
  120.          StrDispose(P);
  121.        end;
  122.        MStream.Position := 0;
  123.        inherited LoadFromStream(MStream);
  124.      finally
  125.        MStream.Free;
  126.      end;
  127.   end;
  128. end;
  129.  
  130. procedure TAnimatedIcon.SaveToStream(Stream: TStream);
  131. var
  132.   MStream: TMemoryStream;
  133.   lSize  : Longint;
  134.   P      : PChar;
  135. begin
  136.   Stream.Write(FDisplayTime, sizeof(Longint));
  137.   MStream := TMemoryStream.Create;
  138.   try
  139.     inherited SaveToStream(MStream);
  140.     lSize := MStream.Size;
  141.     Stream.Write(lSize, sizeof(LongInt));
  142.     MStream.Position := 0;
  143.     P := StrAlloc(lSize+1);
  144.     try
  145.       MStream.Read(P^, lSize);
  146.       Stream.Write(P^, lSize);
  147.     finally
  148.       StrDispose(P);
  149.     end;
  150.   finally
  151.     MStream.Free;
  152.   end;
  153. end;
  154.  
  155. { TAnimatedIcons }
  156. constructor TAnimatedIcons.Create(Size: TIconSize);
  157. begin
  158.   inherited Create;
  159.   FIconSize := Size;
  160.   SetDrawSize;
  161.   FIcons := TList.Create;
  162.   FBrush := TBrush.Create;
  163.   TimerPool.NotifyRegister(Self, False);
  164. end;
  165.  
  166. destructor TAnimatedIcons.Destroy;
  167. begin
  168.   TimerPool.NotifyUnregister(Self);
  169.   FIcons.Free;
  170.   FBrush.Free;
  171.   inherited Destroy;
  172. end;
  173.  
  174. procedure TAnimatedIcons.SetIconIndex(Value: Integer);
  175. begin
  176.   if FIconIndex<>Value then
  177.    begin
  178.      if (Value>=0) and (Value<Count) then
  179.       FIconIndex := Value
  180.      else
  181.       raise EIconListError.Create('Icon list index out of bounds');
  182.    end;
  183. end;
  184.  
  185. function TAnimatedIcons.Add(const Icon: TAnimatedIcon): Integer;
  186. begin
  187.   Result := GetCount;
  188.   Insert(Result, Icon);
  189. end;
  190.  
  191. procedure TAnimatedIcons.AddIcons(Icons: TAnimatedIcons);
  192. var
  193.   I: Integer;
  194. begin
  195.   for I := 0 to Icons.Count - 1 do Add(Icons[I]);
  196. end;
  197.  
  198. procedure TAnimatedIcons.Assign(Source: TPersistent);
  199. begin
  200.   if Source is TAnimatedIcons then
  201.    begin
  202.      FAuthor := TAnimatedIcons(Source).Author;
  203.      FTitle := TAnimatedIcons(Source).Title;
  204.      FIconSize := TAnimatedIcons(Source).IconSize;
  205.      SetDrawSize;
  206.      Clear;
  207.      AddIcons(TAnimatedIcons(Source));
  208.    end
  209.   else
  210.    inherited Assign(Source);
  211. end;
  212.  
  213. procedure TAnimatedIcons.DefineProperties(Filer: TFiler);
  214.  
  215.   function DoWrite: Boolean;
  216.   begin
  217.     if Filer.Ancestor <> nil then
  218.     begin
  219.       Result := True;
  220.       if Filer.Ancestor is TAnimatedIcons then
  221.         Result := not Equals(TAnimatedIcons(Filer.Ancestor))
  222.     end
  223.     else Result := Count > 0;
  224.   end;
  225.  
  226. begin
  227.   Filer.DefineBinaryProperty('Icons', ReadData, WriteData, DoWrite);
  228. end;
  229.  
  230. function TAnimatedIcons.Equals(Icons: TAnimatedIcons): Boolean;
  231. var
  232.   I, Count: Integer;
  233. begin
  234.   Result := False;
  235.   Count := GetCount;
  236.   if Count <> Icons.GetCount then Exit;
  237.   for I := 0 to Count - 1 do if Get(I) <> Icons.Get(I) then Exit;
  238.   Result := True;
  239. end;
  240.  
  241. procedure TAnimatedIcons.Exchange(Index1, Index2: Integer);
  242. begin
  243.   FIcons.Exchange(Index1, Index2);
  244. end;
  245.  
  246. procedure TAnimatedIcons.Move(CurIndex, NewIndex: Integer);
  247. begin
  248.   FIcons.Move(CurIndex, NewIndex);
  249. end;
  250.  
  251. function TAnimatedIcons.GetCount: Integer;
  252. begin
  253.   Result := FIcons.Count;
  254. end;
  255.  
  256. function TAnimatedIcons.Get(Index: Integer): TAnimatedIcon;
  257. begin
  258.   Result := TAnimatedIcon(FIcons[Index]);
  259. end;
  260.  
  261. procedure TAnimatedIcons.Put(Index: Integer; const Icon: TAnimatedIcon);
  262. begin
  263.   Delete(Index);
  264.   Insert(Index, Icon);
  265. end;
  266.  
  267. procedure TAnimatedIcons.Clear;
  268. begin
  269.   while Count>0 do Delete(0);
  270. end;
  271.  
  272. procedure TAnimatedIcons.Delete(Index: Integer);
  273. begin
  274.   TAnimatedIcon(FIcons[Index]).Free;
  275.   FIcons.Delete(Index);
  276.   FIcons.Pack;
  277. end;
  278.  
  279. procedure TAnimatedIcons.Insert(Index: Integer; const Icon: TAnimatedIcon);
  280. var
  281.   NewIcon: TAnimatedIcon;
  282. begin
  283.   NewIcon := TAnimatedIcon.Create;
  284.   NewIcon.Assign(Icon);
  285.   FIcons.Insert(Index, NewIcon);
  286. end;
  287.  
  288. procedure TAnimatedIcons.LoadFromFile(const FileName: string);
  289. var
  290.   Stream: TStream;
  291. begin
  292.   Stream := TFileStream.Create(FileName, fmOpenRead);
  293.   try
  294.     LoadFromStream(Stream);
  295.   finally
  296.     Stream.Free;
  297.   end;
  298. end;
  299.  
  300. function TAnimatedIcons.ReadString(Stream: TStream): String;
  301. var
  302.   i, iCount : Integer;
  303.   cLetter   : Char;
  304. begin
  305.   Result := '';
  306.   with Stream do
  307.    begin
  308.      Read(iCount, sizeof(Longint));
  309.      for i:=1 to iCount do
  310.       begin
  311.         Read(cLetter, sizeof(Char));
  312.         Result := Result + cLetter;
  313.       end;
  314.    end;
  315. end;
  316.  
  317. procedure TAnimatedIcons.WriteString(Stream: TStream; Value: String);
  318. var
  319.   i, iCount : Integer;
  320. begin
  321.   iCount := Length(Value);
  322.   with Stream do
  323.    begin
  324.      Write(iCount, sizeof(Longint));
  325.      for i:=1 to iCount do
  326.       Write(Value[i], sizeof(Char));
  327.    end;
  328. end;
  329.  
  330. procedure TAnimatedIcons.LoadFromStream(Stream: TStream);
  331. var
  332.   Icon     : TAnimatedIcon;
  333.   i, iCount: Longint;
  334. begin
  335.   FTitle := ReadString(Stream);
  336.   FAuthor := ReadString(Stream);
  337.   Stream.Read(FIconSize, sizeof(TIconSize));
  338.   SetDrawSize;
  339.   Stream.Read(iCount, sizeof(LongInt));
  340.   Clear;
  341.   for i:=0 to iCount-1 do
  342.    begin
  343.      Icon := TAnimatedIcon.Create;
  344.      Icon.LoadFromStream(Stream);
  345.      Add(Icon);
  346.    end;
  347. end;
  348.  
  349. procedure TAnimatedIcons.ReadData(Stream: TStream);
  350. begin
  351.   LoadFromStream(Stream);
  352. end;
  353.  
  354. procedure TAnimatedIcons.SaveToFile(const FileName: string);
  355. var
  356.   Stream: TStream;
  357. begin
  358.   Stream := TFileStream.Create(FileName, fmCreate);
  359.   try
  360.     SaveToStream(Stream);
  361.   finally
  362.     Stream.Free;
  363.   end;
  364. end;
  365.  
  366. procedure TAnimatedIcons.SaveToStream(Stream: TStream);
  367. var
  368.   i, iCount: Integer;
  369. begin
  370.   iCount := Count;
  371.   WriteString(Stream, FTitle);
  372.   WriteString(Stream, FAuthor);
  373.   Stream.Write(FIconSize, sizeof(TIconSize));
  374.   Stream.Write(iCount, sizeof(LongInt));
  375.   for I := 0 to iCount - 1 do
  376.    Icons[I].SaveToStream(Stream);
  377. end;
  378.  
  379. procedure TAnimatedIcons.WriteData(Stream: TStream);
  380. begin
  381.   SaveToStream(Stream);
  382. end;
  383.  
  384. procedure TAnimatedIcons.cmTimerElapsed(var Msg: TCMTimerElapsed);
  385. begin
  386.   if (FIconIndex>=FIcons.Count) then
  387.    begin
  388.      FIconIndex := 0;
  389.      if (FIcons.Count = 0) then Exit;
  390.    end;
  391.   inc(FCurrentTiming, Msg.MilliSeconds);
  392.   if FCurrentTiming>=Icons[FIconIndex].DisplayTime*10 then
  393.    begin
  394.      if Assigned(FOnNewFrame) then FOnNewFrame(Self, FIconIndex);
  395.      inc(FIconIndex);
  396.      if FIconIndex>=Count then
  397.       begin
  398.         FIconIndex := 0;
  399.         if FTotalLoops>0 then
  400.          begin
  401.            inc(FCurrentLoop);
  402.            if FCurrentLoop = FTotalLoops then Stop;
  403.          end;
  404.       end;
  405.      FCurrentTiming := 0;
  406.    end;
  407. end;
  408.  
  409. procedure TAnimatedIcons.Play(NrOfTimes: Integer);
  410. begin
  411.   if not Assigned(FOnNewFrame) or (Count=0) then Exit;
  412.   FIconIndex := 0;
  413.   FCurrentTiming := 0;
  414.   FPlaying := True;
  415.   FTotalLoops := NrOfTimes;
  416.   FCurrentLoop := 0;
  417.   TimerPool.NotifyRegister(Self, True);
  418. end;
  419.  
  420. procedure TAnimatedIcons.Stop;
  421. begin
  422.   TimerPool.NotifyRegister(Self, False);
  423.   FPlaying := False;
  424.   if Assigned(FOnStopped) then FOnStopped(Self);
  425. end;
  426.  
  427. procedure TAnimatedIcons.SetDrawSize;
  428. begin
  429.   if FIconSize=is16x16 then FDrawSize := 16 else FDrawSize := 32;
  430. end;
  431.  
  432. procedure TAnimatedIcons.DrawIcon(Canvas: TCanvas; X, Y, Index: Integer; MaskColor: TColor);
  433. begin
  434.   if not Assigned(Canvas) then Exit;
  435.   if (Index>=0) and (Index<FIcons.Count) then
  436.    begin
  437.      FBrush.Color := MaskColor;
  438.      DrawIconEx(Canvas.Handle, X, Y, TIcon(FIcons[Index]).Handle, FDrawSize, FDrawSize, 0,
  439.                 FBrush.Handle, DI_NORMAL);
  440.    end;
  441. end;
  442.  
  443. end.
  444.