问题
I have a timer, ID 1, which has a timerproc as a callback function.
I am making the other timers (ID 2, 3, ...) in the timerproc and they use WM_TIMER event, not another timerproc.
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.
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);
}
回答1:
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.
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:
If the
lpmsgparameter points to aWM_TIMERmessage and thelParamparameter of theWM_TIMERmessage is notNULL,lParampoints to a function that is called instead of the window procedure.
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.
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);
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...
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());
来源:https://stackoverflow.com/questions/52761097/how-do-i-use-sendmessage-for-sending-wm-timer-that-has-timer-proc-in-win32