The multimedia timer API provides single shot timer support. The advantage is that the time is much more accurate than the SetTimer / KillTimer solution, and you can use it at intervals of <50 ms. This happens at a cost since the callback is not returned in the context of the main thread. Here is my single shot timer implementation using the multimedia API:
unit MMTimer; interface uses windows, Classes, mmsystem, SysUtils; TOneShotCallbackEvent = procedure (const UserData: Pointer) of object; (* The MMOneShotCallback function calls the Callback after the Interval passed. ** Attention: ** The Callback is not called within the context of the main thread. *) type TMMOneShotTimer = class(TObject) private FTimeCaps: TTimeCaps; FResult: Integer; FResolution: Cardinal; public constructor Create; function MMOneShotCallback(const Interval: Cardinal; UserData: Pointer; Callback: TOneShotCallbackEvent): Boolean; property Result: Integer read FResult; property Resolution: Cardinal read FResolution; end; implementation type TOneShotCallbackData = record Callback: TOneShotCallbackEvent; UserData: Pointer; end; POneShotCallbackData = ^TOneShotCallbackData; procedure OneShotCallback(TimerID, Msg: UINT; dwUser, dw1, dw2: DWord); pascal; var pdata: POneShotCallbackData; begin pdata := Pointer(dwUser); pdata.Callback(pdata.UserData); FreeMemory(pdata); end; constructor TMMOneShotTimer.Create; begin FResult := timeGetDevCaps(@FTimeCaps, SizeOF(FTimeCaps)); Assert(FResult=TIMERR_NOERROR, 'Call to timeGetDevCaps failed'); FResolution := FTimeCaps.wPeriodMin; FResult := timeBeginPeriod(FResolution); Assert(FResult=TIMERR_NOERROR, 'Call to timeBeginPeriod failed'); end; function TMMOneShotTimer.MMOneShotCallback(const Interval: Cardinal; UserData: Pointer; Callback: TOneShotCallbackEvent): Boolean; var pdata: POneShotCallbackData; begin GetMem(pdata, SizeOf(TOneShotCallbackData)); pdata.Callback := Callback; pdata.UserData := UserData; result := (0 <> timeSetEvent(Interval, FResolution, @OneShotCallback, DWord(pdata), TIME_ONESHOT)); if not result then FreeMemory(pdata); end; end.
Lars frische
source share