0

我正在尝试将消息从全局 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;
    }
}
4

1 回答 1

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()andDispatchMessage()调用移入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;
    }
}
于 2013-02-08T03:59:16.677 回答