[Effective WX] 理解wxWidget中event相关的宏
2012-08-15 10:15
190 查看
wxWidget中的事件响应的方式,是基于事件表的方式,而不是采用虚函数的方式。
假如针对一个wxWindow类型的窗口,想要响应这个窗口的一些事件,通常我们会这样写:
MyWindow.h文件
class MyWindow : public wxWindow
{
...
DECLARE_EVENT_TABLE()
};
MyWindow.cpp文件:
#include "MyWindow.h"
BEGIN_EVENT_TABLE( MyWindow, wxWindow )
EVT_XXX_EVENT(wxMy_EVENT_ID, MyWindow::OnMyEventFunc)
END_EVENT_TABLE()
可以看到有很多宏替我们做了很多事情,但是到底做了什么事情呢?
1. DECLARE_EVENT_TABLE
当我们在某个类中添加这个宏时,其实是对这个类添加了一个静态的事件响应表/数组(sm_eventTableEntries),表中的每一项是事件类型与事件响应函数的组合。
2. BEGIN_EVENT_TABLE
BEGIN_EVENT_TABLE其实是开始初始化这个静态的事件响应表,及其相关的静态函数。
3. END_EVENT_TABLE
可以看到END_EVENT_TABLE仅仅是插入一个空的EVENT ETNRY到表中,代表结束。
4. DECLARE_EVENT_TABLE_ENTRY
事件响应表中的每一项其实都是结构体,包含着事件类型,来自于哪个窗口,对应的响应函数,以及其它参数。
5. 如何添加/定义一个事件类型?
一个事件类型用ID来表示,INT类型。而且在这次事件链中必须是唯一的。声明一个事件类型借用宏DECLARE_EXPORTED_EVENT_TYPE,也仅仅是将全部事件整型值导出。通常声明在头文件中,定义在实现文件中。
譬如要定义一个事件类型wxEVT_GRID_CELL_LEFT_CLICK:
实现文件有如下定义:(请注意:wxEventType是int类型的typedef,也就是说,开始时所有的event type都是0)
针对这个事件类型,定义它的事件响应函数,并将它们绑定起来形成event entry,插入到事件表中:
定义一个定制的事件类型,编程思路差不多。
关于event entry结构体,有以下定义:
m_eventType用了常量引用,一开始都是0,之后会是一个有效的值。(暂不清楚这个值是在哪里重新赋值的。)
假如针对一个wxWindow类型的窗口,想要响应这个窗口的一些事件,通常我们会这样写:
MyWindow.h文件
class MyWindow : public wxWindow
{
...
DECLARE_EVENT_TABLE()
};
MyWindow.cpp文件:
#include "MyWindow.h"
BEGIN_EVENT_TABLE( MyWindow, wxWindow )
EVT_XXX_EVENT(wxMy_EVENT_ID, MyWindow::OnMyEventFunc)
END_EVENT_TABLE()
可以看到有很多宏替我们做了很多事情,但是到底做了什么事情呢?
1. DECLARE_EVENT_TABLE
#define DECLARE_EVENT_TABLE() \ private: \ static const wxEventTableEntry sm_eventTableEntries[]; \ protected: \ static const wxEventTable sm_eventTable; \ virtual const wxEventTable* GetEventTable() const; \ static wxEventHashTable sm_eventHashTable; \ virtual wxEventHashTable& GetEventHashTable() const;
当我们在某个类中添加这个宏时,其实是对这个类添加了一个静态的事件响应表/数组(sm_eventTableEntries),表中的每一项是事件类型与事件响应函数的组合。
2. BEGIN_EVENT_TABLE
#define BEGIN_EVENT_TABLE(theClass, baseClass) \ const wxEventTable theClass::sm_eventTable = \ { &baseClass::sm_eventTable, &theClass::sm_eventTableEntries[0] }; \ const wxEventTable *theClass::GetEventTable() const \ { return &theClass::sm_eventTable; } \ wxEventHashTable theClass::sm_eventHashTable(theClass::sm_eventTable); \ wxEventHashTable &theClass::GetEventHashTable() const \ { return theClass::sm_eventHashTable; } \ const wxEventTableEntry theClass::sm_eventTableEntries[] = { \
BEGIN_EVENT_TABLE其实是开始初始化这个静态的事件响应表,及其相关的静态函数。
3. END_EVENT_TABLE
#define END_EVENT_TABLE() DECLARE_EVENT_TABLE_ENTRY( wxEVT_NULL, 0, 0, 0, 0 ) };
可以看到END_EVENT_TABLE仅仅是插入一个空的EVENT ETNRY到表中,代表结束。
4. DECLARE_EVENT_TABLE_ENTRY
事件响应表中的每一项其实都是结构体,包含着事件类型,来自于哪个窗口,对应的响应函数,以及其它参数。
#define DECLARE_EVENT_TABLE_ENTRY(type, winid, idLast, fn, obj) \ wxEventTableEntry(type, winid, idLast, fn, obj)
5. 如何添加/定义一个事件类型?
一个事件类型用ID来表示,INT类型。而且在这次事件链中必须是唯一的。声明一个事件类型借用宏DECLARE_EXPORTED_EVENT_TYPE,也仅仅是将全部事件整型值导出。通常声明在头文件中,定义在实现文件中。
譬如要定义一个事件类型wxEVT_GRID_CELL_LEFT_CLICK:
#define BEGIN_DECLARE_EVENT_TYPES() #define END_DECLARE_EVENT_TYPES() #define DECLARE_EXPORTED_EVENT_TYPE(expdecl, name, value) \ extern expdecl const wxEventType name; BEGIN_DECLARE_EVENT_TYPES() DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_ADV, wxEVT_GRID_CELL_LEFT_CLICK, 1580) // more event type, add here. END_DECLARE_EVENT_TYPES()
实现文件有如下定义:(请注意:wxEventType是int类型的typedef,也就是说,开始时所有的event type都是0)
#define DEFINE_EVENT_TYPE(name) const wxEventType name = wxNewEventType(); DEFINE_EVENT_TYPE(wxEVT_GRID_CELL_LEFT_CLICK)
针对这个事件类型,定义它的事件响应函数,并将它们绑定起来形成event entry,插入到事件表中:
#define wx__DECLARE_EVT2(evt, id1, id2, fn) \ DECLARE_EVENT_TABLE_ENTRY(evt, id1, id2, fn, NULL), #define wx__DECLARE_EVT1(evt, id, fn) \ wx__DECLARE_EVT2(evt, id, wxID_ANY, fn) typedef void (wxEvtHandler::*wxGridEventFunction)(wxGridEvent&); #define wxGridEventHandler(func) \ (wxObjectEventFunction)(wxEventFunction)wxStaticCastEvent(wxGridEventFunction, &func) #define wx__DECLARE_GRIDEVT(evt, id, fn) \ wx__DECLARE_EVT1(wxEVT_GRID_ ## evt, id, wxGridEventHandler(fn)) #define EVT_GRID_CMD_CELL_LEFT_CLICK(id, fn) wx__DECLARE_GRIDEVT(CELL_LEFT_CLICK, id, fn)
定义一个定制的事件类型,编程思路差不多。
关于event entry结构体,有以下定义:
// an entry from a static event table struct WXDLLIMPEXP_BASE wxEventTableEntry : public wxEventTableEntryBase { wxEventTableEntry(const int& evType, int winid, int idLast, wxObjectEventFunction fn, wxObject *data) : wxEventTableEntryBase(winid, idLast, fn, data), m_eventType(evType) { } // the reference to event type: this allows us to not care about the // (undefined) order in which the event table entries and the event types // are initialized: initially the value of this reference might be // invalid, but by the time it is used for the first time, all global // objects will have been initialized (including the event type constants) // and so it will have the correct value when it is needed const int& m_eventType; private: wxEventTableEntry& operator=(const wxEventTableEntry&); };
m_eventType用了常量引用,一开始都是0,之后会是一个有效的值。(暂不清楚这个值是在哪里重新赋值的。)
相关文章推荐
- [Effective WX] 理解wxWidget中wxGrid相关类的关系
- 深入理解iOS API系列(三)UiView事件传递相关函数:pointInside:withEvent:和hittest:withevent:
- [Effective WX] 理解wxWidget跨平台的实现方法
- smarty相关理解
- 大型企业网络配置系列课程详解(四) --HSRP和VRRP配置与相关概念的理解
- Android开发之深入理解Android 7.0系统权限更改相关文档
- Python多线程的创建,相关函数和守护线程的理解
- Android事件传递机制以及ViewGroup的onInterceptTouchEvent的理解
- 非局部均值图像恢复的相关理解
- 深度学习 4. MatConvNet 相关函数解释说明,MatConvNet 细节理解,MatConvNet 代码理解
- php闭包相关理解
- Zookeeper相关内容及简单理解、安装
- DLL的相关理解01
- 图论相关算法理解和总结
- 指针运算相关问题的理解
- IOS获取各个文件目录路径的方法以及相关沙盒机制理解
- 理解Mac和iOS中的 Event 处理
- D3D动画相关接口理解
- 大型企业网络配置系列课程详解(一)---OSPF单区域配置与相关概念的理解
- 大型企业网络配置系列课程详解(五) --Frame-Relay配置与相关概念的理解 推荐