SetTimer generate a random IDEvent

2019-07-20 21:59发布

问题:

When I try to use the Windows SetTimer function, it generate a IDEvent for the timer even if I have specified one!

This:

SetTimer(0,999,10000,@timerproc); 

In:

procedure timerproc(hwnd: HWND; uMsg: UINT; idEvent: UINT_PTR;dwTime: DWORD); stdcall;
begin
KillTimer(0, idEvent);
showmessage(inttostr(idevent));
end;

Return:

Random Number!

Is it possible to manage my timers by myself instead of Windows choosing for me?

Thank you very much!

回答1:

If you want to handle multiple timer events in a single routine, then handle it by specific window rather then by specific routine:

type
  TForm1 = class(TForm)
    procedure FormCreate(Sender: TObject);
  private
    FTimerWindow: HWND;
    procedure TimerProc(var Msg: TMessage);
  end;

...

procedure TForm1.FormCreate(Sender: TObject);
begin
  FTimerWindow := Classes.AllocateHWnd(TimerProc);
  SetTimer(FTimerWindow, 999, 10000, nil);
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
  Classes.DeallocateHWnd(FTimerWindow);
end;

procedure TForm1.TimerProc(var Msg: TMessage);
begin
  if Msg.Msg = WM_TIMER then
    with TWMTimer(Msg) do
      case TimerID of
        999:
          //
      else:
        //
      end;
end;


回答2:

SetTimer will work differently, depending upon whether you are passing a window handle to it or not.

Timer_Indentifier := SetTimer(0, MyIdentifier, Time, @myproc);

In the above instance, Timer_Identifier does NOT equal MyIdentifier.

Timer_Indentifier := SetTimer(handle, MyIdentifier, Time, @myproc);

In the second example, Timer_Identifier = MyIdentifier.

This is because in the second example, your windows loop will need to use "MyIdentifier" to find out which timer is sending a "WM_Timer" message to it.

Using a specific Timer function, with no Window Handle, is different. The short answer is that in your scenario, use the value that Windows gives you.

http://msdn.microsoft.com/en-us/library/windows/desktop/ms644906%28v=vs.85%29.aspx



回答3:

Multimedia Timer solved my problem!

I can pass whatever I want to them with dwUser:)

MMRESULT timeSetEvent(
  UINT uDelay,
  UINT uResolution,
  LPTIMECALLBACK lpTimeProc,
  DWORD_PTR dwUser,
  UINT fuEvent
);

From MSDN : dwUser -> User-supplied callback data.

  • They have a TIME_ONESHOT option which is exactly what I use timers for!