I wrote a code to learn about SetTimer and KillTimer. I firstly set a timer in WM_CREATE, then write KillTimer in the timer callback function so that the timer would be called only once.
I put a MessageBox in the timer callback function, so that a MessageBox would pop up to indicate that the timer is called. The MessageBox is expected to pop up only once, since the timer would be shut down by KillTimer right after the MessageBox call.
However, the program doesn't run as intended. It seems that KillTimer didn't stop the timer as instructed. Instead, the program keeps popping out MessageBoxes.
The following is the code:
#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);
}
}
I wrote a code to learn about SetTimer and KillTimer. I firstly set a timer in WM_CREATE, then write KillTimer in the timer callback function so that the timer would be called only once.
I put a MessageBox in the timer callback function, so that a MessageBox would pop up to indicate that the timer is called. The MessageBox is expected to pop up only once, since the timer would be shut down by KillTimer right after the MessageBox call.
However, the program doesn't run as intended. It seems that KillTimer didn't stop the timer as instructed. Instead, the program keeps popping out MessageBoxes.
The following is the code:
#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);
}
}
Share
Improve this question
asked Nov 17, 2024 at 6:43
Limina102Limina102
1,0877 silver badges25 bronze badges
1
- 5 You are using an application modal dialog box. Until you close it, KillTimer() will not be called since the MessageBox call doesn't return until then. Try moving the KillTimer() call to before displaying the message box. – Avi Berger Commented Nov 17, 2024 at 7:13
1 Answer
Reset to default 2You are not killing the timer until after the message box dialog is closed.
MessageBox()
blocks the calling thread, so your message loop will not be running while the message box dialog is open. To keep the dialog responsive, MessageBox()
runs its own internal message loop. Until you close the dialog, it will continue to receive and dispatch window messages for the calling thread, including timer messages.
To fix this, you need to either:
kill the timer before you display the message box.
Otherwise, use a different method of reporting your timer events to the user that doesn't involve processing window messages. Such as displaying updated text on your UI, or using
OutputDebugString()
to log to your debugger or DebugView app, etc.
发布者:admin,转转请注明出处:http://www.yc00.com/questions/1745636662a4637434.html
评论列表(0条)