3

I've created a custom message type for use in resizing my Window, called WM_NEED_RESIZE. I've defined it in my .h file, and initialized in my .cpp file. I have also registered my WindowProc function to accept messages. Here is the code for these items:

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);
}

In another function I am running through PeekMessage(..) to collect all messages. Here is the snippet of the message pump:

    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);

    }

My problem is that the WM_NEED_RESIZE message is only found once in the message queue when the window first opens, after which it is never found in the message queue by my PeekMessage(..). I'm really not sure why this is happening. It is, however, being received by the WindowProc(..) method (which doesn't really help me). I would appreciate any help you guys could provide.

Thanks

Jarrett

elder_george
  • 7,849
  • 24
  • 31
Jarrett
  • 1,767
  • 25
  • 47
  • Why do you need to catch `NEED_RESIZE` in the main message loop, can't you process it inside your WindowProc? – Ben Voigt Jun 03 '11 at 03:39
  • @Ben `WindowProc` is static, and a `resize` needs to be called on a `WindowsGLWindow` object, which I don't have access to within `WindowProc`. Plus I would like to know why what I'm doing doesn't work (as it seems it should..) – Jarrett Jun 03 '11 at 03:45
  • Are you running this from a console, expecting to see the output from std::cout, or are you running this from the debugger expecting to see the output from the output window? – johnathan Jun 03 '11 at 04:16
  • Also, pass your class pointer to the last parameter of your CreateWindowEx call, then use SetWindowLong , GetWindowLong to get/set your class in your winmain, calling a non static function in your class for message handling. Look on the msdn, they have a tutorial on how to do that. – johnathan Jun 03 '11 at 04:21
  • @johnathon I'm running it from Eclipse, expecting to see the output in the Console output screen (A window appears as well, and I resize it to check and see if the message is sent correctly). Thanks for the info about the class pointer...(I imagine that's an object pointer?). I'll check that out.. – Jarrett Jun 03 '11 at 04:27
  • @Jarrett, @Johnathon: `Get`/`SetWindowProp` are much better than `Get`/`SetWindowLongPtr` (and `SetWindowLong` is wrong for storing pointers). – Ben Voigt Jun 03 '11 at 04:29
  • @Jarrett: Evidently you only have one window, since you're running your message loop inside its member function. Then you could just store a pointer in a global (or static member) variable. Even easier than `Get`/`SetWindowProp`! – Ben Voigt Jun 03 '11 at 04:31
  • @Ben Voigt msdn recommends using Get/SetWndowLongPtr in their tutorial. just going off of that. – johnathan Jun 03 '11 at 04:41
  • @Ben Voigt As I understand it, you should use the `Get/SetWindowLongPtr` if you're going to be programming for 64bit architecture (which I may be in the near future), so I think in my case these functions are appropriate. – Jarrett Jun 03 '11 at 04:51
  • @Jarrett: `Get`/`SetWindowProp` are the appropriate functions to use. – Ben Voigt Jun 03 '11 at 05:16
  • @Ben Voigt Do you know of any examples that use these functions? I am unable to find a reference to these functions on the msdn site, and google search hasn't yielded much. – Jarrett Jun 03 '11 at 18:04
  • @Jarrett: Sorry, got the name wrong. It's just [`GetProp`](http://msdn.microsoft.com/en-us/library/ms633564.aspx)/[`SetProp`](http://msdn.microsoft.com/en-us/library/ms633568.aspx). So much for consistent function naming. The important thing is that you aren't fighting over a single data value with every other library/tool/whatever that wants to store per-window data, you get your own private property attached to your windows. – Ben Voigt Jun 03 '11 at 18:35
  • @Ben Voigt ahh okay I see now. Looks easy enough - thanks Ben! – Jarrett Jun 04 '11 at 14:01

2 Answers2

2
  1. Dont use std::cout expecting to see that output in your debugger, insted use OutputDebugString(); .

  2. You need to pass your class pointer to the last parameter of your call to CreateWindowEx, then retrieve that pointer from the LPCREATESTRUCT passed to you in the LPARAM of WM_CREATE, your class pointer will be in the lpCreateParmas feild of the struct. Set your clas pointer to the GWLP_USERDATA of your window, and on any other message calls , call GetWindowsLong , retrieve your class pointer, then pass the message, wparam, and lparam all off to your internal class message handler.

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

johnathan
  • 2,315
  • 13
  • 20
  • Thanks Johnathon, this was a great help! Works like a charm now. Also, I was using `std::cout` to print to the Console, and the output was appearing as it should (except, of course, the output from the `PeekMessage(..)` loop). – Jarrett Jun 03 '11 at 04:53
  • OutputDebugString prints to the debugger, so you don't have to have a console window open to see the output (ie I don't use Eclipse to code with, so i don't even know if Eclipse has a debug view window), if you use that api, and use string containers, return .c_str() in them if it's a narrow character project, if it's a unicode project, use wstring and then .c_str(). – johnathan Jun 03 '11 at 05:18
  • ahh interesting, I didn't know that. Thanks – Jarrett Jun 03 '11 at 14:54
0

The message pump loop that you are showing will exit as soon as the queue is empty. I can't tell from what you've posted if it ever gets entered again.

If this is your main message pump, you should use GetMessage() instead, as it will wait until something is available before returning. Take a look at this MSDN article for more info.

zdan
  • 28,667
  • 7
  • 60
  • 71
  • You're right, I didn't include enough information in my description of the problem. I'm developing a game, and because of the way `GetMessage()` behaves I didn't think it was appropriate (as it would not return and allow other game related processing to occur). I call my message pump code from within my main game loop. – Jarrett Jun 03 '11 at 04:55