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
::SetWindowLong(hwnd, GWL_USERDATA, reinterpret_cast
// save window handle
// retrieve associated Window instance
wnd = reinterpret_cast
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:
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:
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 ;)