【问题标题】:PeekMessage not getting the message?PeekMessage 没有收到消息?
【发布时间】:2011-09-07 12:50:46
【问题描述】:

我创建了一个自定义消息类型,用于调整我的Window 的大小,称为WM_NEED_RESIZE。我已经在我的 .h 文件中定义了它,并在我的 .cpp 文件中进行了初始化。我还注册了我的WindowProc 函数来接受消息。以下是这些项目的代码:

const uint32 WindowsGLWindow::WM_NEED_RESIZE = WM_USER + 100;
LONG WINAPI WindowsGLWindow::WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    static PAINTSTRUCT ps;// do I need this?
    static sint32 newWidth = 0;
    static sint32 newHeight = 0;
    bool res = false;

    switch (uMsg) {
        case WM_PAINT:
            //display();
            BeginPaint(hWnd, &ps);
            EndPaint(hWnd, &ps);
            return 0;

        case WM_SIZE:
            //glViewport(0, 0, LOWORD(lParam), HIWORD(lParam));
            res = PostMessage(hWnd, WindowsGLWindow::WM_NEED_RESIZE, wParam,     lParam);
            std::cout << "WM_SIZE: " << res << std::endl;
            return 0;

        case WindowsGLWindow::WM_NEED_RESIZE:
            std::cout << "WindowsGLWindow::WM_NEED_RESIZE" << std::endl;
            break;

        case WM_CHAR:
            switch (wParam) {
                case 27: /* ESC key */
                    PostQuitMessage(0);
                    break;
            }
            return 0;

        case WM_CLOSE:
            PostQuitMessage(0);
            return 0;
    }

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

在另一个函数中,我正在运行PeekMessage(..) 以收集所有消息。这是消息泵的sn-p:

    MSG msg;
    while (PeekMessage(&msg, 0, 0, 0, PM_REMOVE) == TRUE) // maybe use GetInputState(?)     as well?
    {
        if (msg.message == WM_QUIT)
            retVal = -1;

        if (msg.message == WindowsGLWindow::WM_NEED_RESIZE) {
            uint32 newWidth = LOWORD(msg.lParam);
            uint32 newHeight = HIWORD(msg.lParam);

            std::cout << "PeekMessage: WindowsGLWindow::WM_NEED_RESIZE" <<         std::endl;

            // call resize only if our window-size changed
            if ((newWidth != width_) || (newHeight != height_)) {
                resize(newWidth, newHeight);
            }

            PostMessage(msg.hwnd, WM_PAINT, 0, 0);
        }

        switch (msg.message) {
            case WM_MOUSEMOVE:
                // Retrieve mouse screen position
                //int x = (short) LOWORD(lParam);
                //int y = (short) HIWORD(lParam);

                // Check to see if the left button is held down:
                //bool leftButtonDown = wParam & MK_LBUTTON;

                // Check if right button down:
                //bool rightButtonDown = wParam & MK_RBUTTON;
                break;
            case WM_LBUTTONDOWN:
            case WM_RBUTTONDOWN:
            case WM_LBUTTONUP:
            case WM_RBUTTONUP:
            case WM_KEYUP:
            case WM_KEYDOWN:
                /*
                switch (msg.wParam) {
                    case 'W':
                        // w key pressed
                        break;
                    case VK_RIGHT:
                        // Right arrow pressed
                        break;
                    default:
                        break;
                }
                */
                break;
        }

        TranslateMessage(&msg);
        DispatchMessage(&msg);

    }

我的问题是 WM_NEED_RESIZE 消息仅在窗口第一次打开时在消息队列中找到一次,之后我的 PeekMessage(..) 在消息队列中再也找不到它。我真的不确定为什么会这样。然而,它WindowProc(..) 方法接收的(这对我没有帮助)。如果你们能提供任何帮助,我将不胜感激。

谢谢

贾勒特

【问题讨论】:

  • 为什么你需要在主消息循环中捕获NEED_RESIZE,你不能在你的WindowProc中处理它吗?
  • @Ben WindowProc 是静态的,需要在 WindowsGLWindow 对象上调用 resize,而我无法在 WindowProc 中访问该对象。另外,我想知道为什么我正在做的事情不起作用(看起来应该......)
  • 您是从控制台运行它,希望看到 std::cout 的输出,还是从调试器运行它,希望看到输出窗口的输出?
  • 另外,将您的类指针传递给您的 CreateWindowEx 调用的最后一个参数,然后使用 SetWindowLong 、 GetWindowLong 在您的 winmain 中获取/设置您的类,在您的类中调用一个非静态函数进行消息处理。查看msdn,他们有一个关于如何做到这一点的教程。
  • @johnathon 我从 Eclipse 运行它,希望在控制台输出屏幕中看到输出(也会出现一个窗口,我调整它的大小以检查消息是否发送正确) .感谢您提供有关类指针的信息......(我想那是一个对象指针?)。我去看看..

标签: c++ window messages postmessage peekmessage


【解决方案1】:

您正在显示的消息泵循环将在队列为空后立即退出。我无法判断您发布的内容是否会再次被输入。

如果这是您的主要消息泵,您应该改用GetMessage(),因为它会等到有可用的内容后再返回。请查看this MSDN article 了解更多信息。

【讨论】:

  • 你说得对,我的问题描述中没有包含足够的信息。我正在开发一款游戏,由于GetMessage() 的行为方式,我认为它不合适(因为它不会返回并允许发生其他与游戏相关的处理)。我从我的主游戏循环中调用我的消息泵代码。
【解决方案2】:
  1. 不要使用 std::cout 期望在调试器中看到该输出,使用 OutputDebugString(); .

  2. 您需要将类指针传递给调用 CreateWindowEx 的最后一个参数,然后从 WM_CREATE 的 LPARAM 中传递给您的 LPCREATESTRUCT 中检索该指针,您的类指针将位于结构。将您的 clas 指针设置为窗口的 GWLP_USERDATA,并在任何其他消息调用上调用 GetWindowsLong ,检索您的类指针,然后将消息、wparam 和 lparam 全部传递给您的内部类消息处理程序。

    李>

http://msdn.microsoft.com/en-us/library/ff381400%28v=VS.85%29.aspx

【讨论】:

  • 感谢 Johnathon,这是一个很大的帮助!现在就像一个魅力。此外,我使用std::cout 打印到控制台,并且输出正常显示(当然,PeekMessage(..) 循环的输出除外)。
  • OutputDebugString 打印到调试器,因此您不必打开控制台窗口即可查看输出(即我不使用 Eclipse 进行编码,所以我什至不知道是否Eclipse 有一个调试视图窗口),如果您使用该 api,并使用字符串容器,如果是窄字符项目,则在其中返回 .c_str(),如果是 unicode 项目,请使用 wstring,然后使用 .c_str()。跨度>
  • 啊有趣,我不知道。谢谢
猜你喜欢
  • 2017-10-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-06-03
  • 2019-12-12
  • 2021-10-26
  • 2020-07-16
相关资源
最近更新 更多