如何使用 sendmessage 发送在 win32 中具有计时器过程的 wm_timer [英] How do I use sendmessage for sending wm_timer that has timer proc in win32
问题描述
我有一个计时器,ID 为 1,它有一个 timerproc 作为回调函数.
I have a timer, ID 1, which has a timerproc as a callback function.
我正在 timerproc 中创建其他计时器(ID 2、3、...),它们使用 WM_TIMER
事件,而不是另一个 timerproc.
I am making the other timers (ID 2, 3, ...) in the timerproc and they use WM_TIMER
event, not another timerproc.
创建窗口时,我想立即生成定时器事件,ID 1.
When creating window, I want to immediately generate Timer Event, ID 1.
所以我使用了这样的 SendMessage 函数
So I used SendMessage function like that
SendMessage(hWnd, WM_TIMER, 1, (LPARAM)&timerproc);
但是没有用.
如何在第一次窗口右侧激活 timerproc?
How do I activate timerproc at right that the first time of window?
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);
}
推荐答案
创建窗口时,我想立即生成定时器事件,ID 1.所以我使用了这样的 SendMessage 函数
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);
但是没有用.
仅当计时器向拥有线程的消息队列发出信号以生成 WM_TIMER
消息时,计时器才会调用回调,然后通过 (Peek|Get)Message()<检索该消息/code> 并通过线程的消息循环传递给
DispatchMessage()
.DispatchMessage()
如果分配了定时器回调,则调用定时器回调,否则将 WM_TIMER
消息传递给窗口的 WndProc:
The callback gets called by the timer only when the timer signals the owning thread's message queue to generate a WM_TIMER
message, which is then retrieved by (Peek|Get)Message()
and passed to DispatchMessage()
by the thread's message loop. It is DispatchMessage()
that calls the timer callback if one is assigned, otherwise it delivers the WM_TIMER
message to the window's WndProc:
如果 lpmsg
参数指向 WM_TIMER
消息并且 WM_TIMER
消息的 lParam
参数不是NULL
, lParam
指向一个被调用的函数,而不是窗口过程.
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()
绕过窗口的消息队列并直接进入窗口的 WndProc.这就是为什么您没有看到计时器回调被调用的原因.
Using SendMessage()
bypasses the window's message queue and goes directly to the window's WndProc. That is why you are not seeing the timer callback getting called.
因此,至少,您必须使用 PostMessage()
而不是 SendMessage()
以便您的手动 WM_TIMER
消息可以通过窗口的消息队列到达DispatchMessage()
:
So, at the very least, you would have to use PostMessage()
instead of SendMessage()
so that your manual WM_TIMER
message can go through the window's message queue and reach DispatchMessage()
:
PostMessage(hWnd, WM_TIMER, 1, (LPARAM)&timerproc);
否则,您将不得不使用您自己的假MSG
直接调用DispatchMessage()
:
Otherwise, you would have to call DispatchMessage()
directly with a fake MSG
of your own:
MSG msg = {};
msg.hwnd = hWnd;
msg.message = WM_TIMER;
msg.wParam = 1;
msg.lParam = (LPARAM) &timerproc;
msg.time = GetTickCount();
GetCursorPos(&msg.pt);
DispatchMessage(&msg);
然而,这实际上并不是必需的,因为...
However, that is not actually necessary, because...
如何在第一次窗口右侧激活 timerproc?
How do I activate timerproc at right that the first time of window?
回调是一个函数,所以直接调用它,就像任何其他函数一样:
The callback is a function, so just call it directly, like any other function:
//SendMessage(hWnd, WM_TIMER, 1, (LPARAM)&MakeRain);
MakeRain(hWnd, WM_TIMER, 1, GetTickCount());
这篇关于如何使用 sendmessage 发送在 win32 中具有计时器过程的 wm_timer的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!