为了简单起见,我封装了一个UIEvent类,用户可以通过相关函数解析WPARAM/LPARAM或者自行处理,不在事件枚举中的不常见事件也可以通过重载MsgHandler截获到。

至于Notify机制,原先我想的是在UIWindow中记录控件名-消息-函数的映射,然后在消息响应时查表即可。但是后来考虑了一下为了可拓展性强,势必要允许类似WM_MOUSEMOVE这类频繁调用的函数被响应,这样会造成严重的性能下降,而且反复查找的效率也不高。
因此我就用空间换时间,在每个控件中开一个MsgHandleFun msgmap_[kWM_End_]函数指针数组,设置的时候查找一次,然后控件记录对应消息的函数指针,这样在窗口收到消息之后,通过原先的消息机制发送给控件,控件直接根据消息的值调用数组中的函数执行响应就行了,避免了每次查找浪费时间。

类似MFC的事件绑定,我也弄了一套宏,注意这里涉及了成员函数指针,和普通函数指针完全不同,参看这里

1
2
3
4
5
#define MSG_MAP_BEGIN(theclass)         virtual void _CtrlBindMsgHandler() { \
typedef theclass _thisclass;
#define ON_CONTROL_MSG(name, msg, func) BindMsgHandler(name, msg, static_cast<MsgHandleFun>(&thisclass::func));
#define ON_PARENT_MSG(parentclass) parentclass::_CtrlBindMsgHandler();
#define MSG_MAP_END }

当然如果使用C++11的bind/function可以更加简单:

1
#define ON_CONTROL_MSG(name, msg, func)     BindMsgHandler(name, msg, std::bind(&_thisclass::func, this, std::placeholders::_1));

还可以资瓷Lambda表达式,这是极好的。

避免每次ON_CONTROL_MSG都要带上类名,直接在MSG_MAP_BEGIN中记录下类名,原先我并没有想到怎么记录,还是参考了MFC的类似绑定宏的定义,typedef重命名这个方法实在是很巧妙,学习一个。

大致流程:
2018020504371511.jpg