CnTimer.pas 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799
  1. {******************************************************************************}
  2. { CnPack For Delphi/C++Builder }
  3. { 中国人自己的开放源码第三方开发包 }
  4. { (C)Copyright 2001-2018 CnPack 开发组 }
  5. { ------------------------------------ }
  6. { }
  7. { 本开发包是开源的自由软件,您可以遵照 CnPack 的发布协议来修 }
  8. { 改和重新发布这一程序。 }
  9. { }
  10. { 发布这一开发包的目的是希望它有用,但没有任何担保。甚至没有 }
  11. { 适合特定目的而隐含的担保。更详细的情况请参阅 CnPack 发布协议。 }
  12. { }
  13. { 您应该已经和开发包一起收到一份 CnPack 发布协议的副本。如果 }
  14. { 还没有,可访问我们的网站: }
  15. { }
  16. { 网站地址:http://www.cnpack.org }
  17. { 电子邮件:master@cnpack.org }
  18. { }
  19. {******************************************************************************}
  20. unit CnTimer;
  21. {* |<PRE>
  22. ================================================================================
  23. * 软件名称:不可视工具组件包
  24. * 单元名称:高精度定时器组件TCnTimer单元
  25. * 单元作者:周劲羽 (zjy@cnpack.org)
  26. * 备 注:- Delphi自带的TTimer使用操作系统以消息方式提供的定时器,在Win9X下
  27. * 定时精度仅为55ms,NT下约10ms。
  28. * - TCnTimer使用多媒体定时器进行定时控制,精度较高。其使用方式与TTimer
  29. * 完全兼容,并提供了更多的功能。
  30. * - TCnTimerList定时器列表可以同时产生多个定时器。
  31. * - 所有定时器使用同一个内部定时器,适合大量使用的场合。
  32. * - 由于Win32是抢占式多任务操作系统,各个线程轮流享用CPU时间片,如果
  33. * 其它的线程占用大量CPU时间,即使设置最高精度,也不一定能保证精确
  34. * 的定时间隔。
  35. * 开发平台:PWin98SE + Delphi 5.0
  36. * 兼容测试:PWin9X/2000/XP + Delphi 5/6
  37. * 本 地 化:该单元中的字符串均符合本地化处理方式
  38. * 单元标识:$Id$
  39. * 修改记录:2008.12.22 V2.2
  40. * 增加同步事件属性 SyncEvent 并默认为真,使定时器事件可以在主线程中执行
  41. * 2006.12.28 V2.1
  42. * 去掉定时线程,改用多媒体定时器,以减少资源占用并解决在 DLL 中不能
  43. * 使用的问题
  44. * 2002.11.05 V2.0
  45. * 重写全部代码,增加定时器列表,所有定时器使用同一线程定时
  46. * 2002.04.18 V1.0
  47. * 创建单元
  48. ================================================================================
  49. |</PRE>}
  50. interface
  51. {$I CnPack.inc}
  52. uses
  53. Windows, SysUtils, Classes, Forms, MMSystem, CnClasses, CnConsts, CnCompConsts,
  54. CnNativeDecl;
  55. type
  56. //==============================================================================
  57. // 高精度定时器对象
  58. //==============================================================================
  59. { TCnTimerObject }
  60. TCnTimerObject = class(TObject)
  61. private
  62. FActualFPS: Double;
  63. FEnabled: Boolean;
  64. FExecCount: Cardinal;
  65. FInterval: Cardinal;
  66. FLastTickCount: Cardinal;
  67. FOnTimer: TNotifyEvent;
  68. FRepeatCount: Cardinal;
  69. FSyncEvent: Boolean;
  70. function GetFPS: Double;
  71. procedure SetEnabled(Value: Boolean);
  72. procedure SetFPS(Value: Double);
  73. procedure SetInterval(Value: Cardinal);
  74. procedure SetRepeatCount(Value: Cardinal);
  75. protected
  76. procedure Timer; dynamic;
  77. public
  78. constructor Create;
  79. destructor Destroy; override;
  80. property ActualFPS: Double read FActualFPS;
  81. property ExecCount: Cardinal read FExecCount;
  82. property Enabled: Boolean read FEnabled write SetEnabled default True;
  83. property FPS: Double read GetFPS write SetFPS stored False;
  84. property Interval: Cardinal read FInterval write SetInterval default 1000;
  85. property OnTimer: TNotifyEvent read FOnTimer write FOnTimer;
  86. property RepeatCount: Cardinal read FRepeatCount write SetRepeatCount default 0;
  87. property SyncEvent: Boolean read FSyncEvent write FSyncEvent default True;
  88. end;
  89. //==============================================================================
  90. // 高精度定时器组件
  91. //==============================================================================
  92. { TCnTimer }
  93. TCnTimer = class(TCnComponent)
  94. {* 高精度定时器组件,使用方法类似 TTimer。}
  95. private
  96. FTimerObject: TCnTimerObject;
  97. function GetActualFPS: Double;
  98. function GetEnabled: Boolean;
  99. function GetExecCount: Cardinal;
  100. function GetFPS: Double;
  101. function GetInterval: Cardinal;
  102. function GetOnTimer: TNotifyEvent;
  103. function GetRepeatCount: Cardinal;
  104. function GetSyncEvent: Boolean;
  105. procedure SetEnabled(Value: Boolean);
  106. procedure SetFPS(Value: Double);
  107. procedure SetInterval(Value: Cardinal);
  108. procedure SetOnTimer(Value: TNotifyEvent);
  109. procedure SetRepeatCount(Value: Cardinal);
  110. procedure SetSyncEvent(const Value: Boolean);
  111. protected
  112. procedure GetComponentInfo(var AName, Author, Email, Comment: string);
  113. override;
  114. public
  115. constructor Create(AOwner: TComponent); override;
  116. {* 类构造器}
  117. destructor Destroy; override;
  118. {* 类析构器}
  119. property ActualFPS: Double read GetActualFPS;
  120. {* 实际的定时器速率,次每秒}
  121. property ExecCount: Cardinal read GetExecCount;
  122. {* 已经执行过的次数}
  123. published
  124. property Enabled: Boolean read GetEnabled write SetEnabled default True;
  125. {* 定时器是否启用}
  126. property FPS: Double read GetFPS write SetFPS stored False;
  127. {* 定时器速度,次每秒}
  128. property Interval: Cardinal read GetInterval write SetInterval default 1000;
  129. {* 定时间隔,毫秒}
  130. property OnTimer: TNotifyEvent read GetOnTimer write SetOnTimer;
  131. {* 定时事件}
  132. property RepeatCount: Cardinal read GetRepeatCount write SetRepeatCount default 0;
  133. {* 定时事件次数,当定时事件发生指定次数后自动关闭。如果为 0 表示不限制}
  134. property SyncEvent: Boolean read GetSyncEvent write SetSyncEvent default True;
  135. {* 定时事件是否用同步方式在主线程中产生,如果为 False 则定时事件在多媒体定时器线程中调用。
  136. 定时事件中如果涉及到 VCL 界面操作,应设为 True。}
  137. end;
  138. //==============================================================================
  139. // 高精度定时器列表集合子项
  140. //==============================================================================
  141. { TCnTimerItem }
  142. TCnTimerItem = class(TCollectionItem)
  143. {* 高精度定时器列表子项,使用方法类似 TTimer。}
  144. private
  145. FOnTimer: TNotifyEvent;
  146. FTimerObject: TCnTimerObject;
  147. function GetActualFPS: Double;
  148. function GetEnabled: Boolean;
  149. function GetExecCount: Cardinal;
  150. function GetFPS: Double;
  151. function GetInterval: Cardinal;
  152. function GetRepeatCount: Cardinal;
  153. procedure SetEnabled(Value: Boolean);
  154. procedure SetFPS(Value: Double);
  155. procedure SetInterval(Value: Cardinal);
  156. procedure SetRepeatCount(Value: Cardinal);
  157. function GetSyncEvent: Boolean;
  158. procedure SetSyncEvent(const Value: Boolean);
  159. protected
  160. procedure Timer(Sender: TObject);
  161. public
  162. constructor Create(Collection: TCollection); override;
  163. {* 类构造器}
  164. destructor Destroy; override;
  165. {* 类析构器}
  166. procedure Assign(Source: TPersistent); override;
  167. {* 赋值方法}
  168. property ActualFPS: Double read GetActualFPS;
  169. {* 实际的定时器速率,次每秒}
  170. property ExecCount: Cardinal read GetExecCount;
  171. {* 已经执行过的次数}
  172. published
  173. property Enabled: Boolean read GetEnabled write SetEnabled default True;
  174. {* 定时器是否启用}
  175. property FPS: Double read GetFPS write SetFPS stored False;
  176. {* 定时器速度,次每秒}
  177. property Interval: Cardinal read GetInterval write SetInterval default 1000;
  178. {* 定时间隔,毫秒}
  179. property OnTimer: TNotifyEvent read FOnTimer write FOnTimer;
  180. {* 定时事件}
  181. property RepeatCount: Cardinal read GetRepeatCount write SetRepeatCount default 0;
  182. {* 定时事件次数,当定时事件发生指定次数后自动关闭。如果为 0 表示不限制}
  183. property SyncEvent: Boolean read GetSyncEvent write SetSyncEvent default True;
  184. {* 定时事件是否用同步方式在主线程中产生,如果为 False 则定时事件在多媒体定时器线程中调用。
  185. 定时事件中如果涉及到 VCL 界面操作,应设为 True。}
  186. end;
  187. //==============================================================================
  188. // 高精度定时器列表集合类
  189. //==============================================================================
  190. { TCnTimerCollection }
  191. TCnTimerList = class;
  192. TCnTimerCollection = class(TOwnedCollection)
  193. {* 高精度定时器列表集合}
  194. private
  195. FTimerList: TCnTimerList;
  196. function GetItems(Index: Integer): TCnTimerItem;
  197. procedure SetItems(Index: Integer; Value: TCnTimerItem);
  198. protected
  199. property TimerList: TCnTimerList read FTimerList;
  200. public
  201. constructor Create(AOwner: TPersistent);
  202. {* 类构造器}
  203. property Items[Index: Integer]: TCnTimerItem read GetItems write SetItems; default;
  204. {* 定时器数组属性}
  205. end;
  206. //==============================================================================
  207. // 高精度定时器列表组件
  208. //==============================================================================
  209. { TCnTimerList }
  210. TCnTimerEvent = procedure(Sender: TObject; Index: Integer; var Handled:
  211. Boolean) of object;
  212. {* 高精度定时器列表事件。Index 为产生事件的定时器子项序号,Handle 返回是否已处理,
  213. 如果在事件中将 Handle 置为 true,将不产生该定时器子项事件}
  214. TCnTimerList = class(TCnComponent)
  215. {* 高精度定时器列表组件,可以定义多个定时器。}
  216. private
  217. FItems: TCnTimerCollection;
  218. FOnTimer: TCnTimerEvent;
  219. procedure SetItems(Value: TCnTimerCollection);
  220. protected
  221. procedure GetComponentInfo(var AName, Author, Email, Comment: string);
  222. override;
  223. function Timer(Index: Integer): Boolean;
  224. public
  225. constructor Create(AOwner: TComponent); override;
  226. {* 类构造器}
  227. destructor Destroy; override;
  228. {* 类析构器}
  229. published
  230. property Items: TCnTimerCollection read FItems write SetItems;
  231. {* 定时器列表}
  232. property OnTimer: TCnTimerEvent read FOnTimer write FOnTimer;
  233. {* 定时器事件}
  234. end;
  235. implementation
  236. uses
  237. Messages;
  238. const
  239. UM_CNTIMER = WM_USER + 101;
  240. type
  241. //==============================================================================
  242. // 高精度定时器管理器(私有类)
  243. //==============================================================================
  244. { TCnTimerMgr }
  245. TCnTimerMgr = class(TObject)
  246. private
  247. FTimerList: TThreadList;
  248. FTimerRes: Integer;
  249. FTimerID: Integer;
  250. FHwnd: HWND;
  251. function InitMMTimer: Boolean;
  252. procedure FreeMMTimer;
  253. protected
  254. procedure ClearTimer;
  255. procedure DoTimer(Sync: Boolean);
  256. procedure Timer; virtual;
  257. procedure WndProc(var Message: TMessage);
  258. public
  259. constructor Create;
  260. destructor Destroy; override;
  261. function AddTimer: TCnTimerObject;
  262. procedure DeleteTimer(TimerObject: TCnTimerObject);
  263. end;
  264. //==============================================================================
  265. // 高精度定时器管理器(私有类)
  266. //==============================================================================
  267. { TCnTimerMgr }
  268. constructor TCnTimerMgr.Create;
  269. begin
  270. inherited Create;
  271. FTimerList := TThreadList.Create;
  272. FHwnd := AllocateHWnd(WndProc);
  273. InitMMTimer;
  274. end;
  275. destructor TCnTimerMgr.Destroy;
  276. begin
  277. DeallocateHWnd(FHwnd);
  278. FreeMMTimer;
  279. ClearTimer;
  280. FreeAndNil(FTimerList);
  281. inherited Destroy;
  282. end;
  283. procedure MMTimerProc(uTimerID, uMessage: UINT; dwUser, dw1, dw2: TCnNativePointer) stdcall;
  284. begin
  285. TCnTimerMgr(dwUser).Timer;
  286. end;
  287. function TCnTimerMgr.InitMMTimer: Boolean;
  288. var
  289. tc: TIMECAPS;
  290. begin
  291. Result := False;
  292. if timeGetDevCaps(@tc, SizeOf(TIMECAPS)) = TIMERR_NOERROR then
  293. begin
  294. FTimerRes := tc.wPeriodMin;
  295. if timeBeginPeriod(FTimerRes) = TIMERR_NOERROR then
  296. begin
  297. FTimerID := timeSetEvent(tc.wPeriodMin, 0, MMTimerProc, Cardinal(Self),
  298. TIME_PERIODIC);
  299. Result := FTimerID <> 0;
  300. end
  301. else
  302. FTimerRes := 0;
  303. end;
  304. end;
  305. procedure TCnTimerMgr.FreeMMTimer;
  306. begin
  307. if FTimerID <> 0 then
  308. begin
  309. timeKillEvent(FTimerID);
  310. end;
  311. if FTimerRes <> 0 then
  312. begin
  313. timeEndPeriod(FTimerRes);
  314. end;
  315. end;
  316. function TCnTimerMgr.AddTimer: TCnTimerObject;
  317. begin
  318. Result := TCnTimerObject.Create;
  319. with FTimerList.LockList do
  320. try
  321. Add(Result);
  322. finally
  323. FTimerList.UnlockList;
  324. end;
  325. end;
  326. procedure TCnTimerMgr.ClearTimer;
  327. var
  328. i: Integer;
  329. begin
  330. with FTimerList.LockList do
  331. try
  332. for i := Count - 1 downto 0 do
  333. begin
  334. TCnTimerObject(Items[i]).Free;
  335. Delete(i);
  336. end;
  337. finally
  338. FTimerList.UnlockList;
  339. end;
  340. end;
  341. procedure TCnTimerMgr.DeleteTimer(TimerObject: TCnTimerObject);
  342. var
  343. i: Integer;
  344. begin
  345. with FTimerList.LockList do
  346. try
  347. for i := 0 to Count - 1 do
  348. if Items[i] = TimerObject then
  349. begin
  350. TimerObject.Free;
  351. Delete(i);
  352. Exit;
  353. end;
  354. finally
  355. FTimerList.UnlockList;
  356. end;
  357. end;
  358. procedure TCnTimerMgr.DoTimer(Sync: Boolean);
  359. var
  360. i: Integer;
  361. CurrTick: Cardinal;
  362. begin
  363. with FTimerList.LockList do
  364. try
  365. CurrTick := timeGetTime;
  366. for i := 0 to Count - 1 do
  367. with TCnTimerObject(Items[i]) do
  368. if Enabled and (FSyncEvent = Sync) and(Interval <> 0) and
  369. (CurrTick - FLastTickCount >= Interval) and Assigned(FOnTimer) then
  370. begin
  371. if CurrTick <> FLastTickCount then
  372. FActualFPS := 1000 / (CurrTick - FLastTickCount)
  373. else
  374. FActualFPS := 0;
  375. FLastTickCount := CurrTick;
  376. try
  377. Timer;
  378. except
  379. Application.HandleException(Self);
  380. end;
  381. end;
  382. finally
  383. FTimerList.UnlockList;
  384. end;
  385. end;
  386. procedure TCnTimerMgr.Timer;
  387. begin
  388. DoTimer(False);
  389. PostMessage(FHwnd, UM_CNTIMER, 0, 0);
  390. end;
  391. procedure TCnTimerMgr.WndProc(var Message: TMessage);
  392. begin
  393. if Message.Msg = UM_CNTIMER then
  394. begin
  395. DoTimer(True);
  396. end;
  397. end;
  398. var
  399. TimerMgr: TCnTimerMgr;
  400. function GetTimerMgr: TCnTimerMgr;
  401. begin
  402. if TimerMgr = nil then
  403. TimerMgr := TCnTimerMgr.Create;
  404. Result := TimerMgr;
  405. end;
  406. //==============================================================================
  407. // 高精度定时器对象
  408. //==============================================================================
  409. { TCnTimerObject }
  410. constructor TCnTimerObject.Create;
  411. begin
  412. inherited Create;
  413. FEnabled := True;
  414. FExecCount := 0;
  415. FInterval := 1000;
  416. FLastTickCount := timeGetTime;
  417. FRepeatCount := 0;
  418. FSyncEvent := True;
  419. end;
  420. destructor TCnTimerObject.Destroy;
  421. begin
  422. inherited;
  423. end;
  424. function TCnTimerObject.GetFPS: Double;
  425. begin
  426. if Interval = 0 then
  427. Result := 0
  428. else
  429. Result := 1000 / Interval;
  430. end;
  431. procedure TCnTimerObject.SetEnabled(Value: Boolean);
  432. begin
  433. if FEnabled <> Value then
  434. begin
  435. FEnabled := Value;
  436. FExecCount := 0;
  437. if FEnabled then
  438. begin
  439. FLastTickCount := timeGetTime;
  440. end;
  441. end;
  442. end;
  443. procedure TCnTimerObject.SetFPS(Value: Double);
  444. begin
  445. if Value < 0 then
  446. Exit
  447. else if Value < 1 / High(Word) then
  448. Value := 1 / High(Word)
  449. else if Value > 1000 then
  450. Value := 1000;
  451. FInterval := Round(1000 / Value);
  452. end;
  453. procedure TCnTimerObject.SetInterval(Value: Cardinal);
  454. begin
  455. if FInterval <> Value then
  456. begin
  457. FInterval := Value;
  458. FLastTickCount := timeGetTime;
  459. end;
  460. end;
  461. procedure TCnTimerObject.SetRepeatCount(Value: Cardinal);
  462. begin
  463. if FRepeatCount <> Value then
  464. begin
  465. FRepeatCount := Value;
  466. end;
  467. end;
  468. procedure TCnTimerObject.Timer;
  469. begin
  470. Inc(FExecCount);
  471. if Assigned(FOnTimer) then FOnTimer(Self);
  472. if (RepeatCount <> 0) and (FExecCount >= RepeatCount) then
  473. begin
  474. Enabled := False;
  475. end;
  476. end;
  477. //==============================================================================
  478. // 高精度定时器组件
  479. //==============================================================================
  480. { TCnTimer }
  481. constructor TCnTimer.Create(AOwner: TComponent);
  482. begin
  483. inherited Create(AOwner);
  484. FTimerObject := GetTimerMgr.AddTimer;
  485. end;
  486. destructor TCnTimer.Destroy;
  487. begin
  488. if TimerMgr <> nil then
  489. TimerMgr.DeleteTimer(FTimerObject);
  490. inherited Destroy;
  491. end;
  492. function TCnTimer.GetActualFPS: Double;
  493. begin
  494. Result := FTimerObject.ActualFPS;
  495. end;
  496. procedure TCnTimer.GetComponentInfo(var AName, Author, Email, Comment: string);
  497. begin
  498. AName := SCnTimerName;
  499. Author := SCnPack_Zjy;
  500. Email := SCnPack_ZjyEmail;
  501. Comment := SCnTimerComment;
  502. end;
  503. function TCnTimer.GetEnabled: Boolean;
  504. begin
  505. Result := FTimerObject.Enabled;
  506. end;
  507. function TCnTimer.GetExecCount: Cardinal;
  508. begin
  509. Result := FTimerObject.ExecCount;
  510. end;
  511. function TCnTimer.GetFPS: Double;
  512. begin
  513. Result := FTimerObject.FPS;
  514. end;
  515. function TCnTimer.GetInterval: Cardinal;
  516. begin
  517. Result := FTimerObject.Interval;
  518. end;
  519. function TCnTimer.GetOnTimer: TNotifyEvent;
  520. begin
  521. Result := FTimerObject.OnTimer;
  522. end;
  523. function TCnTimer.GetRepeatCount: Cardinal;
  524. begin
  525. Result := FTimerObject.RepeatCount;
  526. end;
  527. function TCnTimer.GetSyncEvent: Boolean;
  528. begin
  529. Result := FTimerObject.SyncEvent;
  530. end;
  531. procedure TCnTimer.SetEnabled(Value: Boolean);
  532. begin
  533. FTimerObject.Enabled := Value;
  534. end;
  535. procedure TCnTimer.SetFPS(Value: Double);
  536. begin
  537. FTimerObject.FPS := Value;
  538. end;
  539. procedure TCnTimer.SetInterval(Value: Cardinal);
  540. begin
  541. FTimerObject.Interval := Value;
  542. end;
  543. procedure TCnTimer.SetOnTimer(Value: TNotifyEvent);
  544. begin
  545. FTimerObject.OnTimer := Value;
  546. end;
  547. procedure TCnTimer.SetRepeatCount(Value: Cardinal);
  548. begin
  549. FTimerObject.RepeatCount := Value;
  550. end;
  551. procedure TCnTimer.SetSyncEvent(const Value: Boolean);
  552. begin
  553. FTimerObject.SyncEvent := Value;
  554. end;
  555. //==============================================================================
  556. // 高精度定时器列表集合子项
  557. //==============================================================================
  558. { TCnTimerItem }
  559. constructor TCnTimerItem.Create(Collection: TCollection);
  560. begin
  561. inherited Create(Collection);
  562. FTimerObject := GetTimerMgr.AddTimer;
  563. FTimerObject.OnTimer := Timer;
  564. end;
  565. destructor TCnTimerItem.Destroy;
  566. begin
  567. if TimerMgr <> nil then
  568. TimerMgr.DeleteTimer(FTimerObject);
  569. inherited Destroy;
  570. end;
  571. procedure TCnTimerItem.Assign(Source: TPersistent);
  572. begin
  573. if Source is TCnTimerItem then
  574. begin
  575. Enabled := TCnTimerItem(Source).Enabled;
  576. Interval := TCnTimerItem(Source).Interval;
  577. RepeatCount := TCnTimerItem(Source).RepeatCount;
  578. end
  579. else
  580. inherited;
  581. end;
  582. function TCnTimerItem.GetActualFPS: Double;
  583. begin
  584. Result := FTimerObject.ActualFPS;
  585. end;
  586. function TCnTimerItem.GetEnabled: Boolean;
  587. begin
  588. Result := FTimerObject.Enabled;
  589. end;
  590. function TCnTimerItem.GetExecCount: Cardinal;
  591. begin
  592. Result := FTimerObject.ExecCount;
  593. end;
  594. function TCnTimerItem.GetFPS: Double;
  595. begin
  596. Result := FTimerObject.FPS;
  597. end;
  598. function TCnTimerItem.GetInterval: Cardinal;
  599. begin
  600. Result := FTimerObject.Interval;
  601. end;
  602. function TCnTimerItem.GetRepeatCount: Cardinal;
  603. begin
  604. Result := FTimerObject.RepeatCount;
  605. end;
  606. function TCnTimerItem.GetSyncEvent: Boolean;
  607. begin
  608. Result := FTimerObject.SyncEvent;
  609. end;
  610. procedure TCnTimerItem.SetEnabled(Value: Boolean);
  611. begin
  612. FTimerObject.Enabled := Value;
  613. end;
  614. procedure TCnTimerItem.SetFPS(Value: Double);
  615. begin
  616. FTimerObject.FPS := Value;
  617. end;
  618. procedure TCnTimerItem.SetInterval(Value: Cardinal);
  619. begin
  620. FTimerObject.Interval := Value;
  621. end;
  622. procedure TCnTimerItem.SetRepeatCount(Value: Cardinal);
  623. begin
  624. FTimerObject.RepeatCount := Value;
  625. end;
  626. procedure TCnTimerItem.SetSyncEvent(const Value: Boolean);
  627. begin
  628. FTimerObject.SyncEvent := Value;
  629. end;
  630. procedure TCnTimerItem.Timer(Sender: TObject);
  631. begin
  632. if not TCnTimerList(TCnTimerCollection(Collection).GetOwner).Timer(Index) then
  633. if Assigned(FOnTimer) then
  634. FOnTimer(Self);
  635. end;
  636. //==============================================================================
  637. // 高精度定时器列表集合类
  638. //==============================================================================
  639. { TCnTimerCollection }
  640. constructor TCnTimerCollection.Create(AOwner: TPersistent);
  641. begin
  642. inherited Create(AOwner, TCnTimerItem);
  643. Assert(AOwner is TCnTimerList);
  644. end;
  645. function TCnTimerCollection.GetItems(Index: Integer): TCnTimerItem;
  646. begin
  647. Result := TCnTimerItem(inherited Items[Index]);
  648. end;
  649. procedure TCnTimerCollection.SetItems(Index: Integer; Value: TCnTimerItem);
  650. begin
  651. inherited Items[Index] := Value;
  652. end;
  653. //==============================================================================
  654. // 高精度定时器列表组件
  655. //==============================================================================
  656. { TCnTimerList }
  657. constructor TCnTimerList.Create(AOwner: TComponent);
  658. begin
  659. inherited Create(AOwner);
  660. FItems := TCnTimerCollection.Create(Self);
  661. end;
  662. destructor TCnTimerList.Destroy;
  663. begin
  664. FItems.Free;
  665. inherited Destroy;
  666. end;
  667. procedure TCnTimerList.GetComponentInfo(var AName, Author, Email, Comment:
  668. string);
  669. begin
  670. AName := SCnTimerListName;
  671. Author := SCnPack_Zjy;
  672. Email := SCnPack_ZjyEmail;
  673. Comment := SCnTimerListComment;
  674. end;
  675. procedure TCnTimerList.SetItems(Value: TCnTimerCollection);
  676. begin
  677. FItems.Assign(Value);
  678. end;
  679. function TCnTimerList.Timer(Index: Integer): Boolean;
  680. begin
  681. Result := False;
  682. if Assigned(FOnTimer) then
  683. FOnTimer(Self, Index, Result);
  684. end;
  685. initialization
  686. finalization
  687. if TimerMgr <> nil then
  688. FreeAndNil(TimerMgr);
  689. end.