neoWidgets
 All Classes Namespaces Files Functions Variables Enumerations Enumerator Pages
Message Handling

Binding message handlers

The preferred way to handle window messages is with the neo::WindowBase::Bind() mechanism. This mean a message handler is attached to the messages that require it. The message handler can have any name, and can be static or a member function, even a functor. But it must have return type void and take a neo::Message& as parameter. Subclasses of message are also valid choices for parameters.

using namespace neo;
class LoginDialog : public WindowModal
{
public:
NameDialog(LoginController* pLogin)
{
Size s(300, 100);
login = pLogin;
// non resizable dialog
Create(WindowParam()
.Text("Enter your name and password")
.Style(WS_OVERLAPPED|WS_SYSMENU|WS_CAPTION)
.InnerSize(s));
textName = TextBox(*this, Rect(5, 5, s.cx - 10, 25));
textPassword = TextBox(*this, Rect(5, 35, s.cx - 10, 25), ControlParam().AddStyle(ES_PASSWORD));
Button buttonOk = Button(*this, "Ok", Rect(s.cx - 210, s.cy - 35, 100, 25));
Button buttonCancel = Button(*this, "Ok", Rect(s.cx - 105, s.cy - 35, 100, 25));
Bind(WM_CLOSE, &LoginDialog::DialogCancel, this);
Bind(ButtonMessageId(buttonOk), &LoginDialog::DialogOk, this);
Bind(ButtonMessageId(buttonCancel), &LoginDialog::DialogCancel, this);
}
void DialogOk(Message& m)
{
if(login->DoLogin(textName.GetText(), textPassword.GetText()))
EndModal(IDOK);
}
void DialogCancel(Message& m)
{
EndModal(IDCANCEL);
}
private:
LoginController* login;
TextBox textName;
TextBox textPassword;
};

Old school

The above code example works and looks pretty clean. But for those who like direct access to the windows messages, the old school neo::WindowBase::WndProc() is also available as a virtual function.

using namespace neo;
class LoginDialog : public WindowModal
{
public:
static const int BUTTON_OK = 100;
static const int BUTTON_CANCEL = 101;
NameDialog(LoginController* pLogin)
{
Size s(300, 100);
login = pLogin;
// non resizable dialog
Create(WindowParam()
.Text("Enter your name and password")
.Style(WS_OVERLAPPED|WS_SYSMENU|WS_CAPTION)
.InnerSize(s));
textName = TextBox(*this, Rect(5, 5, s.cx - 10, 25));
textPassword = TextBox(*this, Rect(5, 35, s.cx - 10, 25), ControlParam().AddStyle(ES_PASSWORD));
Button buttonOk = Button(*this, "Ok", Rect(s.cx - 210, s.cy - 35, 100, 25), ControlParam().Id(BUTTON_OK));
Button buttonCancel = Button(*this, "Ok", Rect(s.cx - 105, s.cy - 35, 100, 25), ControlParam().Id(BUTTON_CANCEL));
}
virtual LRESULT WndProc(HWND window, UINT message, WPARAM wp, LPARAM lp) override
{
switch(message)
{
case WM_CLOSE:
EndModal(IDCANCEL);
break;
case WM_COMMAND:
if(HIWORD(wp) == BN_CLICKED)
{
switch(LOWORD(wp))
{
case BUTTON_OK:
if(login->DoLogin(textName.GetText(), textPassword.GetText()))
EndModal(IDOK);
break;
case BUTTON_CANCEL;
EndModal(IDCANCEL);
break;
}
}
}
return WindowModal::WndProc(window, message, wp, lp);
}
private:
LoginController* login;
TextBox textName;
TextBox textPassword;
};

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

using namespace neo;
class BindLambda : public Window
{
BindLambda()
{
Create(WindowParam());
Button button = Button(*this, L"Increase x", 0, 0, 0, 100, 25);
auto incr = [this](msgCommand&)
{
++x;
}
Bind(ButtonMessageId(button), incr);
}
int x;
};