home *** CD-ROM | disk | FTP | other *** search
/ Chip 2003 January / Chip_2003-01_cd1.bin / zkuste / delphi / kompon / d23456 / COOLTRAY.ZIP / SimpleTimer.pas < prev    next >
Pascal/Delphi Source File  |  2002-10-29  |  8KB  |  312 lines

  1. {*****************************************************************}
  2. { SimpleTimer is a timer class. It has the same timer resolution  }
  3. { as TTimer, but it is more lightweight because it's derived from }
  4. { TObject in stead of TComponent. Furthermore, the same handle is }
  5. { shared between multiple instances of SimpleTimer.               }
  6. { This makes it ideal for developers who need a timer in their    }
  7. { own components or applications, but want to keep the resource   }
  8. { usage minimal.                                                  }
  9. {                                                                 }
  10. { The unit is freeware. Feel free to use and improve it.          }
  11. { I would be pleased to hear what you think.                      }
  12. {                                                                 }
  13. { Troels Jakobsen - delphiuser@get2net.dk                         }
  14. { Copyright (c) 2002                                              }
  15. {*****************************************************************}
  16.  
  17. unit SimpleTimer;
  18.  
  19. { Some methods have moved to the Classes unit in D6 and are thus deprecated.
  20.   Using the following compiler directives we handle that situation. }
  21. {$IFDEF VER140} {$DEFINE DELPHI_6} {$ENDIF}
  22. {$IFDEF VER150} {$DEFINE DELPHI_7} {$ENDIF}
  23. {$IFDEF DELPHI_6} {$DEFINE DELPHI_6_UP} {$ENDIF}
  24. {$IFDEF DELPHI_7} {$DEFINE DELPHI_6_UP} {$ENDIF}
  25.  
  26. interface
  27.  
  28. uses
  29.   Windows, Classes;
  30.  
  31. type
  32.   TSimpleTimerCallBackMethod = procedure(AOwner: TObject); stdcall;
  33.  
  34.   TSimpleTimer = class(TObject)
  35.   private
  36.     FId: UINT;
  37.     FEnabled: Boolean;
  38.     FInterval: Cardinal;
  39.     FAutoDisable: Boolean;
  40.     FOnTimer: TNotifyEvent;
  41.     procedure SetEnabled(Value: Boolean);
  42.     procedure SetInterval(Value: Cardinal);
  43.     procedure SetOnTimer(Value: TNotifyEvent);
  44.     procedure Initialize(AInterval: Cardinal; AOnTimer: TNotifyEvent);
  45.   protected
  46.     function Start: Boolean;
  47.     function Stop(Disable: Boolean): Boolean;
  48.   public
  49.     constructor Create; overload;
  50.     constructor Create(AInterval: Cardinal; AOnTimer: TNotifyEvent); overload;
  51.     destructor Destroy; override;
  52.     property Enabled: Boolean read FEnabled write SetEnabled;
  53.     property Interval: Cardinal read FInterval write SetInterval default 1000;
  54.     property AutoDisable: Boolean read FAutoDisable write FAutoDisable;
  55.     property OnTimer: TNotifyEvent read FOnTimer write SetOnTimer;
  56.   end;
  57.  
  58. function GetSimpleTimerCount: Cardinal;
  59. function GetSimpleTimerActiveCount: Cardinal;
  60.  
  61.  
  62. implementation
  63.  
  64. uses
  65.   Messages{$IFNDEF DELPHI_6_UP}, Forms {$ENDIF};
  66.  
  67. type
  68.   TSimpleTimerHandler = class(TObject)
  69.   private
  70.     RefCount: Cardinal;
  71.     ActiveCount: Cardinal;
  72.     FWindowHandle: HWND;
  73.     procedure WndProc(var Msg: TMessage);
  74.   public
  75.     constructor Create;
  76.     destructor Destroy; override;
  77.     procedure AddTimer;
  78.     procedure RemoveTimer;
  79.   end;
  80.  
  81. var
  82.   SimpleTimerHandler: TSimpleTimerHandler = nil;
  83.  
  84.  
  85. function GetSimpleTimerCount: Cardinal;
  86. begin
  87.   if Assigned(SimpleTimerHandler) then
  88.     Result := SimpleTimerHandler.RefCount
  89.   else
  90.     Result := 0;
  91. end;
  92.  
  93.  
  94. function GetSimpleTimerActiveCount: Cardinal;
  95. begin
  96.   if Assigned(SimpleTimerHandler) then
  97.     Result := SimpleTimerHandler.ActiveCount
  98.   else
  99.     Result := 0;
  100. end;
  101.  
  102. {--------------- TSimpleTimerHandler ------------------}
  103.  
  104. constructor TSimpleTimerHandler.Create;
  105. begin
  106.   inherited Create;
  107. {$IFDEF DELPHI_6_UP}
  108.   FWindowHandle := Classes.AllocateHWnd(WndProc);
  109. {$ELSE}
  110.   FWindowHandle := AllocateHWnd(WndProc);
  111. {$ENDIF}
  112. end;
  113.  
  114.  
  115. destructor TSimpleTimerHandler.Destroy;
  116. begin
  117. {$IFDEF DELPHI_6_UP}
  118.   Classes.DeallocateHWnd(FWindowHandle);
  119. {$ELSE}
  120.   DeallocateHWnd(FWindowHandle);
  121. {$ENDIF}
  122.   inherited Destroy;
  123. end;
  124.  
  125.  
  126. procedure TSimpleTimerHandler.AddTimer;
  127. begin
  128.   Inc(RefCount);
  129. end;
  130.  
  131.  
  132. procedure TSimpleTimerHandler.RemoveTimer;
  133. begin
  134.   if RefCount > 0 then
  135.     Dec(RefCount);
  136. end;
  137.  
  138.  
  139. procedure TSimpleTimerHandler.WndProc(var Msg: TMessage);
  140. var
  141.   Timer: TSimpleTimer;
  142. begin
  143.   if Msg.Msg = WM_TIMER then
  144.   begin
  145. {$WARNINGS OFF}
  146.     Timer := TSimpleTimer(Msg.wParam);
  147. {$WARNINGS ON}
  148.     if Timer.FAutoDisable then
  149.       Timer.Stop(True);
  150.     // Call OnTimer event method if assigned
  151.     if Assigned(Timer.FOnTimer) then
  152.       Timer.FOnTimer(Timer);
  153.   end
  154.   else
  155.     Msg.Result := DefWindowProc(FWindowHandle, Msg.Msg, Msg.wParam, Msg.lParam);
  156. end;
  157.  
  158. {---------------- Container management ----------------}
  159.  
  160. procedure AddTimer;
  161. begin
  162.   if not Assigned(SimpleTimerHandler) then
  163.     // Create new handler
  164.     SimpleTimerHandler := TSimpleTimerHandler.Create;
  165.   SimpleTimerHandler.AddTimer;
  166. end;
  167.  
  168.  
  169. procedure RemoveTimer;
  170. begin
  171.   if Assigned(SimpleTimerHandler) then
  172.   begin
  173.     SimpleTimerHandler.RemoveTimer;
  174.     if SimpleTimerHandler.RefCount = 0 then
  175.     begin
  176.       // Destroy handler
  177.       SimpleTimerHandler.Free;
  178.       SimpleTimerHandler := nil;
  179.     end;
  180.   end;
  181. end;
  182.  
  183. {------------------ Callback method -------------------}
  184. {
  185. procedure TimerProc(hWnd: HWND; uMsg: UINT; idEvent: UINT; dwTime: DWORD); stdcall;
  186. var
  187.   Timer: TSimpleTimer;
  188. begin
  189. //  if uMsg = WM_TIMER then    // It's always WM_TIMER
  190.   begin
  191.     try
  192.       Timer := TSimpleTimer(idEvent);
  193.       if Assigned(Timer.FCallBackProc) then
  194.         Timer.FCallBackProc(Timer.FOwner);
  195.     except
  196.       // ???
  197.     end;
  198.   end;
  199. end;
  200. }
  201. {------------------- TSimpleTimer ---------------------}
  202.  
  203. constructor TSimpleTimer.Create;
  204. begin
  205.   inherited Create;
  206.   Initialize(1000, nil);
  207. end;
  208.  
  209.  
  210. constructor TSimpleTimer.Create(AInterval: Cardinal; AOnTimer: TNotifyEvent);
  211. begin
  212.   inherited Create;
  213.   Initialize(AInterval, AOnTimer);
  214. end;
  215.  
  216.  
  217. destructor TSimpleTimer.Destroy;
  218. begin
  219.   if FEnabled then
  220.     Stop(True);
  221.   RemoveTimer;               // Container management
  222.   inherited Destroy;
  223. end;
  224.  
  225.  
  226. procedure TSimpleTimer.Initialize(AInterval: Cardinal; AOnTimer: TNotifyEvent);
  227. begin
  228. {$WARNINGS OFF}
  229.   FId := UINT(Self);         // Use Self as id in call to SetTimer and callback method
  230. {$WARNINGS ON}
  231.   FAutoDisable := False;
  232.   FEnabled := False;
  233.   FInterval := AInterval;
  234.   SetOnTimer(AOnTimer);
  235.   AddTimer;                  // Container management
  236. end;
  237.  
  238.  
  239. procedure TSimpleTimer.SetEnabled(Value: Boolean);
  240. begin
  241.   if Value then
  242.     Start
  243.   else
  244.     Stop(True);
  245. end;
  246.  
  247.  
  248. procedure TSimpleTimer.SetInterval(Value: Cardinal);
  249. begin
  250.   if Value <> FInterval then
  251.   begin
  252.     FInterval := Value;
  253.     if FEnabled then
  254.       if FInterval <> 0 then
  255.         Start
  256.       else
  257.         Stop(False);
  258.   end;
  259. end;
  260.  
  261.  
  262. procedure TSimpleTimer.SetOnTimer(Value: TNotifyEvent);
  263. begin
  264.   FOnTimer := Value;
  265.   if (not Assigned(Value)) and (FEnabled) then
  266.     Stop(False);
  267. end;
  268.  
  269.  
  270. function TSimpleTimer.Start: Boolean;
  271. begin
  272.   if FInterval = 0 then
  273.   begin
  274.     Result := False;
  275.     Exit;
  276.   end;
  277.   if FEnabled then
  278.     Stop(True);
  279. //  Result := (SetTimer(SimpleTimerHandler.FWindowHandle, FId, FInterval, @TimerProc) <> 0);
  280.   Result := (SetTimer(SimpleTimerHandler.FWindowHandle, FId, FInterval, nil) <> 0);
  281.   if Result then
  282.   begin
  283.     FEnabled := True;
  284.     Inc(SimpleTimerHandler.ActiveCount);
  285.   end
  286. {  else
  287.     raise EOutOfResources.Create(SNoTimers); }
  288. end;
  289.  
  290.  
  291. function TSimpleTimer.Stop(Disable: Boolean): Boolean;
  292. begin
  293.   if Disable then
  294.     FEnabled := False;
  295.   Result := KillTimer(SimpleTimerHandler.FWindowHandle, FId);
  296.   if Result and (SimpleTimerHandler.ActiveCount > 0) then
  297.     Dec(SimpleTimerHandler.ActiveCount);
  298. end;
  299.  
  300.  
  301. initialization
  302.  
  303. finalization
  304.   if Assigned(SimpleTimerHandler) then
  305.   begin
  306.     SimpleTimerHandler.Free;
  307.     SimpleTimerHandler := nil;
  308.   end;
  309.  
  310. end.
  311.  
  312.