Jump to content
  • Advertisement
Sign in to follow this  
Renthalkx97

WinAPI WNDPROC to Engine/Game MessageHandler

This topic is 973 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

Hello all, I need some opinions from everyone. I've been questioning my approach on handling window events. As you most likely know, the window procedure is very tightly coupled to a winapi window, as is registering the window class.
 

The way  I circumvent this is by using a static MessageRouter(read static WNDPROC) that grabs the pointer to my engine class that is stored in the extra user data of the window. I then call my MessageHandler from my engine inside the MessageRouter and that is how I forward my events.

 

I do feel as though this is a very suitable solution, however I also feel as though there are better, more elegant ways to handle this. I just wanted to get everyone's input on how they handle this exact problem.

 

This is an example of my my approach looks;

LRESULT CALLBACK LWindowWin32::MessageRouter(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
	Lightning *pLightning;

	if (msg == WM_NCCREATE)
	{
		LPCREATESTRUCT lpCreateStruct = reinterpret_cast<LPCREATESTRUCT>(lParam);

		pLightning = static_cast<Lightning*>(lpCreateStruc->lpCreateParams);

		SetWindowLongPtr(hWnd, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(pLightning));
	}
	else
	{
		pLightning = reinterpret_cast<Lightning*>(GetWindowLongPtr(hWnd, GWLP_USERDATA));
	}

	if (pLightning)
	{
		pLightning->MessageHandler(/*converted winapi parameters would go here*/)
	}

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

Thank you,

BagelBytes

Share this post


Link to post
Share on other sites
Advertisement

What do you feel isn't elegant about it?

Another way is to capture messages in the main loop when returned from GetMessage/PeekMessage.

 

One thing I see is that you should probably not always return DefWindowProc at the end, but let 'MessageHandler' decide. Though I'm not entirely clear on what your message handler does, do you pass everything to it or where do you decide what "converted winapi parameters" are?

Edited by Erik Rufelt

Share this post


Link to post
Share on other sites

Another way is to capture messages in the main loop when returned from GetMessage/PeekMessage.

 

This is in general not an option, since Windows sometimes uses an internal message loop instead of the applications loop, e.g. when a menu is opened, the window is resized, when a modal dialog is shown...

Share this post


Link to post
Share on other sites
I do something quite similar.  I have a Window class that stores a pointer to itself in the extra user data, and a static message handler that just forwards to the appropriate class.  I inherit the Window class whenever I need a window (usually I only need one) and override WMProc().  All the Window's share the same WNDCLASSEX (well there are ways to user other WNDCLASS's but the default one is shared).  It seems easy and clean enough for me.
 
One this I do a bit differently is I set the extra data right after I create the window:
hwnd = CreateWindowEx(...);
if (hwnd == nullptr) throw_detailed(WindowsException() << "CreateWindowEx() error, cannot create window.");

SetLastError(0);
SetWindowLongPtr(hwnd, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(this));
if (GetLastError() != 0) throw_detailed(WindowsException() << "SetWindowLongPtr() error, cannot set window pointer.");
Edited by Ryan_001

Share this post


Link to post
Share on other sites


What do you feel isn't elegant about it?

 

I just felt as though I could better decouple my event handling from window, but the in all honesty, I'm just prematurely optimizing if you even want to call it that. With the approach Washu offered me, I am a lot more satisfied with the overall architecture of my whole event system. It just feels alot cleaner to me than what I was doing. The above code wasn't my actual code, but an example. The converted winapi parameters comment would be the message id that would be mapped to the winapi equivalent.

 

Nonetheless, I don't believe there is one correct way to do it, all of the solutions mentioned here work extremely well. I'm currently refactoring Washu's example to work with classes and more cleanly interface with my existing setup.

 

 

I do something quite similar.  I have a Window class that stores a pointer to itself in the extra user data, and a static message handler that just forwards to the appropriate class.  I inherit the Window class whenever I need a window (usually I only need one) and override WMProc().  All the Window's share the same WNDCLASSEX (well there are ways to user other WNDCLASS's but the default one is shared).  It seems easy and clean enough for me.
 
One this I do a bit differently is I set the extra data right after I create the window:

hwnd = CreateWindowEx(...);
if (hwnd == nullptr) throw_detailed(WindowsException() << "CreateWindowEx() error, cannot create window.");

SetLastError(0);
SetWindowLongPtr(hwnd, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(this));
if (GetLastError() != 0) throw_detailed(WindowsException() << "SetWindowLongPtr() error, cannot set window pointer.");

 

When I first learned about this method, I had seen them always handling it inside of the NCCREATE message so I just went with that. Your way obviously works too and I'm sure it cleans up your static wndproc a bit, not having to set the user data.

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.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!