Solved

Win32 Timers

Posted on 1998-10-20
6
337 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
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 4
  • 2
6 Comments
 

Accepted Solution

by:
msac_m earned 70 total points
ID: 1343530
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
ID: 1343531
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
ID: 1343532
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
Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 

Expert Comment

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


0
 

Expert Comment

by:msac_m
ID: 1343534
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
ID: 1343535
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

Free Tool: ZipGrep

ZipGrep is a utility that can list and search zip (.war, .ear, .jar, etc) archives for text patterns, without the need to extract the archive's contents.

One of a set of tools we're offering as a way to say thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

This article explains how to create forms/units independent of other forms/units object names in a delphi project. Have you ever created a form for user input in a Delphi project and then had the need to have that same form in a other Delphi proj…
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…
With Secure Portal Encryption, the recipient is sent a link to their email address directing them to the email laundry delivery page. From there, the recipient will be required to enter a user name and password to enter the page. Once the recipient …
A short tutorial showing how to set up an email signature in Outlook on the Web (previously known as OWA). For free email signatures designs, visit https://www.mail-signatures.com/articles/signature-templates/?sts=6651 If you want to manage em…

739 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