PostMessage只运行一次?

时间:2013-02-07 22:56:20

标签: c++ winapi

我正在尝试从全局WindowProc函数向GUI类发送消息。 消息定义如下:

#define WM_ENV_RESIZED (WM_APP + 0)

我的WindowProc功能如下所示

LRESULT CALLBACK windowProcedure(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    int res;
    switch (message)
    {
        case WM_SIZE:
            std::cout << "window resized" << std::endl;

            res = PostMessage(hWnd, WM_ENV_RESIZED, 0, 0);
            if ( res == 0 )    //<-- res is never 0
            {
                std::cout << "PostMessage failure!" << std::endl;
                std::cout << "Error code: " << GetLastError() << std::endl;
            }
            break;
        default:
            return DefWindowProc(hWnd, message, wParam, lParam);
    }

    return DefWindowProc(hWnd, message, wParam, lParam);
}

然后在GUI类中接收消息,如下所示:

MSG msg;
while (running)
{
    while ( PeekMessage(&msg, NULL, 0, 0, PM_REMOVE) )
        processWindowsMessage(&msg);

    //DirectX render calls
}

现在我的问题是PeekMessage()从未收到过该消息。它只在窗口创建时收到一次。在此之后它从未收到过。

在PostMessage()之后直接调用GetLastError()总是返回错误代码6,它代表根据MSDN的ERROR_INVALID_HANDLE。但这没有任何意义,因为PostMessage()永远不会返回0,这意味着在发布过程中出现了问题。 我试图绕过消息队列并使用SendMessage()将消息直接发送到窗口,但总是返回0(具有相同的错误代码6 ..)。

我真的不知道我做错了什么。使用PeekMessage()时,如何确保始终收到已发布的消息?

修改 我已经更新了Remy建议的消息循环。下面是processWindowsMessage()

中的代码
void Environment::processWindowsMessage( MSG *msg )
{
    switch ( msg->message )
    {
        case WM_ENV_RESIZED:
            std::cout << "WM_ENV_RESIZED caught" << std::endl;
            break;
        case WM_QUIT:
            running = false;
            break;
        default:
            TranslateMessage(msg);
            DispatchMessage(msg);
            break;
    }
}

1 个答案:

答案 0 :(得分:1)

由于您的消息被发布到正在调整大小的同一窗口,因此DispatchMessage()会将消息发送到窗口的过程,就像任何其他针对该窗口的消息一样。所以:

1)处理windowProcedure()

内的消息
LRESULT CALLBACK windowProcedure(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    switch (message)
    {
        case WM_SIZE:
            std::cout << "window resized" << std::endl;

            if (!PostMessage(hWnd, WM_ENV_RESIZED, 0, 0))
            {
                std::cout << "PostMessage failure!" << std::endl;
                std::cout << "Error code: " << GetLastError() << std::endl;
            }
            break;

        case WM_ENV_RESIZED:
            std::cout << "env resized" << std::endl;
            //...
            return 0;
    }

    return DefWindowProc(hWnd, message, wParam, lParam);
}

MSG msg;
while (running)
{
    while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE) )
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }

    //DirectX render calls
}

2)如果您不想在窗口过程中处理自定义消息,请更改消息循环,将TranslateMessage()DispatchMessage()调用移至processWindowsMessage()并仅调用它们非自定义消息,不要翻译/发送自定义消息:

LRESULT CALLBACK windowProcedure(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    switch (message)
    {
        case WM_SIZE:
            std::cout << "window resized" << std::endl;

            if (!PostMessage(hWnd, WM_ENV_RESIZED, 0, 0))
            {
                std::cout << "PostMessage failure!" << std::endl;
                std::cout << "Error code: " << GetLastError() << std::endl;
            }
            break;
    }

    return DefWindowProc(hWnd, message, wParam, lParam);
}

MSG msg;
while (running)
{
    while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
        processWindowsMessage(&msg);

    //DirectX render calls
}

void processWindowsMessage(MSG *msg)
{
    switch (msg->message)
    {
        case WM_ENV_RESIZED:
            std::cout << "env resized" << std::endl;
            //...
            break;

        default:
            TranslateMessage(msg);
            DispatchMessage(msg);
            break;
    }
}