GUI库:使本机应用程序具备Windows窗体的简易性
2010-10-15 09:07:42 来源:Web开发网请注意,此代码相当简单;没有类似 "enum {IDD = ...}" 的向导样式代码或消息映射。如果您不需要自定义构造函数则不需要提供,使用默认的构造函数即可。
登录类只从 form_resource::login 派生,而 form_resource::login 是在 login_form_resource.h(此文件由 eGUI++ 库维护)中实现的;form_resource::login 类包含有关窗体的控件的信息(它们的名称和类型,以及从控件捕捉通知的能力);您可以选择更改派生的可访问性类型,不过我反对这样做。像您的类成员数据通常是私有的一样,窗体同样如此 — 其控件应是私有的。
这样,生成的 form_resource::login 看起来类似于以下代码:
// login_form_resource.h
#pragma once
struct form_resource::login {
// ... (code to allow
// handling of notifications)
wnd<edit> username;
wnd<edit> passw;
wnd<button> ok, cancel;
};
这使您可以轻松地处理窗体的控件。假设您希望确保密码是“secretword”:
void login::on_button_click(ev::button_click &, ok_) {
if ( passw->text == "secretword")
{ pass_ok = true; visible = false; }
}
您可以看到,像使用 Visual Basic® 一样,要隐藏窗体,只需将其 visible 属性设置为 false。
脱离旧 ID
您以前可能处理过资源编辑器,并且遇到过许多资源前缀类型,例如 ID_、IDD_、IDC_、IDR_、IDS_ 等。前缀适用于资源编辑器。但是,在代码中,它们只是额外信息,您不需要记住或考虑它们。在 eGUI++ 应用程序中,因为这些前缀会被彻底忽略,所以您根本不需要记。
例如,以前的名称(username、passw、ok、cancel)是资源编辑器的快捷方式。eGUI++ 库自动去除了它们的 ID* 前缀。而原始名称本应为 IDC_username、IDC_passw、IDOK 和 IDCANCEL。
事件和通知
我曾提到,您无需记住单个 WM_ 消息。也就是说,事件是很难驯服的。事件实在太多了,所以您需要一种简便方法来找出您可以响应的事件并轻松地响应它们。您需要找到简便的方法,以便在窗体控件上发生事件时您能够得到通知,从而可以扩展控件和添加自己的事件。
每个窗口类(控件或窗体)都可以生成事件。对于每个窗口类,都有一个可捕捉所有事件的事件处理程序。对于每个事件,都会定义一个函数来处理该事件;该函数是虚拟的,其实现不会起任何作用。每个事件处理程序函数都具有一个参数:事件数据。
对于现有控件,对应的事件类称为 handle_events::control_name。每个现有 eGUI++ 窗口类 wnd_name 都已从 handle_events::wnd_name 派生。如果扩展现有的窗口类,则您始终可以处理其事件。(简而言之,所有事件处理程序函数均以“on_”开始。)例如:
struct my_btn : button {
void on_char(ev::char& e) {
cout << "typed " << e.ch;
}
};
如果您曾处理过其他 GUI 库,就会知道眼见不一定为凭,事情没有您想的那么简单。现有的控件不发送事件,而是发送通知。通知以 WM_COMMAND/WM_NOTIFY 消息的形式发送,并且发送到该控件的父级,而不发送到该控件自身。最初,这似乎很合乎情理:确实是控件的父级(窗体)需要通知。但是,这使扩展控件类变得相当困难。如果您希望构建树来使当前文件系统可视化,该如何做呢?您需要捕获将要发送到控件的父级的事件,如项目扩展 (TVN_ITEMEXPANDING)。接着,您需要一种方法将通知向下传递到控件自身。
对于 eGUI++ 来说,通知便是事件。因此,这些通知总是发送到控件,然后发送到控件的父级。当通过继承扩展控件类时,每个通知都将转换成其他事件。例如,如果您希望在用户编辑第一个列时创建显示复合框的列表控件而不是编辑控件,代码应该如下所示:
struct list_with_combo : list {
...
void on_begin_label_edit(
ev::begin_label_edit & e) {
e.allow_default = false;
combo->rect(...);
combo->visible = true;
}
wnd<combo_box> combo;
};
要处理事件,需重载事件处理程序函数,如下所示:
struct my_btn : button {
void on_char(ev::char& e);
};
更多精彩
赞助商链接