604
社区成员
发帖
与我相关
我的任务
分享
unit PreciseTimerUnit;
interface
uses
Windows,MMSystem,UnitManagedObject;
type
TTimerEvent=procedure (Sender:TObject) of Object;
TPreciseTimer=class(TManagedObject)
strict private
FPurifierTimer:UINT;
FOnTimerEvent:TTimerEvent;
FInterval: UINT;
FResolution: UINT;
private
procedure RaiseTimerEvent;
public
property OnTimer:TTimerEvent read FOnTimerEvent write FOnTimerEvent;
property Interval: UINT read FInterval;
public
Constructor Create;overload;
Constructor Create(AInterval: UINT);overload;
Destructor Destroy;override;
end;
const
TIME_KILL_SYNCHRONOUS:UINT=$0100;
var
WinVersion:DWORD;
implementation
function ByteSwap(value:DWORD):DWORD; assembler;
asm
BSWAP eax
end;
procedure TPreciseTimer.RaiseTimerEvent;
begin
if Assigned(FOnTimerEvent) then
FOnTimerEvent(Self);
end;
procedure PurifierTimerProc(uTimerID, uMessage: UINT;
dwUser, dw1, dw2: DWORD) stdcall;
var
pTimer: TPreciseTimer;
begin
pTimer := TPreciseTimer(dwUser);
if pTimer.Attach <> pTimer then
Exit;
try
pTimer.RaiseTimerEvent;
finally
pTimer.Free;
end;
end;
constructor TPreciseTimer.Create;
begin
Create(1000);
end;
constructor TPreciseTimer.Create(AInterval: UINT);
var
fuEvent:UINT;
tc: TIMECAPS;
begin
Inherited Create;
FInterval := AInterval;
FOnTimerEvent := Nil;
if timeGetDevCaps(@tc, SizeOf(TIMECAPS)) <> TIMERR_NOERROR then Exit;
FResolution := tc.wPeriodMin;
if timeBeginPeriod(FResolution) <> TIMERR_NOERROR then Exit;;
fuEvent:=TIME_PERIODIC;
if(HiWord(byteswap( WinVersion))>=$501) then//WinXP or Later
fuEvent:=fuEvent or TIME_KILL_SYNCHRONOUS;
FPurifierTimer:=timeSetEvent(Interval,
0,
PurifierTimerProc,
DWORD_PTR(self),
fuEvent);
if(0=FPurifierTimer) then
timeEndPeriod(FResolution);
end;
destructor TPreciseTimer.Destroy;
begin
if(0<>FPurifierTimer) then
begin
timeKillEvent(FPurifierTimer);
timeEndPeriod(FResolution);
FPurifierTimer:=0;
Sleep(15);
end;
end;
initialization
WinVersion:=GetVersion;
finalization
end.