3.5 动态事件处理方法
前面我们讨论的事件处理方法,都是静态的事件表,这也是我们处理事件最常用的方式。接下来,我们来讨论一下事件表的动态处理,也就是说在运行期改变事件表的映射关系。使用这种事件映射方法的原因,可能是你想在程序运行的不同时刻使用不同的映射关系,或者因为你使用的那种语言(例如python)不支持静态映射,或者仅仅是因为你更喜欢动态映射。因为动态映射的方法可以使你更精确的控制事件表的细节,你甚至可以单独的将事件表中的某一个条目在运行期打开或者关闭,而前面说的PushEventHandler和PopEventHandler的方法只能针对整个事件表进行处理。除此以外,动态事件处理还允许你在不同的类之间共享事件函数。
和动态事件处理相关的API有两个:wxEvtHandler::Connect和wxEvtHandler::Disconnect。大多数情况下你不需要手动调用wxEvtHandler::Disconnect函数,这个函数将在窗口类被释放的时候自动。
下面我们还用前面的MyFrame类来举例说明:
class MyFrame : public wxFrame
{
public:
MyFrame(const wxString& title);
void OnQuit(wxCommandEvent& event);
void OnAbout(wxCommandEvent& event);
private:
};
你可能已经注意到,这次我们没有使用DECLARE_EVENT_TABLE来声明一个事件表。为了动态进行事件映射,我们需要在OnInit函数中增加下面的代码:
frame->Connect( wxID_EXIT,
wxEVT_COMMAND_MENU_SELECTED,
wxCommandEventHandler(MyFrame::OnQuit) );
frame->Connect( wxID_ABOUT,
wxEVT_COMMAND_MENU_SELECTED,
wxCommandEventHandler(MyFrame::OnAbout) );
我们传递给Connect函数的三个参数分别为菜单标识符,事件标识符和事件处理函数指针。要注意这里的事件标识符 wxEVT_COMMAND_MENU_SELECTED不同于前面在静态事件表中用于表示事件映射的宏EVT_MENU,实际上EVT_MENU内部也使用了wxEVT_COMMAND_MENU_SELECTED.EVT_MENU其实也自动包含了用于对事件处理指针类型强制转换的宏 wxCommandEventHandler()。一般说来,如果事件处理函数的参数类型是wxXYZEvent,那么其处理函数的类型就应该用 wxXYZEventHandler宏进行强制转换.
如果我们希望在某个时候中止上面的事件映射,可以使用下面的方法:
frame->Disconnect( wxID_EXIT,
wxEVT_COMMAND_MENU_SELECTED,
wxCommandEventHandler(MyFrame::OnQuit) );
frame->Disconnect( wxID_ABOUT,
wxEVT_COMMAND_MENU_SELECTED,
wxCommandEventFunction(MyFrame::OnAbout) );