Solved

Win32 Timers

Posted on 1998-10-20
6
329 Views
Last Modified: 2010-04-06
I am programming a DirectX game in Delphi 2.0, and I want to have a timer fire off messages about 50 times a second so I can update the display and game variables. I tried the TTimer component that comes with Delphi, but the display kept "shaking" and I don't like this. Is it possible that I can utilize the timers in the Windows API? If so, how can I do this? Say I want Form1.OnUpdate to recieve the messages. How can I specify this in the Win32 SetTimer() function? Please include code samples that show me how to put this into my Delphi application.
0
Comment
Question by:mmarvi
  • 4
  • 2
6 Comments
 

Accepted Solution

by:
msac_m earned 70 total points
Comment Utility
Hi mmarvi,

   I am pasting my Unit,;

//MY UNIT BEGINS//
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls;

type
  TForm1 = class(TForm)
    Label1: TLabel;
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }

    procedure MyMessageHandler(Var Msg: TMessage);message WM_TIMER;
    procedure MyOnUpDate;
  end;

var
  Form1: TForm1;
  MyTimerID: UINT ;
  nIDEvent: UINT = 1;
  Count: Integer;
implementation

{$R *.DFM}
procedure TForm1.MyOnUpDate;
Begin
     Inc(Count);
     Label1.Caption:= IntToStr(Count);
End;
procedure TForm1.MyMessageHandler;
Begin
     MyOnUpDate;
End;

procedure TForm1.FormCreate(Sender: TObject);
begin
Count:= 0;
MyTimerID:= SetTimer(
    Form1.Handle,      // handle of window for timer messages
    nIDEvent,      // timer identifier
    5000,      // time-out value 5secs
    Pointer(0)       // address of timer procedure
   );
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
    if(not KillTimer(
    Form1.Handle,      // handle of window that installed timer
    MyTimerID       // timer identifier
   )) Then ShowMessage('ERROR');


end;

end.
//END OF THE UNIT//

  Hope this helps,

msac_m
0
 

Author Comment

by:mmarvi
Comment Utility
Dear msac_m:

I tried putting your code into my game, and when it compiled, there was a "not enough actual parameters" error on the line in Form1.OnCreate where you called SetTimer. Also, what should I enter for the fourth parameter of SetTimer? Do you have any code samples?
0
 

Author Comment

by:mmarvi
Comment Utility
Dear msac_m:

I corrected the "not enough actual parameters" problem, and I got the code to compile. However, I encountered a runtime exception when I ran the program. I pasted the example unit's code below, perhaps you can help me.

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls;

type
  TForm1 = class(TForm)
    Label1: TLabel;
    procedure OnStart(Sender: TObject);
  private
    { Private declarations }
    Flag1: Integer;
    TimerID: UINT;
    procedure OnUpdateGame(Var Msg: TMessage);message WM_TIMER;
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.DFM}

procedure TForm1.OnStart(Sender: TObject);
begin
     TimerID := SetTimer(Form1.Handle, 1, 20, @TForm1.OnUpdateGame);
     Flag1 := 0;
end;

procedure TForm1.OnUpdateGame;
begin
     Inc(Flag1);
     Label1.Caption := IntToStr(Flag1);
end;

end.

// END OF UNIT

Thanks!

mmarvi
0
What Is Threat Intelligence?

Threat intelligence is often discussed, but rarely understood. Starting with a precise definition, along with clear business goals, is essential.

 

Expert Comment

by:msac_m
Comment Utility
SOORY FOR BEING LATE, I WILL LOOK INTO YOUR CODE TODAY.


0
 

Expert Comment

by:msac_m
Comment Utility
Hi  mmarvi,


First The Settimer function is defined as below;

UINT SetTimer(

    HWND hWnd,      // handle of window for timer messages
    UINT nIDEvent,      // timer identifier
    UINT uElapse,      // time-out value
    TIMERPROC lpTimerFunc       // address of timer procedure
   );      

As you see the last parameter of the function is of type
 TIMERPROC which defined as;

VOID CALLBACK TimerProc(

    HWND hwnd,      // handle of window for timer messages
    UINT uMsg,      // WM_TIMER message
    UINT idEvent,      // timer identifier
    DWORD dwTime       // current system time
   );

So in the SetTimer if you do not specify a TIMERPROC callback function
the window that you specified in the SetTimer (the first parameter) gets the
WM_TIMER messages. And when the window gets this message, you can do the things that
you want to. This is the way that I followed in the code snippet that I sent to you.
If you looked at my code you will see that, I used the SetTimer as;

MyTimerID:= SetTimer(
    Form1.Handle,      // handle of window for timer messages
    nIDEvent,      // timer identifier
    5000,      // time-out value 5secs
    Pointer(0)       // address of timer procedure
   );

The first parameter is the handle of the window which will get the WM_TIMER message.
The last one means that I have no callback function, because I want to handle the
timer events in my MyMessageHandler function.

The thing that is wrong in your code is the TIMERPROC function which you defined as
TForm1.OnUpdateGame(Var Msg: TMessage); Because this method is completely different
from the TIMERPROC callback function definition. (See above the TIMERPROC function definition.)
1- First according to the definition above the function must have 4 parameters
2- This function must use stdcall calling convention (Because Win32 uses stdcall as default
where Delphi uses fastcall which can cause conflicts.)
3- And the your OnUpdateGame is a method which is not a simple procedure. As you know methods
differ from procedure or functions. They always have one hidden parameter to indicate the current
object instance which is called as Self.


  So if you want to use callback function you must supply a valid function which obeys  the rules listed above.
But instead of using callback function I recommend you use the form to handle the WM_TIMER message.

As a last comment, I will re-execute my previous code snippet and  post it to you.


Best Regards.




0
 

Expert Comment

by:msac_m
Comment Utility
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls;

type
  TForm1 = class(TForm)
    Label1: TLabel;
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }

    procedure MyMessageHandler(Var Msg: TMessage);message WM_TIMER;
    Class Procedure MyTimerProc(
    Myhwnd: HWND  ;      // handle of window for timer messages
    MyMsg: UINT  ;      // WM_TIMER message
    MyidEvent: UINT ;      // timer identifier
    MydwTime: DWORD         // current system time
   );stdcall;
  end;

var
  Form1: TForm1;
  MyTimerID: UINT ;
  nIDEvent: UINT = 1;
  Count: Integer;
implementation

{$R *.DFM}

Class Procedure TForm1.MyTimerProc(
    Myhwnd: HWND  ;      // handle of window for timer messages
    MyMsg: UINT  ;      // WM_TIMER message
    MyidEvent: UINT ;      // timer identifier
    MydwTime: DWORD         // current system time
   );stdcall;
Begin
     Inc(Count);
     Form1.Label1.Caption:= IntToStr(Count);
     Application.ProcessMessages;
     // Add Your Code Here.
      
End;

procedure TForm1.MyMessageHandler;
Begin
     Inc(Count);
     Label1.Caption:= IntToStr(Count);
     Application.ProcessMessages;
End;

procedure TForm1.FormCreate(Sender: TObject);
begin
Count:= 0;
MyTimerID:= SetTimer(
    Form1.Handle,      // handle of window for timer messages
    nIDEvent,      // timer identifier
    20,      // time-out value
    @TForm1.MyTimerProc       // address of timer procedure
   );


end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
    if(not KillTimer(
    Form1.Handle,      // handle of window that installed timer
    MyTimerID       // timer identifier
   )) Then ShowMessage('ERROR');
end;

end.

Hi again,

  First I checked my previous code and it worked.
But I added  TForm1.MyTimerProc to the program which is the
callback function, if you notice it is defined as class procedure and
stdcall convention is used.
PS: in the settimer function
 if you make the last parameter Pointer(0) then
 MyMessageHandler will be called or if you  
 give it as @TForm1.MyTimerProc then the callback function
 will be called.

Regards,


 



0

Featured Post

Top 6 Sources for Identifying Threat Actor TTPs

Understanding your enemy is essential. These six sources will help you identify the most popular threat actor tactics, techniques, and procedures (TTPs).

Join & Write a Comment

Introduction I have seen many questions in this Delphi topic area where queries in threads are needed or suggested. I know bumped into a similar need. This article will address some of the concepts when dealing with a multithreaded delphi database…
Introduction Raise your hands if you were as upset with FireMonkey as I was when I discovered that there was no TListview.  I use TListView in almost all of my applications I've written, and I was not going to compromise by resorting to TStringGrid…
Internet Business Fax to Email Made Easy - With eFax Corporate (http://www.enterprise.efax.com), you'll receive a dedicated online fax number, which is used the same way as a typical analog fax number. You'll receive secure faxes in your email, fr…
You have products, that come in variants and want to set different prices for them? Watch this micro tutorial that describes how to configure prices for Magento super attributes. Assigning simple products to configurable: We assigned simple products…

772 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

14 Experts available now in Live!

Get 1:1 Help Now