如何在 win32 中使用 sendmessage 发送具有定时器过程的 wm_timer
How do I use sendmessage for sending wm_timer that has timer proc in win32
我有一个计时器,ID 1,它有一个 timerproc 作为回调函数。
我正在 timerproc 中制作其他计时器(ID 2、3、...),它们使用 WM_TIMER
事件,而不是另一个 timerproc。
创建window时,我想立即生成定时器事件,ID 1。
所以我就这样使用了 SendMessage 函数
SendMessage(hWnd, WM_TIMER, 1, (LPARAM)&timerproc);
但是没用。
如何在 window 的第一次正确激活 timerproc?
void CALLBACK MakeRain(HWND hWnd, UINT iMessage, UINT_PTR wParam, DWORD lParam)
{ /* this is timerproc for ID 1 */
if (gRdx >= MAX_WORDS_COUNT) return;
gRain[gRdx].f = 1;
gRain[gRdx].x = rand() % (gRect.right - 30);
gRain[gRdx].y = 10;
int id = RdxToTID(gRdx);
int vel = rand() % 2000 + 1000;
SetTimer(hWnd, id, vel, NULL); /* In here I am making other timers */
gRdx++;
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam)
{
HDC hdc;
PAINTSTRUCT ps;
int tid = wParam;
int rdx = TIDToRdx(tid);
switch (iMessage)
{
case WM_CREATE:
GetClientRect(hWnd, &gRect);
srand((unsigned int)time(NULL));
SetTimer(hWnd, 1, MAKE_RAIN_TERM, MakeRain);
/* my trying, It is not working */
//SendMessage(hWnd, WM_TIMER, 1, (LPARAM)&MakeRain);
return 0;
case WM_TIMER:
gRain[rdx].y += 10;
if (gRain[rdx].y >= gRect.bottom) {
gRain[rdx].f = 0;
KillTimer(hWnd, tid);
}
InvalidateRect(hWnd, NULL, TRUE);
return 0;
case WM_PAINT:
hdc = BeginPaint(hWnd, &ps);
for (int i = 0; i < MAX_WORDS_COUNT; i++) {
if (gRain[i].f == 0) continue;
TextOut(hdc, gRain[i].x, gRain[i].y, words[i], lstrlen(words[i]));
}
EndPaint(hWnd, &ps);
return 0;
case WM_DESTROY:
KillTimer(hWnd, 1);
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hWnd, iMessage, wParam, lParam);
}
When creating window, I want to immediately generate Timer Event, ID 1.
So I used SendMessage function like that
SendMessage(hWnd, WM_TIMER, 1, (LPARAM)&timerproc);
but it didn't work.
仅当定时器向拥有线程的消息队列发送信号以生成 WM_TIMER
消息时,定时器才会调用回调,然后由 (Peek|Get)Message()
检索并传递给 DispatchMessage()
通过线程的消息循环。如果分配了一个,它是 DispatchMessage()
调用定时器回调,否则它将 WM_TIMER
消息传递到 window 的 WndProc:
If the lpmsg
parameter points to a WM_TIMER
message and the lParam
parameter of the WM_TIMER
message is not NULL
, lParam
points to a function that is called instead of the window procedure.
使用SendMessage()
绕过window的消息队列,直接进入window的WndProc。这就是为什么您没有看到调用计时器回调的原因。
因此,至少,您必须使用 PostMessage()
而不是 SendMessage()
,这样您的手动 WM_TIMER
消息才能通过 window 的消息队列并达到 DispatchMessage()
:
PostMessage(hWnd, WM_TIMER, 1, (LPARAM)&timerproc);
否则,您将不得不用自己的假 MSG
直接调用 DispatchMessage()
:
MSG msg = {};
msg.hwnd = hWnd;
msg.message = WM_TIMER;
msg.wParam = 1;
msg.lParam = (LPARAM) &timerproc;
msg.time = GetTickCount();
GetCursorPos(&msg.pt);
DispatchMessage(&msg);
然而,这实际上不是必需的,因为...
How do I activate timerproc at right that the first time of window?
回调是一个函数,所以直接调用它,就像其他函数一样:
//SendMessage(hWnd, WM_TIMER, 1, (LPARAM)&MakeRain);
MakeRain(hWnd, WM_TIMER, 1, GetTickCount());
我有一个计时器,ID 1,它有一个 timerproc 作为回调函数。
我正在 timerproc 中制作其他计时器(ID 2、3、...),它们使用 WM_TIMER
事件,而不是另一个 timerproc。
创建window时,我想立即生成定时器事件,ID 1。
所以我就这样使用了 SendMessage 函数
SendMessage(hWnd, WM_TIMER, 1, (LPARAM)&timerproc);
但是没用。
如何在 window 的第一次正确激活 timerproc?
void CALLBACK MakeRain(HWND hWnd, UINT iMessage, UINT_PTR wParam, DWORD lParam)
{ /* this is timerproc for ID 1 */
if (gRdx >= MAX_WORDS_COUNT) return;
gRain[gRdx].f = 1;
gRain[gRdx].x = rand() % (gRect.right - 30);
gRain[gRdx].y = 10;
int id = RdxToTID(gRdx);
int vel = rand() % 2000 + 1000;
SetTimer(hWnd, id, vel, NULL); /* In here I am making other timers */
gRdx++;
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam)
{
HDC hdc;
PAINTSTRUCT ps;
int tid = wParam;
int rdx = TIDToRdx(tid);
switch (iMessage)
{
case WM_CREATE:
GetClientRect(hWnd, &gRect);
srand((unsigned int)time(NULL));
SetTimer(hWnd, 1, MAKE_RAIN_TERM, MakeRain);
/* my trying, It is not working */
//SendMessage(hWnd, WM_TIMER, 1, (LPARAM)&MakeRain);
return 0;
case WM_TIMER:
gRain[rdx].y += 10;
if (gRain[rdx].y >= gRect.bottom) {
gRain[rdx].f = 0;
KillTimer(hWnd, tid);
}
InvalidateRect(hWnd, NULL, TRUE);
return 0;
case WM_PAINT:
hdc = BeginPaint(hWnd, &ps);
for (int i = 0; i < MAX_WORDS_COUNT; i++) {
if (gRain[i].f == 0) continue;
TextOut(hdc, gRain[i].x, gRain[i].y, words[i], lstrlen(words[i]));
}
EndPaint(hWnd, &ps);
return 0;
case WM_DESTROY:
KillTimer(hWnd, 1);
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hWnd, iMessage, wParam, lParam);
}
When creating window, I want to immediately generate Timer Event, ID 1. So I used SendMessage function like that
SendMessage(hWnd, WM_TIMER, 1, (LPARAM)&timerproc);
but it didn't work.
仅当定时器向拥有线程的消息队列发送信号以生成 WM_TIMER
消息时,定时器才会调用回调,然后由 (Peek|Get)Message()
检索并传递给 DispatchMessage()
通过线程的消息循环。如果分配了一个,它是 DispatchMessage()
调用定时器回调,否则它将 WM_TIMER
消息传递到 window 的 WndProc:
If the
lpmsg
parameter points to aWM_TIMER
message and thelParam
parameter of theWM_TIMER
message is notNULL
,lParam
points to a function that is called instead of the window procedure.
使用SendMessage()
绕过window的消息队列,直接进入window的WndProc。这就是为什么您没有看到调用计时器回调的原因。
因此,至少,您必须使用 PostMessage()
而不是 SendMessage()
,这样您的手动 WM_TIMER
消息才能通过 window 的消息队列并达到 DispatchMessage()
:
PostMessage(hWnd, WM_TIMER, 1, (LPARAM)&timerproc);
否则,您将不得不用自己的假 MSG
直接调用 DispatchMessage()
:
MSG msg = {};
msg.hwnd = hWnd;
msg.message = WM_TIMER;
msg.wParam = 1;
msg.lParam = (LPARAM) &timerproc;
msg.time = GetTickCount();
GetCursorPos(&msg.pt);
DispatchMessage(&msg);
然而,这实际上不是必需的,因为...
How do I activate timerproc at right that the first time of window?
回调是一个函数,所以直接调用它,就像其他函数一样:
//SendMessage(hWnd, WM_TIMER, 1, (LPARAM)&MakeRain);
MakeRain(hWnd, WM_TIMER, 1, GetTickCount());