MMTimer.pas
上传用户:hylc_2004
上传日期:2014-01-23
资源大小:46800k
文件大小:10k
源码类别:

Delphi控件源码

开发平台:

Delphi

  1. {========================================================================}
  2. {=                (c) 1995-98 SwiftSoft Ronald Dittrich                 =}
  3. {========================================================================}
  4. {=                          All Rights Reserved                         =}
  5. {========================================================================}
  6. {=  D 01099 Dresden             = Fax.: +49(0)351-8037944               =}
  7. {=  Loewenstr.7a                = info@swiftsoft.de                     =}
  8. {========================================================================}
  9. {=  Actual versions on http://www.swiftsoft.de/index.html               =}
  10. {========================================================================}
  11. {=  This code is for reference purposes only and may not be copied or   =}
  12. {=  distributed in any format electronic or otherwise except one copy   =}
  13. {=  for backup purposes.                                                =}
  14. {=                                                                      =}
  15. {=  No Delphi Component Kit or Component individually or in a collection=}
  16. {=  subclassed or otherwise from the code in this unit, or associated   =}
  17. {=  .pas, .dfm, .dcu, .asm or .obj files may be sold or distributed     =}
  18. {=  without express permission from SwiftSoft.                          =}
  19. {=                                                                      =}
  20. {=  For more licence informations please refer to the associated        =}
  21. {=  HelpFile.                                                           =}
  22. {========================================================================}
  23. {=  $Date: 23.11.98 - 17:38:26 $                                        =}
  24. {========================================================================}
  25. Unit MMTimer;
  26. {$C FIXED PRELOAD PERMANENT}
  27. {$I COMPILER.INC}
  28. Interface
  29. Uses
  30. {$IFDEF WIN32}
  31.     Windows,
  32. {$ELSE}
  33.     WinTypes,
  34.     WinProcs,
  35. {$ENDIF}
  36.     SysUtils,
  37.     MMSystem,
  38.     MMUtils;
  39. const
  40.     TIMERELAPSE = 25;
  41. type
  42.   TMMTimeCallBack = procedure(uTimerID, dwUser: Longint);
  43. function  MMTimeSetEvent(Interval: Cardinal; Suspended: Boolean;
  44.                          lpCallBack: TMMTimeCallBack; dwUser: Longint): Longint;
  45. procedure MMTimeSetInterval(uTimerID: Longint; Interval: Cardinal);
  46. procedure MMTimeSuspendEvent(uTimerID: Longint);
  47. procedure MMTimeResumeEvent(uTimerID: Longint);
  48. procedure MMTimeKillEvent(uTimerID: Longint);
  49. implementation
  50. type
  51.    PMMTimer = ^TMMTimer;
  52.    TMMTimer = record
  53.       dwInterval : Longint;
  54.       dwUserData : Longint;
  55.       lpFunction : TMMTimeCallBack;
  56.       dwSuspended: Longint;
  57.       dwCounter  : Longint;
  58.       lpNext     : PMMTimer;
  59.    end;
  60.    PMMTimerData = ^TMMTimerData;
  61.    TMMTimerData = record
  62.       TimerID    : integer;
  63.       TimerList  : PMMTimer;
  64.       TimerCount : Longint;
  65.       InHandler  : Longint;
  66.    end;
  67. const
  68.    TimerData : TMMTimerData = (TimerID   : 0;
  69.                                TimerList : nil;
  70.                                TimerCount: 0;
  71.                                InHandler : 0);
  72. {$IFDEF WIN32}
  73. var
  74.    DataSection: TRtlCriticalSection;
  75. {$ENDIF}
  76. {------------------------------------------------------------------------}
  77. procedure TimeCallBack(uTimerID, uMessage: UINT; dwUser, dw1, dw2: DWORD);
  78. export;{$IFDEF WIN32}stdcall;{$ENDIF}
  79. var
  80.    pTimer: PMMTimer;
  81. begin
  82.    if (dwUser <> 0) then
  83.    with PMMTimerData(dwUser)^ do
  84.    begin
  85.       inc(InHandler);
  86.       if (InHandler = 1) then
  87.       begin
  88.          {$IFDEF WIN32}
  89.          EnterCriticalSection(DataSection);
  90.          try
  91.          {$ENDIF}
  92.             pTimer := TimerList;
  93.             while (pTimer <> nil) do
  94.             with pTimer^ do
  95.             begin
  96.                if (dwSuspended = 0) then
  97.                begin
  98.                   inc(dwCounter,TIMERELAPSE);
  99.                   if (dwCounter >= dwInterval) then
  100.                   begin
  101.                      asm
  102.                         {$IFDEF WIN32}
  103.                         pushad
  104.                         {$ELSE}
  105.                         db   66h
  106.                         pusha
  107.                         {$ENDIF}
  108.                      end;
  109.                      lpFunction(Longint(pTimer),dwUserData);
  110.                      asm
  111.                         {$IFDEF WIN32}
  112.                         popad
  113.                         {$ELSE}
  114.                         db   66h
  115.                         popa
  116.                         {$ENDIF}
  117.                      end;
  118.                      dwCounter := 0;
  119.                   end;
  120.                end;
  121.                pTimer := pTimer^.lpNext;
  122.             end;
  123.          {$IFDEF WIN32}
  124.          finally
  125.             LeaveCriticalSection(DataSection);
  126.          end;
  127.          {$ENDIF}
  128.       end;
  129.       dec(InHandler);
  130.    end;
  131. end;
  132. {------------------------------------------------------------------------}
  133. function MMTimeSetEvent(Interval: Cardinal; Suspended: Boolean;
  134.                         lpCallBack: TMMTimeCallBack; dwUser: Longint): Longint;
  135. var
  136. {$IFNDEF WIN32}
  137.    TimeCB: TTimeCallBack;
  138. {$ENDIF}
  139.    p,pTimer: PMMTimer;
  140. begin
  141.    with TimerData do
  142.    begin
  143.       inc(TimerCount);
  144.       if (TimerCount = 1) then
  145.       begin
  146.          { create the timer itself }
  147.          TimeBeginPeriod(TIMERELAPSE);
  148.          {$IFDEF WIN32}
  149.          InitializeCriticalSection(DataSection);
  150.          TimerID := TimeSetEvent(TIMERELAPSE, 0, @TimeCallBack, Longint(@TimerData), TIME_PERIODIC);
  151.          {$ELSE}
  152.          TimeCB := TimeCallBack;
  153.          TimerID := TimeSetEvent(TIMERELAPSE, 0, TimeCB, Longint(@TimerData), TIME_PERIODIC);
  154.          {$ENDIF}
  155.          if (TimerID = 0) then
  156.          begin
  157.             Result := 0;
  158.             TimerCount := 0;
  159.             exit;
  160.          end;
  161.       end;
  162.       { create new timer }
  163.       New(pTimer);
  164.       with pTimer^ do
  165.       begin
  166.          dwInterval := Max(Interval,TIMERELAPSE);
  167.          dwUserData := dwUser;
  168.          lpFunction := lpCallBack;
  169.          dwCounter  := 0;
  170.          dwSuspended:= Ord(Suspended);
  171.          lpNext     := nil;
  172.       end;
  173.       {$IFDEF WIN32}
  174.       EnterCriticalSection(DataSection);
  175.       try
  176.       {$ENDIF}
  177.          { insert the new timer in the list }
  178.          if TimerList = nil then TimerList := pTimer
  179.          else
  180.          begin
  181.             { insert at end }
  182.             p := TimerList;
  183.             while (p^.lpNext <> nil) do p := p^.lpNext;
  184.             p^.lpNext := pTimer;
  185.          end;
  186.       {$IFDEF WIN32}
  187.       finally
  188.         LeaveCriticalSection(DataSection);
  189.       end;
  190.       {$ENDIF}
  191.       Result := DWORD(pTimer);
  192.    end;
  193. end;
  194. {------------------------------------------------------------------------}
  195. procedure MMTimeSetInterval(uTimerID: Longint; Interval: Cardinal);
  196. begin
  197.    if (uTimerID <> 0) and (TimerData.TimerCount > 0) then
  198.    begin
  199.       {$IFDEF WIN32}
  200.       EnterCriticalSection(DataSection);
  201.       try
  202.       {$ENDIF}
  203.          with PMMTimer(uTimerID)^ do
  204.          begin
  205.             dwInterval := Max(Interval,TIMERELAPSE);
  206.             dwCounter := 0;
  207.          end;
  208.       {$IFDEF WIN32}
  209.       finally
  210.          LeaveCriticalSection(DataSection);
  211.       end;
  212.       {$ENDIF}
  213.    end;
  214. end;
  215. {------------------------------------------------------------------------}
  216. procedure MMTimeSuspendEvent(uTimerID: Longint);
  217. begin
  218.    if (uTimerID <> 0) and (TimerData.TimerCount > 0) then
  219.    begin
  220.       {$IFDEF WIN32}
  221.       EnterCriticalSection(DataSection);
  222.       try
  223.       {$ENDIF}
  224.          with PMMTimer(uTimerID)^ do
  225.          begin
  226.             inc(dwSuspended);
  227.             dwCounter := 0;
  228.          end;
  229.       {$IFDEF WIN32}
  230.       finally
  231.          LeaveCriticalSection(DataSection);
  232.       end;
  233.       {$ENDIF}
  234.    end;
  235. end;
  236. {------------------------------------------------------------------------}
  237. procedure MMTimeResumeEvent(uTimerID: Longint);
  238. begin
  239.    if (uTimerID <> 0) and (TimerData.TimerCount > 0) then
  240.    begin
  241.       {$IFDEF WIN32}
  242.       EnterCriticalSection(DataSection);
  243.       try
  244.       {$ENDIF}
  245.          with PMMTimer(uTimerID)^ do
  246.          begin
  247.             if (dwSuspended > 0) then dec(dwSuspended);
  248.          end;
  249.       {$IFDEF WIN32}
  250.       finally
  251.          LeaveCriticalSection(DataSection);
  252.       end;
  253.       {$ENDIF}
  254.    end;
  255. end;
  256. {------------------------------------------------------------------------}
  257. procedure MMTimeKillEvent(uTimerID: Longint);
  258. var
  259.    p: PMMTimer;
  260. begin
  261.    if (uTimerID <> 0) and (TimerData.TimerCount > 0) then
  262.    with TimerData do
  263.    begin
  264.       {$IFDEF WIN32}
  265.       EnterCriticalSection(DataSection);
  266.       try
  267.       {$ENDIF}
  268.          if (PMMTimer(uTimerId) = TimerList) then
  269.          begin
  270.             TimerList := TimerList^.lpNext;
  271.             Dispose(Pointer(uTimerID));
  272.             dec(TimerCount);
  273.          end
  274.          else
  275.          begin
  276.             { go trough the list and search the timer }
  277.             p := TimerList;
  278.             while (p <> nil) and (p^.lpNext <> PMMTimer(uTimerID)) do p := p^.lpNext;
  279.             if (p <> nil) then
  280.             begin
  281.                { remove timer from list }
  282.                p^.lpNext := PMMTimer(uTimerID)^.lpNext;
  283.                Dispose(Pointer(uTimerID));
  284.                dec(TimerCount);
  285.             end
  286.             else exit;
  287.          end;
  288.       {$IFDEF WIN32}
  289.       finally
  290.          LeaveCriticalSection(DataSection);
  291.       end;
  292.       {$ENDIF}
  293.       if (TimerCount = 0) then
  294.       begin
  295.         if (TimerID <> 0) then
  296.         begin
  297.            TimeKillEvent(TimerID);
  298.            TimerID := 0;
  299.            TimeEndPeriod(TIMERELAPSE);
  300.            TimerList := nil;
  301.         end;
  302.         {$IFDEF WIN32}
  303.         DeleteCriticalSection(DataSection);
  304.         {$ENDIF}
  305.       end;
  306.    end;
  307. end;
  308. procedure NewExitProc; Far;
  309. begin
  310.    if (TimerData.TimerID <> 0) then
  311.    with TimerData do
  312.    begin
  313.       { make sure the timer is shoot down }
  314.       TimeKillEvent(TimerID);
  315.       TimerID := 0;
  316.       TimeEndPeriod(TIMERELAPSE);
  317.       TimerList := nil;
  318.    end;
  319. end;
  320. initialization
  321. {$IFNDEF WIN32}
  322.    AddExitProc(NewExitProc);
  323. {$ELSE}
  324. finalization
  325.    NewExitProc;
  326. {$ENDIF}
  327. end.