2.4 事件处理函数

你也许已经注意到了,事件处理函数在MyFrame类中不是虚函数。如果不是虚函数,他们是怎样被调用的呢?答案就在下面的事件表里:

BEGIN_EVENT_TABLE(MyFrame, wxFrame)
    EVT_MENU(wxID_ABOUT, MyFrame::OnAbout)
    EVT_MENU(wxID_EXIT,  MyFrame::OnQuit)
END_EVENT_TABLE()

所谓事件表,是一组位于类的实现文件(.cpp文件)中的宏,用来告诉wxWidgets来自用户或者其它地方的事件应该怎样和类的成员函数对应起来。

前面展示的事件表表明,要把鼠标点击标识分别为wxID_EXIT和wxID_ABOUT的菜单项的事件和MyFrame的成员函数OnAbout和 OnQuit关联起来。这里的EVT_MENU宏只是很多中事件宏的其中之一,事件宏的作用是告诉wxWidgets哪种事件应该被关联到哪个成员函数。这里的两个标识wxID_ABOUT和wxID_EXIT是wxWidgets预定义的宏,通常你应该通过枚举,常量或者预编译宏的方式定义你自己的标识。

用上面的方法定义的时间表是一种静态的事件表,它不可以在运行期改变,在下一章里,我们将描述怎样定义可以在运行期改变的动态事件表。

现在,让我们来看看这两个事件处理函数.

void MyFrame::OnAbout(wxCommandEvent& event)
{
    wxString msg;
    msg.Printf(wxT("Hello and welcome to %s"),
               wxVERSION_STRING);
    wxMessageBox(msg, wxT("About Minimal"),
                 wxOK | wxICON_INFORMATION, this);
}



void MyFrame::OnQuit(wxCommandEvent& event)
{
    Close();
}

当用户点击关于菜单项的时候,MyFrame::OnAbout函数弹出一个消息框。这用到了wxWidgets提供的API wxMessageBox,它的四个参数分别代表消息内容,标题,窗口类型以及父窗口。

当用户点击退出菜单项的时候,MyFrame::OnQuit函数被调用(你已经意识到了,这是事件表的功劳)。它调用wxFrame类的Close函数来释放frame窗口。因为没有别的窗口存在了,这触发了应用程序的退出,实际上,wxFrame类的Close函数并不直接关闭 frame窗口,而是产生一个wxEVT_CLOSE_WINDOW事件,这个事件默认的处理函数调用wxWindow::Destroy函数释放了 frame窗口。

用户还可以通过别的方法关掉应用程序,比如通过点击标题栏上的关闭按钮或者是通过系统菜单中的关闭菜单,在这种情况下,OnQuit函数是怎样被调用的呢?事实上,在这种情况,OnQuit函数并没有被调用。这时,wxWidgets会通过Close函数(象OnQuit中的那样),给 frame窗口发送一个wxEVT_CLOSE_WINDOW事件,这个事件默认的处理函数会释放掉frame窗口。在你的应用程序中,可以通过重载这个处理函数来增加改变这种默认的行为,比如:如果你想问一问你的用户是不是真的要关闭窗口。关于这种处理的细节,可以参见第4章,"窗口基础"。

另外,大多数的应用程序类还应该重载一个OnExit函数,以便在任何时候程序退出时,执行一下清理和资源回收的动作。需要注意的是,这个函数只有在OnInit函数返回真的时候才会被执行。当然,我们这个小例子程序就用不着定义这个函数了。