Thomas Sampson

Taking control of the message loop!

Leave a comment

Intro

Today I found a neat way to access and work with the windows message loop via a class member function using a small hack/workaround. Unless you are working with a command line application you will probably have need to call RegisterClassEx() (a win api function) at some point early on in your program, to register a window with the operating system. In doing so you fill out a WNDCLASSEX structure describing your window, and also setting the message processing callback function (the part we are interested in).

The scenario

As mentioned previously, when setting up our WNDCLASSEX structure we usually pass a non-member function into the structure as a callback mechanism for system/window events (usually names something like MsgProc). This non member function gets invoked when messages are sent to our application from the OS and we can handle them appropriately.

In a lot of situations (especially when developing games applications) we have some kind of manager class responsible for initialising the window, perhaps a graphics api etc, and it would be nice for this manager class to be able to handle the message loop it’s self using a class member function. This is handy as it allows events in the message loop to directly affect the state and behaviour of the manager class.

The problem is that when registering your window, the WNDCLASSEX structure will not take a class member function as a parameter (due to it needing a handle to the class instance at runtime). I have seen and used many hacks to allow a class to handle this job (involving function pointers / static class methods etc etc) but none have been as efficient as the one which follows…

  • Give the WNDCLASSEX structure a non-member function to act as a …”middle man” message loop
  • When calling CreateWindow() pass in a pointer to the class instance (usually “this“)
  • Inside the non member message loop extract this pointer and redirect the call

Example

Here is an example of redirecting the message loop to the WndProc() method of a Manager instance…

Window Setup
//Setup the window class
WNDCLASSEX wc = {sizeof(WNDCLASSEX), CS_CLASSDC, MainWndProc, 0L, 0L, GetModuleHandle(NULL), NULL, NULL, NULL, NULL,"demo", NULL};

//Register window class with OS
RegisterClassEx(&wc);

// "this" is used to let the window know of our manager class instance
CreateWindow("demo", "demo", MODE_WINDOWED, 100, 100, 640, 480, GetDesktopWindow(), NULL, wc.hInstance, this);
Non-member Message Loop
//NON MEMBER MESSAGE LOOP
LRESULT CALLBACK MainWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
	static Manager* app = 0;

	switch( msg )
	{
		case WM_CREATE:
		{
			// Get the pointer to the manager instance we passed
			// into CreateWindow
			CREATESTRUCT* cs = (CREATESTRUCT*)lParam;
			app = (sys::Core*)cs->lpCreateParams;
			return 0;
		}
	}

	if( app )
	{
		return app->MsgProc(msg, wParam, lParam); //Re-call the message loop on our manager instance
	}
	else
	{
		return DefWindowProc(hwnd, msg, wParam, lParam);
	}
}
Manager::MsgProc (Member Message Loop)
//MEMBER MESSAGE LOOP
LRESULT WINAPI CALLBACK Manager::MsgProc(UINT msg, WPARAM wParam,
																				   LPARAM lParam)
{
	switch (msg)
	{

	//Handle the message here inside the Manager member function

	}
}
Advertisements

Author: tomtech999

I have recently graduated with a 1st class degree in MComp Games Software Development at Sheffield Hallam University, focusing primarily on application development in C++, with experience in graphics programming, scripting languages, DVCS/VCS and web technology. In my spare time I enjoy Drumming, Reading and Snowboarding!

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s