Click here to Skip to main content
13,345,867 members (52,041 online)
Click here to Skip to main content
Add your own
alternative version


24 bookmarked
Posted 1 Dec 2003

Win 32 API Timers for .NET

, 1 Dec 2003
Rate this:
Please Sign up or sign in to vote.
This article describes how to work with timers provided by win32 API


Not long time ago, I was programming an application for Windows that every certain time had to execute a task; in the development of the project everything went with normality but arrived the day to prove the program in the definitive machines where it had to remain working, and we observed that once in a while timers stopped working. We did thousand verifications always reaching the same result, sometimes, timers provided by the Framework don't tick, no events fired. It was then when we began to look for a solution to replace these timers and the solution that seemed better to me was the one to replace them by timers of the API of Windows. We looked on the Internet in case somebody had had the same idea that I had, without success, and therefore put hands to the work.


The Win32 API has some system calls to make it possible, the first is SetTimer, used to init a timer and the second is KillTimer, used to kill or stop a timer. Here is a description of these system calls.


The SetTimer function creates a timer with the specified time-out value.

UINT_PTR SetTimer( 
  HWND hWnd, // handle to window 
  UINT_PTR nIDEvent, // timer identifier 
  UINT uElapse, // time-out value 
  TIMERPROC lpTimerFunc // timer procedure 



[in] Handle to the window to be associated with the timer. This window must be owned by the calling thread. If this parameter is NULL, no window is associated with the timer and the nIDEvent parameter is ignored.


[in] Specifies a nonzero timer identifier. If the hWnd parameter is NULL, this parameter is ignored.

If the hWnd parameter is not NULL and the window specified by hWnd already has a timer with the value nIDEvent, then the existing timer is replaced by the new timer. When SetTimer replaces a timer, the timer is reset. Therefore, a message will be sent after the current time-out value elapses, but the previously set time-out value is ignored.


[in] Specifies the time-out value, in milliseconds.


[in] Pointer to the function to be notified when the time-out value elapses. For more information about the function, see TimerProc.

If lpTimerFunc is NULL, the system posts a WM_TIMER message to the application queue. The hwnd member of the message's MSG structure contains the value of the hWnd parameter.

Return Values

If the function succeeds and the hWnd parameter is NULL, the return value is an integer identifying the new timer. An application can pass this value to the KillTimer function to destroy the timer.

If the function succeeds and the hWnd parameter is not NULL, then the return value is a nonzero integer. An application can pass the value of the nIDTimer parameter to the KillTimer function to destroy the timer.

If the function fails to create a timer, the return value is zero. To get extended error information, call GetLastError.


An application can process WM_TIMER messages by including a WM_TIMER case statement in the window procedure or by specifying a TimerProc callback function when creating the timer. When you specify a TimerProc callback function, the default window procedure calls the callback function when it processes WM_TIMER. Therefore, you need to dispatch messages in the calling thread, even when you use TimerProc instead of processing WM_TIMER.

The wParam parameter of the WM_TIMER message contains the value of the nIDEvent parameter.

The timer identifier, nIDEvent, is specific to the associated windows. Another window can have its own timer which has the same identifier as a timer owned by another window. The timers are distinct.


The KillTimer function destroys the specified timer.

BOOL KillTimer(
  HWND hWnd, // handle to window
  UINT_PTR uIDEvent // timer identifier



[in] Handle to the window associated with the specified timer. This value must be the same as the hWnd value passed to the SetTimer function that created the timer.


[in] Specifies the timer to be destroyed. If the window handle passed to SetTimer is valid, this parameter must be the same as the uIDEvent value passed to SetTimer. If the application calls SetTimer with hWnd set to NULL, this parameter must be the timer identifier returned by SetTimer.

Return Values

If the function succeeds, the return value is nonzero.

If the function fails, the return value is zero. To get extended error information, call GetLastError.


The KillTimer function does not remove WM_TIMER messages already posted to the message queue.


The TimerProc function is an application-defined callback function that processes WM_TIMER messages. The TIMERPROC type defines a pointer to this callback function. TimerProc is a placeholder for the application-defined function name.

  HWND hwnd, // handle to window
  UINT uMsg, // WM_TIMER message
  UINT_PTR idEvent, // timer identifier
  DWORD dwTime // current system time



[in] Handle to the window associated with the timer.


[in] Specifies the WM_TIMER message.


[in] Specifies the timer's identifier.


[in] Specifies the number of milliseconds that have elapsed since the system was started. This is the value returned by the GetTickCount function.

Return Values

This function does not return a value.

Using the code

Common system calls :-

public const int WM_TIMER = 0x113;
// Constant to identify System.Windows.Forms.Message 
// in WndProc is a timer Message
// Init Timer
private static extern int SetTimer(IntPtr hwnd, int nIDEvent, 
    int uElapse, TimerProc CB); 
// Kill Timer
private static extern int KillTimer(IntPtr hwnd, int nIDEvent);

CallBack Timers

We needed an appropriate function callback to the call of API and a procedure to which to do callback, also we must keep the identifier from timer for being able to kill it in the future.

private delegate void TimerProc(IntPtr hWnd, uint nMsg, 
    int nIDEvent, int dwTime); 
private TimerProc Cb = new TimerProc(this.OnTickTimer); 
private int ID_CB_Timer = 0; // Callback timer identifier

// Start Callback 
// Save timer identifier 
this.ID_CB_Timer = SetTimer(IntPtr.Zero, 0, 
    (int)this.numericUpDown2.Value, Cb); 

// Send to form info about timer 
this.statusBar1.Text = "CalBack " + this.ID_CB_Timer.ToString(); 
this.label7.Text = this.ID_CB_Timer.ToString(); 
// Stop timer 
Int rs = KillTimer(IntPtr.Zero,this.ID_CB_Timer); 

If we obtain a Non-zero value when stop timer, an error occurred, we can obtain info about error calling GetLastError() system call.

When the tick occurs, she only add '1' to a counter of ticks and displays the number of ticks in form.

// On Tick Timer 
// Received Ticks via callback 
private void OnTickTimer(IntPtr hWnd, uint nMsg, int nIDEvent, 
  int dwTime) 
  // Count ticks 
  this.label5.Text = this.Cnt_CB_Timer.ToString(); 

TimerProc Timers

We don't need a callback, ticks are received on TimerProc Form's function.

private int ID_WN_Timer; // Timer's identifier
// Start Timer WndProc 
// Save the timer id in ID_WN_Timer 
this.ID_WN_Timer = SetTimer(this.Handle,5000,
// Send the info about the new timer to the form 
this.statusBar1.Text = "WndProc " + this.ID_WN_Timer.ToString(); 
this.label8.Text = this.ID_WN_Timer.ToString();
// Stop WndProc 
this.Cnt_WN_Timer = 0; 
this.label6.Text = "0"; 
int rs = 0; 
rs = KillTimer(this.Handle,this.ID_WN_Timer); 
if (rs == 0) 
  // Error killing timer 
  this.statusBar1.Text = "Error Kill Timer WndProc " + 
    rs.ToString() + " Timer id [" + this.ID_WN_Timer.ToString() + ']'; 
  // Here we could search with GetLastError what is the 
  // cause the timer does not stop ticking 
this.statusBar1.Text = "Kill Timer WndProc " + rs.ToString(); 

If we obtain a Non-zero value when stop timer, an error occurred, we can obtain info about error calling GetLastError() system call.

When the tick occurs, she only add '1' to a counter of ticks and displays the number of ticks in form.

// On Tick Timer
protected override void WndProc( ref System.Windows.Forms.Message m ) 
  #region Switch system messages 
    switch (m.Msg) 
      case (int)WM_TIMER: 
        this.label6.Text = this.Cnt_WN_Timer.ToString(); 
        base.WndProc(ref m); 
  catch (Exception ex) 
    this.statusBar1.Text = ex.Message; 


Ok, that’s all, I expect on this, my first article submitted to Codeproject it will help to someone. Thanks to all for the dozens of articles that I’ve read here. I'll never edit again any HTML page with Visual Studio - there is intelligent life on it!

Points of Interest

Refer Microsoft MSDN for related topics.


  • 1.0 Initial Release


This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


About the Author

Web Developer
Spain Spain
I'm a System engineer which is programming in C# actually.

You may also be interested in...

Comments and Discussions

Generalreal time timers Pin
Milos-Soucek16-Oct-06 7:55
memberMilos-Soucek16-Oct-06 7:55 
GeneralWinService Pin
octamxHot21-Jun-05 14:54
memberoctamxHot21-Jun-05 14:54 
GeneralSomething I don't understand.... Pin
sagmam27-Dec-04 9:02
membersagmam27-Dec-04 9:02 
GeneralBe careful with GetLastError Pin
Richard Poole15-Sep-04 2:31
memberRichard Poole15-Sep-04 2:31 
GeneralHELP! convert string to Intptr using ASP.Net ERROR Pin
gin_blossoms5-Jan-04 23:19
membergin_blossoms5-Jan-04 23:19 
Questionwhat does "Form.Handle" do? Pin
gin_blossoms30-Dec-03 0:53
membergin_blossoms30-Dec-03 0:53 
AnswerRe: what does "Form.Handle" do? Pin
jan larsen30-Dec-03 1:44
memberjan larsen30-Dec-03 1:44 
GeneralRe: what does "Form.Handle" do? Pin
gin_blossoms30-Dec-03 8:05
membergin_blossoms30-Dec-03 8:05 
GeneralRe: what does "Form.Handle" do? Pin
jan larsen4-Jan-04 21:54
memberjan larsen4-Jan-04 21:54 
I haven't really dug very deep into the web framework in .NET, so I cant dismiss the probability of a workaround. But there aren't really any window instance required to run a web app, and my, admittedly very brief, search for any members looking vaguely like a window handle didn't turn successfull.
So based on my findings, or rather the lack of those, I would say that web pages doesn't have any access, directly or otherwise, to a window handle.

It shouldn't be impossible to launch a window from a webapp, but I doubt it would be possible using the .NET framework itself. I mean, to create windows using the Win32 API, you have to have an instance handle for the application, and I don't believe I have seen any reference to such a member in the classes I looked in.

"After all it's just text at the end of the day. - Colin Davies

"For example, when a VB programmer comes to my house, they may say 'does your pool need cleaning, sir ?' " - Christian Graus
GeneralRe: what does "Form.Handle" do? Pin
jan larsen5-Jan-04 21:58
memberjan larsen5-Jan-04 21:58 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Permalink | Advertise | Privacy | Terms of Use | Mobile
Web04 | 2.8.180111.1 | Last Updated 2 Dec 2003
Article Copyright 2003 by toclipa
Everything else Copyright © CodeProject, 1999-2018
Layout: fixed | fluid