严谨来说,wxwidgets中每个事件都可以被以下三个事件描述:
1.事件类型
它是一个唯一标识事件类型的东西,当然是宏定义的形式,例如#define wxEVT_COMMAND_BUTTON_CLICKED wxEVT_BUTTON它标识按键点击这个事件类型
2.事件所携带的事件类
每个事件都会有与之相关的信息,这些数据的传递是通过那些从wxevent派生的类实现的,而不同类型的事件可以使用相同的事件类,比如按button和选择listbox都使用wxcommandevent类(所有的control events都是用它)。但是键盘事件使用wxkeyevent,因为它们携带的信息不同。
3.事件源
wxevent(事件所携带的事件类)保存了产生事件的东西,对窗口来说,就是他的标识id,而很多时候会有许多object产生相同种类的事件(比如一个窗口有好几个按键, 它们都产生相同的按键点击事件),检查事件源或id来分辨它们。
event
Event Handling
evenhanding
上面说了事件,下面谈谈事件处理。每一个wxEvtHandler的派生类(所有继承自wxwindows的窗口类及应用程序类都是wxEvtHandler的派生类),例如frame,按钮,菜单等都在内部维护一个事件表(这里指静态事件表与动态绑定),通过这个表将事件与事件处理函数关联在一起。
在wxwi中有两种主要的处理事件的方法,即事件表宏和动态绑定。事件表将在编译期间将事件与其处理函数静态的关联,而动态绑定发生在运行期间,而且还可以解除绑定。动态绑定可以直接将事件和以下处理绑定:1.别的object的处理2.普通函数3.一些库函数,像boost::function<>和std::function<>。
3.为每一个你想处理的事件定义一个事件处理函数。
例如:
MyFrame::OnButton1(wxCommandEvent& event) {.../*处理*/} 4.在cpp文件中使用wxBEGIN_EVENT_TABLE和wxEND_EVENT_TABLE()实现一个事件表,在其中增加事件宏,它将把事件与其处理函数关联起来。
例如:
wxBEGIN_EVENT_TABLE(MyFrame, wxFrame) EVT_BUTTON(BUTTON1, MyFrame::OnButton1) wxEND_EVENT_TABLE() 其中onbutton1就是事件处理函数。而第一个参数button1就是上面说的事件源。evt_button是预设事件宏。而第三步中MyFrame::OnButton1函数参数就是一个事件类的引用。假设你要实现按button1来显示一个helloworld信息,步骤可能是这样的:1.点击按键,产生按键点击事件(最前面说的事件类)。2.myframe窗口捕捉到这个事件,先查询在wxbutton中是否有符合条件的处理(如果找不到会到其基类的事件表查找,再找不到会到窗口控件的父子继承树中查找,比如这里正在说的在myframe中找到了),通过myframe中事件表得知对于标识符为button1(前面说的事件源)的按键事件应该发送到onbutton1函数,所以把携带事件信息的事件类传递给这个函数,后面就是处理函数处理过程,即弹出对话框显示helloworld。那么最前面说的事件类型在哪里会被用到呢?其实点击按键时产生的事件类wxCommandEvent包含标识符button1和事件类型wxEVT_COMMAND_BUTTON_CLICKED,这两样结合起来在各个事件表中查找是否有对应处理。注意:只有Command事件(指的是直接或间接继承自wxCommandEvent的事件)才会被递归的应用到其父窗口的事件表。因为非command事件只对产生它的窗口有意义。例如把一个子窗口的重绘事件发给它的父窗口就没有意义。)不会传递给其父窗口的事件表处理的事件如下:wxActivate,wxCloseEvent,wxEraseEvent,wxFocusEvent,wxKeyEvent,wxIdleEvent,wxInitDialogEvent,wxJoystickEvent,wxMenuEvent,wxMouseEvent,wxMoveEvent,wxPaintEvent,wxQueryLayoutInfoEvent,wxSizeEvent,wxScrollWinEvent,wxSysColourChangedEvent
当同时存在静态与动态处理对于同一事件,静态将会被执行。