Jump to content
  • Advertisement
Sign in to follow this  
Six222

Windows message loop questions

This topic is 2107 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I have a few questions regarding the Windows procedure and how to properly manage messages.

 

1) What's the difference between handling messages in the example:

while(!exitGame)
    {
        if(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);

			switch(msg.message)
			{
			case WM_KEYDOWN:
				keyboard.UpdateKey(msg.wParam, true);
				break;
			}
        }

Compared to handling it in the WindowProc method

LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    switch(message)
    {
        case WM_KEYDOWN:
             keyboard.UpdateKey(msg.wParam, true);
	     break;

    }

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

My first guess is that in the WindowProc is that it handles it per-window? 

 

2) For an application that's only dealing with 1 window is it okay to just ignore the WindowProc method? My main problem with this is I would like to update my Keyboard input class from within the function, is the only way to get around this to make it a global?

 

Thanks smile.png

Share this post


Link to post
Share on other sites
Advertisement

2) For an application that's only dealing with 1 window is it okay to just ignore the WindowProc method? My main problem with this is I would like to update my Keyboard input class from within the function, is the only way to get around this to make it a global?

No. See GWLP_USERDATA and WM_NCCREATE along with the final parameter of the CreateWindowEx function.

As an alternative, there's always WTL, which handles your window creation and management quite cleanly and simply.
#include <iostream>
#include <atlbase.h>
#include <atlwin.h>

class MainWindow : public CWindowImpl<MainWindow, CWindow, CFrameWinTraits>
{
public:
    MainWindow() {
        Create(nullptr, 0, _T("Sample Window"));
        ShowWindow(SW_SHOW);
    }

    BEGIN_MSG_MAP(MainWindow)
        MESSAGE_HANDLER(WM_DESTROY, OnDestroy);
        MESSAGE_HANDLER(WM_KEYDOWN, OnKeyDown);
        MESSAGE_HANDLER(WM_KEYUP, OnKeyUp);
    END_MSG_MAP()

private:
    LRESULT OnKeyDown(UINT MSG, WPARAM wParam, LPARAM lParam, BOOL& handled) {
        if(!(HIWORD(lParam) & KF_REPEAT)) {
            std::cout<<"Key down: "<<std::hex<<wParam<<std::endl;
            // ...
        }
        return 0;
    }

    LRESULT OnKeyUp(UINT MSG, WPARAM wParam, WPARAM lParam, BOOL& handled) {
        std::cout<<"Key up: "<<std::hex<<wParam<<std::endl;
        // ...
        return 0;
    }

    LRESULT OnDestroy(UINT msg, WPARAM wParam, WPARAM lParam, BOOL& handled) {
        PostQuitMessage(0);
        return 0;
    }
};

int main() {
    MainWindow w;

    MSG message;
    while(true) {
        if(PeekMessage(&message, 0, 0, 0, PM_REMOVE)) {
            if(message.message == WM_QUIT)
                break;

            TranslateMessage(&message);
            DispatchMessage(&message);
        } else {
        }
    }
}
Edited by Washu

Share this post


Link to post
Share on other sites

I really like the look of WTL, looks much cleaner!

 

So I've been looking into things and found that during the window creation you can allocate extra bytes during the window creation with WNDCLASSEX.cbWndExtra. where you then create your window you can pass a pointer from CreateWindowEx() through to the lparam of the WM_CREATE message and store that pointer using SetWindowLongPtr. Then every time the in the message loop you can get that pointer with the specified HWND... Is this correct way of doing this? Example:

 

Thanks again for the help smile.png

LRESULT CALLBACK Window::WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
         Window* window = (Window*)GetWindowLongPtr(hWnd, 0);
		
         switch(message)
	{
                case WM_CREATE:
		{
		    CREATESTRUCT* cs = (CREATESTRUCT*) lParam;
	            SetWindowLongPtr(hWnd, 0, (LONG_PTR) cs->lpCreateParams;
		} break;
        }
}

void Window::Create()
{
        ZeroMemory(&wc, sizeof(WNDCLASSEX));

	wc.cbSize = sizeof(WNDCLASSEX);
	wc.style = CS_HREDRAW | CS_VREDRAW;
	wc.lpfnWndProc = WindowProc;
	wc.cbClsExtra = 0;
	wc.cbWndExtra = sizeof(Window*); //Allocate extra space for a pointer to the Window
	wc.hInstance = hInstance;
	wc.hCursor = LoadCursor(NULL, IDC_ARROW);
		
	wc.lpszClassName = "GameClass";

        RegisterClassEx(&wc);

	RECT wr = {0, 0, windowWidth, windowHeight};
	AdjustWindowRect(&wr, WS_OVERLAPPEDWINDOW, FALSE);

	hWnd = CreateWindowEx(NULL,
		"GameClass",
		windowTitle.c_str(),
		WS_OVERLAPPEDWINDOW,
		300,
		100,
		wr.right - wr.left,
		wr.bottom - wr.top,
		NULL,
		NULL,
		hInstance,
		this); //Pass a pointer to this to WM_CREATE
}
Edited by Six222

Share this post


Link to post
Share on other sites

One more reason to not handle the messages in the message loop is this: In several situations the user-implemented message loop is not used. E.g. when showing a modal dialog (incl. message boxes), when moving or resizing a window, when showing a menu, Windows uses an internal loop that dispatches the messages.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!