如何使用 sendmessage 发送在 win32 中具有计时器过程的 wm_timer [英] How do I use sendmessage for sending wm_timer that has timer proc in win32

查看:34
本文介绍了如何使用 sendmessage 发送在 win32 中具有计时器过程的 wm_timer的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个计时器,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 a WM_TIMER message and the lParam parameter of the WM_TIMER message is not NULLlParam 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆