WinapiExtension
 All Classes Files Functions Variables Typedefs Pages
Message Handling

In the Windows API message are sent to windows when an event occurs. The framework supports message handling in two ways.

Old Style: Window::OnMessage()

Every window has its own big window procedure, where all messages run through.

class WndProcExample : public Window
{
BindExample()
{
textfield = NULL;
textfield = CreateEdit(*this, 0, 0, 0, 0, 0);
// start first size calculation
SetClientSize(400, 300);
}
virtual LRESULT OnMessage(HWND hwnd, UINT message, WPARAM wp, LPARAM lp)
{
switch(message)
{
case WM_SIZE:
{
m.Init(hwnd, message, wp, lp);
// because this message can be received before the textfield is created
// we need an extra check
if(textfield)
MoveWindow(textfield, 5, 5, m.Width() - 10, m.Height() - 10, TRUE);
// not using return because the base function must be called as well
break;
}
case WM_CLOSE:
{
PostQuitMessage(0);
// skip base function
// so the standard WM_CLOSE procedure of destroying the window does not take place.
return 0;
}
}
return Window::OnMessage(hwnd, message, wp, lp);
}
HWND textfield;
};

New Style: Window::Bind()

Bind can be used on virtually any function, a global C function, a member function, even a functor.

class BindExample : public Window
{
BindExample()
{
textfield = CreateEdit(*this, 0, 0, 0, 0, 0);
// bind size handler here, after all controls have been created
Bind(WM_SIZE, &BindExample::OnSize, this);
// bind static function, no this pointer needed
Bind(WM_CLOSE, OnClose);
// start first size calculation
SetClientSize(400, 300);
}
// WM_SIZE has a corresponding class msgSize
void OnSize(msgSize& m)
{
MoveWindow(textfield, 5, 5, m.Width() - 10, m.Height() - 10, TRUE);
// no need to call the base implementation, the framework does it for us.
}
// WM_CLOSE uses the msgBase class because it has neither parameters nor special return values
static void OnClose(msgBase& m)
{
PostQuitMessage(0);
// result causes the framework to skip the base implementation of this message.
// so the standard WM_CLOSE procedure of destroying the window does not take place.
m.Result(0);
}
HWND textfield;
};

If you are using C++11, you can also bind lambda expressions.

class BindLambda : public Window
{
BindLambda()
{
HWND button = CreateButton(*this, L"Increase x", 0, 0, 0, 100, 25);
auto incr = [this](msgCommand&)
{
++x;
}
BindCommand(button, incr);
}
int x;
};

I probably have to say that I didn't come up with the Bind mechanism all by myself. I first saw it in wxWidgets 2.9, and thought it was a cool idea. It isn't a complete copy though. I tried to keep everything lightweight. There is no queue for msgBase objects, which are only created when a message comes up and a message handler was found.