Jump to content
  • Advertisement
  • entries
    109
  • comments
    175
  • views
    117584

more on creating a Win32 Window wrapper class...

Sign in to follow this  
Emmanuel Deloget

320 views

WTF again. This version of Firefox decided that the gamedev.net edit fields were not good enough targets to copy the content of the clipboard. This is very annoying, as it happens only on this machine. It is painfull, as I have to type URL instead of just copy them.

This is a simple followup to Oluseyi's article. Some of you might ask how to add non-static message handlers to his nifty Window class - here is the solution!

First, let's define a new tyMessageHandler type as a pointer-to-member-function type. If you need to learn more about these, please have a look to the corresponding section of the C++ FAQ Lite.

typedef LRESULT (Window::*tyMessageHandler)(WPARAM, LPARAM);

Oluseyi's version of tyMessageHandler is a pointer to function, meaning that it can handle only static member functions and non-member functions. This is the key difference between my code and Oluseyi's. The other big difference lies in the MsgRouter() method:

// Final message handler version
LRESULT CALLBACK Window::MsgRouter(HWND hwnd, UINT message,
WPARAM wparam, LPARAM lparam)
{
Window *wnd = 0;

if(message == WM_NCCREATE)
{
// retrieve Window instance from window creation data and associate
wnd = reinterpret_cast((LPCREATESTRUCT)lparam)->lpCreateParams;
::SetWindowLong(hwnd, GWL_USERDATA, reinterpret_cast(wnd));

// save window handle
wnd->SetHWND(hwnd);
}
else
// retrieve associated Window instance
wnd = reinterpret_cast(::GetWindowLong(hwnd, GWL_USERDATA));

if(wnd)
{
tyMessageIterator it;
it = wnd->GetMessageHandler(message);
if(it != NULL)
{
// this is the main difference:
// it->second is a pointer to a member function, not a
// pointer to a function. We also get rid of *wnd (pretty useless)
// and hwnd (pretty useless too, since we'll call this->GetHWND())
return ((*wnd).*(it->second))(wparam, lparam);
}
}
return DefWindowProc(hwnd, message, wparam, lparam);
}

There is only one remaining difference between Oluseyi's version and mine, and it copes with the way we register the handlers. While the RegsiterMessagehandler() method don't change at all, the way we call it change.

// how to register a handler:
RegisterMessageHandler(WM_CLOSE, &Window::OnClose);

Don't forget the '&', the class name and the scope resolution operator - they are mandatory in this case.

I left the easy part for the end - the message handler method signatures are now far simpler:

class MyWindow
{
LRESULT MyMessageHandler(WPARAM wparam, LPARAM lparam);
};

Voila. Once it has been registered, your member function will be automagically called if the message is triggered. It was rather easy, isn't it?

One can add more complexity by using marshallers objects that will first decode both wparam and lparam then call your message handler using the right arguments (for example, a POINT object and a flag value for a mouse message). This is beyond the scope of this journal entry - but be quiet, and I'll give some hints to you ;)
Sign in to follow this  


0 Comments


Recommended Comments

There are no comments to display.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • 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!