Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Delphi: OnTimer event of my own Timer never happens

I need a Timer in a 'no form' Delphi unit (there's still a main unit with a form), so I do this:

unit ...

interface

type
  TMyTimer = Class(TTimer)
  public
    procedure OnMyTimer(Sender: TObject);
  end;

var
  MyTimer: TMyTimer;

implementation

procedure TMyTimer.OnMyTimer(Sender: TObject);
begin
  ...
end;

initialization

MyTimer := TMyTimer.Create(nil);
with MyTimer do
begin
  Interval := 1000;
  Enabled := True;
  OnTimer := OnMyTimer;
end;

finalization

FreeAndNil(MyTimer);

The problem is that the OnMyTimer procedure is never run. I'll truly appreciate any ideas as to why :-)

like image 434
Mikhail Avatar asked Apr 14 '10 06:04

Mikhail


3 Answers

In order for a timer to work, your program must process messages. In a GUI program, that part is automatic; the TApplication class provides that for you. But you say you have a "no form" program, so I suppose you're probably not calling Application.Run in your DPR file.

To use a timer, you need to process messages. The typical starting point for a message pump is code like this:

while Integer(GetMessage(Msg, 0, 0, 0)) > 0 do begin
  TranslateMessage(Msg);
  DispatchMessage(Msg);
end;

When a timer's period has elapsed, the OS effectively places a wm_Timer message in your program's message queue. The GetMessage call fetches messages from the queue, and DispatchMessage calls the destination window's window procedure. TTimer creates a hidden window for itself to serve as the target for those messages, and DispatchMessage makes sure they get there.

like image 185
Rob Kennedy Avatar answered Oct 18 '22 23:10

Rob Kennedy


Apart from the fact you created a MyTimer and freed a MouseTimer, I don't see anything wrong with your code (I do assume you use your code in a GUI application or at least are having a message loop)

This code sample works with Delphi 5. The Hello Worldget's written to the eventlog every second.

unit Unit2;

interface

uses
  extctrls;

type
  TMyTimer = Class(TTimer)
  public
    procedure OnMyTimer(Sender: TObject);
  end;

var
  MyTimer: TMyTimer;

implementation

uses
  windows, sysutils, classes;

procedure TMyTimer.OnMyTimer(Sender: TObject);
begin
  OutputDebugString(PChar('Hello World'));
end;

initialization

MyTimer := TMyTimer.Create(nil);
with MyTimer do
begin
  Interval := 1000;
  Enabled := True;
  OnTimer := OnMyTimer;
end;

finalization
  FreeAndNil(MyTimer);

end.
like image 6
Lieven Keersmaekers Avatar answered Oct 19 '22 01:10

Lieven Keersmaekers


Is your unit used by other units or not? If this unit isn't used by others it won't even get in the initialization section. Or maybe the unit is finalized sooner then you think.

Put a breakpoint at the MyTimer := TMyTimer.Create(nil); line and at the FreeAndNil(MyTimer) line and run your application. Make sure that the timer is created when you want it to and not destroyed too early.

like image 1
The_Fox Avatar answered Oct 18 '22 23:10

The_Fox