| Timer without a Window Handle | D2 D3 |
| This small application shows how to use a Windows timer with a callback function. This is useful for applications that do not have a window handle that is handy (i.e. Console mode). | |
|
A Win32 KnowledgeBase article (PSS ID Number: Q102482, "SetTimer() Should Not Be Used in Console Applications") suggests that it is better to use a thread instead of this. If you really want/need to use a timer, it will work on Win95 and NT 4.0, but remember that MS suggests that you not do it, so expect it to break on future versions. You should be able to find the entire KnowledgeBase article at www.microsoft.com/kb/ if you want it. Just search the Windows 32-bit SDK for the PSS ID Number (Q102482). Take special note of the message loop inside the repeat-until block. In theory, you don't need to do this sort of thing under Win32 anymore (had to do it all the time under Win16). It was used under Win16 to prevent apps from hogging the system. What it did was allow message processing to continue when your app was doing something that was going to take a large amount of time. This allowed Windows to give other apps their share of processsing time, which it didn't do if you did not allow messages to be processed. This is often called a secondary message loop because your app always has a main message loop that did this. This sort of thing is not supposed to be needed anymore because of preemptive multitasking, i.e. the system doesn't need you to cooperate by processing messages to give time to other apps any more. Well, turns out that timers have to have message loops to work. From the KnowledgeBase article referenced above: SetTimer() was not designed to be used with a console application because it requires a message loop to dispatch the timer signal to the timer procedure. In a console application, this behavior can be easily emulated with a thread that is set to wait on an event. This only works in Delphi 2, but the basic callback mechanism works under Win16 or Win32.
program ConsoleTest;
{$APPTYPE CONSOLE}
uses Windows, Messages;
var
TimerHandle: UINT;
Counter: integer;
procedure TimerCallBack(Wnd: HWND; Msg, idEvent: UINT; dwTime: DWORD);
stdcall; far; export;
{
Wnd : handle of window for timer messages
Msg : WM_TIMER message
idEvent : timer identifier
dwTime : current system time
}
begin
writeln('callback');
inc(Counter);
end;
var
Msg: TMsg;
begin
writeln('timer callback test');
Counter := 0;
TimerHandle := SetTimer(0, 0, 100, @TimerCallBack);
if TimerHandle <> 0 then begin
repeat
GetMessage(Msg, 0, 0, 0);
DispatchMessage(Msg);
until (Msg.Message = WM_QUIT) or (Counter >= 10);
KillTimer(0, TimerHandle);
end else
writeln('could not create timer');
writeln('timer callback test finished');
end.
|
|