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

What is WinMain function in windows C? Main vs WinMain, WinMain prototype and arguments.
Describes What is WinMain()? Entry point funtion in Windows exe. Function prototype. Implementation, Command line argument passing. Show Window flag.

Steps to write a basic window program with C and Win32 APIs.
Include windows.h, Define WinMain, Define WNDCLASS attributes, RegisterClass, CreateWindow, ShowWindow, UpdateWindow, GetMessage, DispatchMessage, DefWindowProc

What are LPARAM and WPARAM in window proc function ? How Win32 subsystem pass parameters to this function?
Explains the parameters WPARAM and LPARAM and in window procedure function. What is this W and L stands for? How Win32 subsystem pass parameters?

What is WM_PAINT event ? When does Win32 subsystem call WM_PAINT event?
All you wanted to know Drawing in Windows, Paint Event WM_PAINT, Device Context, BeginPaint EndPaint GDI Objects, Pen, Brush, Font, Bitmap, Palette, Region.

#