我写了一段代码来了解SetTimer和KillTimer。 我首先在WM_CREATE中设置一个定时器,然后在定时器中写入KillTimer 回调函数,这样计时器只会被调用一次。
我在定时器回调函数中放了一个MessageBox,这样 将弹出一个消息框以指示计时器已被调用。 由于计时器,消息框预计只会弹出一次 MessageBox 调用后将立即被 KillTimer 关闭。
但是,程序没有按预期运行。看来 KillTimer 没有按照指示停止计时器。相反,该程序 不断弹出消息框。
以下是代码:
#include <stdio.h>
#include <windows.h>
VOID CALLBACK timer_proc(HWND hwnd, UINT msg, UINT timer_id, DWORD time)
{
char buf[1024];
sprintf(buf, "TIMER PROC CALLED AT %d, ID %d", time, timer_id);
MessageBoxA(hwnd, buf, "MSGBOX", MB_ICONINFORMATION);
KillTimer(hwnd, timer_id);
}
void wm_paint(HWND hwnd)
{
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hwnd, &ps);
TextOutA(hdc, 20, 20, "Hi?", 3);
EndPaint(hwnd, &ps);
}
LRESULT CALLBACK wndproc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp)
{
switch (msg) {
case WM_CREATE:
SetTimer(hwnd, 1, 500, timer_proc);
return 0;
case WM_PAINT: wm_paint(hwnd); return 0;
case WM_SIZE: return 0;
case WM_DESTROY: PostQuitMessage(0); return 0;
default: return DefWindowProc(hwnd, msg, wp, lp);
}
}
void init_wndclass(WNDCLASS *w, HINSTANCE hinstance, char *class_name)
{
w->style = CS_HREDRAW | CS_VREDRAW;
w->lpfnWndProc = wndproc;
w->cbClsExtra = w->cbWndExtra = 0;
w->hInstance = hinstance;
w->hIcon = LoadIcon(NULL, IDI_APPLICATION);
w->hCursor = LoadCursor(NULL, IDC_ARROW);
w->hbrBackground = GetStockObject(WHITE_BRUSH);
w->lpszMenuName = NULL;
w->lpszClassName = class_name;
}
HWND create_window(HINSTANCE hinstance)
{
WNDCLASS wndclass;
char *class_name = "main window class";
init_wndclass(&wndclass, hinstance, class_name);
RegisterClass(&wndclass);
return CreateWindowA(class_name, "TIMER TEST", WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT, // position
CW_USEDEFAULT, CW_USEDEFAULT, // window size
NULL, /* owner window */ NULL, /* menu */
hinstance, NULL /* window-creation data */);
}
int WINAPI WinMain(HINSTANCE hinstance, HINSTANCE prev, PSTR cmdline,
int cmdshow)
{
HWND hwnd = create_window(hinstance);
ShowWindow(hwnd, cmdshow);
UpdateWindow(hwnd);
MSG msg;
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
MessageBox()
运行自己的内部消息循环。在您关闭其对话框之前,它将继续为调用线程接收和分派窗口消息,包括计时器消息。您需要使用不同的方法向用户报告计时器事件。例如在 UI 上显示文本,或使用 OutputDebugString()
登录到调试器或 DebugView 应用程序等。