As the question subject says. I have a console application in Delphi, which contains a TTimer
variable. The thing I want to do is assign an event handler to TTimer.OnTimer
event. I am totally new to Delphi, I used to use C# and adding the event handlers to events is totally different. I have found out that one does not simply assign a procedure to event as a handler, you have to create a dummy class with a method which will be the handler, and then assign this method to the event. Here is the code I currently have:
program TimerTest;
{$APPTYPE CONSOLE}
uses
SysUtils,
extctrls;
type
TEventHandlers = class
procedure OnTimerTick(Sender : TObject);
end;
var
Timer : TTimer;
EventHandlers : TEventHandlers;
procedure TEventHandlers.OnTimerTick(Sender : TObject);
begin
writeln('Hello from TimerTick event');
end;
var
dummy:string;
begin
EventHandlers := TEventHandlers.Create();
Timer := TTimer.Create(nil);
Timer.Enabled := false;
Timer.Interval := 1000;
Timer.OnTimer := EventHandlers.OnTimerTick;
Timer.Enabled := true;
readln(dummy);
end.
It seems correct to me, but it does not work for some reason.
EDIT
It appears that the TTimer
component won't work because console applications do not have the message loop. Is there a way to create a timer in my application?
Console applications don't have a message pump, but do have threads. If you create a thread that does the work and waits for the next second when the work is done, you should get the result you want. Read the documentation about TThread how to create a dedicated thread. Getting data to and from a thread is less straightforward though. That's why there are a number of alternatives to the 'raw' TThread that help with this, like OmniThreadLibrary.
Your code does not work because
TTimer
component internally usesWM_TIMER
message processing and a console app does not have a message loop. To make your code work you should create a message pumping loop yourself:As others have mentioned, console applications don't have a message pump.
Here is a
TConsoleTimer
thread class which mimics aTTimer
class. The main difference is that the code in the event is executed in theTConsoleTimer
thread.Update
At the end of this post is a way to have this event called in the main thread.
And a test:
As mentioned above, how do I make the event execute in the main thread?
Reading Delphi 7: Handling events in console application (TidIRC) gives the answer.
Add a method in
TConsoleTimer
:and change the call in the
Execute
method to:To pump the synchronized calls, use
CheckSynchronize()
function in Classes unit:Note: the console
KeyPressed
function can be found here:How i can implement a IsKeyPressed function in a delphi console application?.