Timer Events

Timer events are used in an application for various requirements. An application might implement stopwatch-type actions, it can monitor or wait for some asynchronous event, showing a countdown to the user, application timeout events, or numerous other requirements where the programmer needs to implement a timer mechanism in the program.

Timer events are handled by Win32 framework and the core of the Windows operating system. An application can register one or more timer events with corresponding timer identities. The Operating system periodically calls the timer event as per the interval given. This is handled in the task manager part of the kernel.

Timer handling APIs

SetTimer() is the Win32 function to register a timer event and KillTimer() can be used to stop that timer. Application written in MFC & C++ can use CWnd::SetTimer() and CWnd::KillTimer() member functions of CWnd class.

SetTimer() API can be called with proper argument to set a timer routine with defined time interval. There are two possible way to set a timer for an application.

  • Set an event identifier associated with a window handle. This will set a timer to be called by posting a WM_TIMER event to the window procedure WndProc().
  • Set a timer call back function TimerProc() with an event id. Timer call back will be fired with specified time interval.

SetTimer

The SetTimer function creates a timer (repetitive call back) with the specified time interval value.

UINT SetTimer(
  HWND hWnd,
  UINT nIDEvent,
  UINT uElapse, 
  TIMERPROC lpTimerFunc 
);

Parameters

  • hWnd - 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.
  • nIDEvent - Specifies a nonzero timer identifier. If the hWnd parameter is NULL, this parameter is ignored.
  • uElapse - Specifies the time-out value, in milliseconds.
  • lpTimerFunc - 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, the return value is an integer identifying the new timer. An application can pass this value, or the string identifier, if it exists, to the KillTimer function to destroy the timer.
If the function fails to create a timer, the return value is zero.

TimerProc callback function

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.

Syntax

VOID CALLBACK TimerProc(HWND hwnd, UINT uMsg, UINT idEvent,  DWORD dwTime);

Parameters

  • hwnd - A handle to the window associated with the timer.
  • uMsg - The WM_TIMER message.
  • idEvent - The timer's identifier.
  • dwTime - The number of milliseconds that have elapsed since the system was started. This is the value returned by the GetTickCount function.

Return value

This function does not return a value.

KillTimer

Destroys the specified timer.

Syntax

BOOL WINAPI KillTimer(HWND hWnd, UINT uIDEvent);

Parameters

  • hWnd - A 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.
  • uIDEvent - The timer to be destroyed. If the window handle passed to SetTimer is valid, this parameter must be the same as the nIDEvent 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 value

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.

Sample demo

Below is a small demo application to show the utility of SetTimer() and KillTimer(). This application creates a top level window. On clicking left mouse button it sets the timer and on clicking right button it kills the timer. In timer event we are taking latest time from system and display it in the title bar. The timer has a value of one second interval thus it updates like a clock. This program uses a timer proc by default when USE_TIMER_PROC macro is defined. Otherwise it uses normal windowproc and WM_TIMER message.

#include <windows.h>
#include <time.h>

#define USE_TIMER_PROC

#define MY_TIMERID1 100
#define MY_TIMERID2 101

#ifdef USE_TIMER_PROC
VOID __stdcall MyTimerProc(HWND hWnd, UINT uMsg, UINT idEvent, DWORD dwTime)
{
  time_t rawtime;
  struct tm * timeinfo;
  char buffer [80];
  if (WM_TIMER == uMsg) {
    if(idEvent == MY_TIMERID2) {
      time (&rawtime);
      timeinfo = localtime (&rawtime);
      strftime (buffer,80,"Now time is %I:%M:%S%p.",timeinfo);
      SetWindowText(hWnd, buffer);
    }
  }
}
#endif
LRESULT CALLBACK WndProc(HWND hWnd,
                         UINT message, 
                         WPARAM wParam,
                         LPARAM lParam);

int APIENTRY WinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPSTR     lpCmdLine,
                     int       nCmdShow)
{
  WNDCLASS wc;
  MSG msg;
  HWND hWnd;
  ZeroMemory(&wc, sizeof(WNDCLASS));

  wc.style           = CS_HREDRAW | CS_VREDRAW;
  wc.lpfnWndProc     = (WNDPROC)WndProc;
  wc.hInstance       = hInstance;
  wc.hCursor         = LoadCursor(NULL, IDC_ARROW);
  wc.hbrBackground   = (HBRUSH)(COLOR_BACKGROUND);
  wc.lpszClassName   = (LPCTSTR)"TimerDemoClass";
  RegisterClass(&wc);

   hWnd = CreateWindow("TimerDemoClass", "SetTimer/KillTimer Demo",WS_OVERLAPPEDWINDOW,
      CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);

  ShowWindow(hWnd, nCmdShow);
  UpdateWindow(hWnd);
  while (GetMessage(&msg, NULL, 0, 0)) 
  {
    DispatchMessage(&msg);
  }
  return 0;
}

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
  time_t rawtime;
  struct tm * timeinfo;
  char buffer [80];
  switch (message) 
  {
#ifndef USE_TIMER_PROC
    case WM_TIMER:
      if(wParam == MY_TIMERID1) {
        time (&rawtime);
        timeinfo = localtime (&rawtime);
        strftime (buffer,80,"Now time is %I:%M:%S%p.",timeinfo);
        SetWindowText(hWnd, buffer);
      }
      break;
    case WM_LBUTTONDOWN:
      SetTimer(hWnd, MY_TIMERID1, 1000, NULL);
      break;
    case WM_RBUTTONDOWN:
      KillTimer(hWnd, MY_TIMERID1);
      break;
#else
    case WM_LBUTTONDOWN:
      SetTimer(hWnd, MY_TIMERID2, 1000, MyTimerProc);
      break;
    case WM_RBUTTONDOWN:
      KillTimer(hWnd, MY_TIMERID2);
      break;
#endif
    case WM_DESTROY:
      PostQuitMessage(0);
      break;
    default:
      return DefWindowProc(hWnd, message, wParam, lParam);
   }
   return 0;
}

Output

SetTimer/KillTimer example demo application

About our authors: Team EQA

Further readings

Where is WinMain() function in MFC application ?

MFC hides WinMain in its framework and includes source file on WinMain(). This explains how framework calls global CWinApp::Initinstance() from entry WinMain.

What is the utility of CWinApp class?

This is constructed during global C++ objects are constructed and is already available when Windows calls the WinMain function, which is supplied by the ...

Basic steps in Win32 GUI Application with source code.

Define a custom Window class structure, Register the class name, CreateWindow, Show windows and write message get and dispatch loop statements. Define the Window CallBack procedure and write the handlers.

What is a Window CallBack procedure and what is its utility?

DispatchMessage() is a API which indirectly triggers the Window CallBack procedure. Message structure members from this function are passed to the CallBack procedure. CallBack procedure should implement event handlers depending on the need of the application.

What are LPARAM and WPARAM in window proc function?

LPARAM and WPARAM are the two parameters in Window CallBack procedure. They signifies parameters of various events. They are used in handing individual events.

What are the basic steps of a typical MFC based application?

We need to write WinMain and need to follow all these in a Win32 application. However we need not to write much if we are writing an application with MFC ...

#