【发布时间】:2018-10-11 13:19:41
【问题描述】:
我有一个计时器,ID 1,它有一个 timerproc 作为回调函数。
我正在 timerproc 中创建其他计时器(ID 2、3、...),它们使用 WM_TIMER 事件,而不是另一个 timerproc。
创建窗口时,我想立即生成Timer Event,ID 1。
所以我使用了类似的 SendMessage 函数
SendMessage(hWnd, WM_TIMER, 1, (LPARAM)&timerproc);
但是没有用。
如何在第一次窗口的右侧激活 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);
}
【问题讨论】:
-
据我所知,TimerProc函数的lParam就是TimerProc函数的地址。
-
这听起来像XY problem。你实际上想做什么?
SetTimer(hWnd, 1, MAKE_RAIN_TERM, MakeRain);是否被调用MakeRain? -
绝对是XY Problem。除此之外,至少有 2 个错误等待发生:
1计时器将以准确的时间间隔到期的假设是没有根据的。如果您使用该假设编写动画代码,它将看起来参差不齐。2定时器 ID 是指针大小的。使用该功能来防止 ID 冲突,例如通过使用(全局)对象的地址作为计时器 ID。 -
如果你想立即调用
MakeRain,不要使用魔法,直接调用即可。 -
感谢您提供适量的代码来找到问题。
标签: winapi timer sendmessage