在DOS操作系统中要用到定时器功能的时候一般有两种方法:一是用一个空循环来延时;一是截获时钟中断,计算机的硬件时钟中断会以每55ms一次的频率触发8号中断,而在默认的int 08h中断处理程序中有一句int 1ch的代码,所以截获int 08h和int 1ch都可以达到定时的要求。
而在Windows操作系统中,用户程序不可能去截获时钟中断,而是使用定时器功能。

在应用程序中需要使用定时器时,可以用SetTimer函数向Windows申请一个定时器,要求系统在指定时间以后“通知”应用程序,如果申请成功,系统会以指定时间周期调用SetTimer函数指定的回调函数,或者向指定的窗口过程发送WM_TIMER消息,SetTimer函数可以指定的时间间隔以ms为单位,可以指定的时间周期为一个32位的整数,也就是从1~4294967295ms,(即232-1ms),这是一个将近50天的范围。
但在实际应用中,由于Windows的定时器是基于时钟中断的,所以虽然参数的单位ms,但精度是55ms,如果指定一个小于55ms的周期,Windows最快也只能在每个时钟中断的时候触发这个定时器,即实际上这个定时器是以55ms为触发周期的;另外,指定一个时间间隔时,Windows以与这个间隔最接近的55ms的整数倍时间来触发定时器。

由于定时器消息是一个低级别的消息,这表现在两方面:
1)Windows只有在消息队列中没有其他消息的情况下才会发送WM_TIMER消息,如果窗口过程忙于处理这个消息没有返回,使消息队列中有消息积累起来,那么WM_TIMER消息就会被丢弃,在消息队列空闲时,被丢弃的WM_TIMER消息不会补发;
2)消息队列中不会有多条WM_TIMER消息,如果消息队列中已经有一条WM_TIMER消息,还没来得及处理,又到了定时时刻,那么两条WM_TIMER消息会被合并成一条。
因此,应用程序不能依靠定时器来保证某件事情必须在规定的时刻被处理,另外,也不能依赖对定时器消息计数来确定已经过去了多长时间。

申请一个定时器使用SetTimer函数:
UINT_PTR WINAPI SetTimer(
__in_opt HWND hWnd, //WM_TIMER消息发往的窗口句柄
__in UINT_PTR nIDEvent, //用户指定的任意整数,用来标识一个程序中的多个定时器
__in UINT uElapse, //时间周期,以ms为单位
__in_opt TIMERPROC lpTimerFunc //定时器过程
);
如果定时器创建成功,返回的是定时器的标识符。
当在SetTimer中指定的定时器标识已经存在,则Windows会用新的参数代替旧的定时器参数,函数执行后,这个标识的定时器消息将以新的时间周期发送。

定时器过程定义如下:
VOID CALLBACK TimerProc(
__in HWND hwnd, //与定时器关联的窗口句柄
__in UINT uMsg, //总是WM_TIMER
__in UINT_PTR idEvent, //SetTimer返回的定时器标识符
__in DWORD dwTime //系统启动至今经过的ms数,该值是由函数GetTickCount返回的
);

撤销定时器的函数是KillTimer:
BOOL WINAPI KillTimer(
__in_opt HWND hWnd, // WM_TIMER消息发往的窗口句柄
__in UINT_PTR uIDEvent //用户指定的任意整数,用来标识一个程序中的多个定时器
);

使用SetTimer函数的方法有两种:
1)要求Windows将WM_TIMER消息发往指定的窗口过程,这时lpTimerProc必须为NULL;
例如如下:
HICON hIcon1; // icon handle
POINT ptOld; // previous cursor location
UINT uResult; // SetTimer's return value
HINSTANCE hinstance; // handle to current instance

//
// Perform application initialization here.
//

wc.hIcon = LoadIcon(hinstance, MAKEINTRESOURCE(400));
wc.hCursor = LoadCursor(hinstance, MAKEINTRESOURCE(200));

// Record the initial cursor position.

GetCursorPos(&ptOld);

// Set the timer for the mousetrap.

uResult = SetTimer(hwnd, // handle to main window
IDT_MOUSETRAP, // timer identifier
10000, // 10-second interval
(TIMERPROC) NULL); // no timer callback

if (uResult == 0)
{
ErrorHandler("No timer is available.");
}

LONG APIENTRY MainWndProc(
HWND hwnd, // handle to main window
UINT message, // type of message
WPARAM wParam, // additional information
LPARAM lParam) // additional information
{

HDC hdc; // handle to device context
POINT pt; // current cursor location
RECT rc; // location of minimized window

switch (message)
{
//
// Process other messages.
//

case WM_TIMER:
// If the window is minimized, compare the current
// cursor position with the one from 10 seconds
// earlier. If the cursor position has not changed,
// move the cursor to the icon.

if (IsIconic(hwnd))
{
GetCursorPos(&pt);

if ((pt.x == ptOld.x) && (pt.y == ptOld.y))
{
GetWindowRect(hwnd, &rc);
SetCursorPos(rc.left, rc.top);
}
else
{
ptOld.x = pt.x;
ptOld.y = pt.y;
}
}

return 0;

case WM_DESTROY:

// Destroy the timer.

KillTimer(hwnd, IDT_MOUSETRAP);
PostQuitMessage(0);
break;

//
// Process other messages.
//

}

2)要求Windows在时间到的时候调用指定的定时器过程,而不是窗口过程,那么只需要指定lpTimerFunc参数即可。
例子如下:
UINT uResult; // SetTimer's return value
HICON hIcon1; // icon handle
POINT ptOld; // previous cursor location
HINSTANCE hinstance; // handle to current instance

//
// Perform application initialization here.
//

wc.hIcon = LoadIcon(hinstance, MAKEINTRESOURCE(400));
wc.hCursor = LoadCursor(hinstance, MAKEINTRESOURCE(200));

// Record the current cursor position.

GetCursorPos(&ptOld);

// Set the timer for the mousetrap.

uResult = SetTimer(hwnd, // handle to main window
IDT_MOUSETRAP, // timer identifier
10000, // 10-second interval
(TIMERPROC) MyTimerProc); // timer callback

if (uResult == 0)
{
ErrorHandler("No timer is available.");
}

LONG APIENTRY MainWndProc(
HWND hwnd, // handle to main window
UINT message, // type of message
WPARAM wParam, // additional information
LPARAM lParam) // additional information
{

HDC hdc; // handle to device context

switch (message)
{
//
// Process other messages.
//

case WM_DESTROY:
// Destroy the timer.

KillTimer(hwnd, IDT_MOUSETRAP);
PostQuitMessage(0);
break;

//
// Process other messages.
//

}

// MyTimerProc is an application-defined callback function that
// processes WM_TIMER messages.

VOID CALLBACK MyTimerProc(
HWND hwnd, // handle to window for timer messages
UINT message, // WM_TIMER message
UINT idTimer, // timer identifier
DWORD dwTime) // current system time
{

RECT rc;
POINT pt;

// If the window is minimized, compare the current
// cursor position with the one from 10 seconds earlier.
// If the cursor position has not changed, move the
// cursor to the icon.

if (IsIconic(hwnd))
{
GetCursorPos(&pt);

if ((pt.x == ptOld.x) && (pt.y == ptOld.y))
{
GetWindowRect(hwnd, &rc);
SetCursorPos(rc.left, rc.top);
}
else
{
ptOld.x = pt.x;
ptOld.y = pt.y;
}
}
}