wxWidgets开发资源与事件处理全解析
1. CD-ROM资源使用指南
1.1 浏览CD-ROM
CD-ROM可在Windows、Mac OS X、Linux(以及其他UNIX系统)下读取。在Windows和Linux系统中,插入CD-ROM后,HTML内容通常会自动打开。若未自动打开,可使用你偏好的网页浏览器打开文件“BrowseMe.htm”。
1.2 CD-ROM内容
CD-ROM中包含以下资源:
-
代码示例
:你可以将代码片段粘贴到自己的应用程序中,也可以使用你喜欢的编译器编译这些示例。除了常规示例外,还有一个额外的示例“Riffle”,这是一个小型图像浏览器,附带源代码、安装脚本以及四个平台的二进制文件。
-
wxWidgets 2.6
:支持Windows(桌面版和Pocket PC)、Unix/Linux、Mac OS X等多种平台。
-
DialogBlocks个人版
:这是一款用于个人使用的商业DialogBlocks对话框编辑器/RAD工具,可在Windows、Linux和Mac OS X上运行,具备强大的基于尺寸器的布局工具,能使用流行的编译器编译源代码。
-
编译器
:Windows系统提供MinGW、Digital Mars C++和OpenWatcom C++;Linux系统可从发行版安装GCC;Mac OS X可从苹果官网获取Apple Developer Tools。
-
poEdit
:这是一个重要工具,可帮助你为国际化应用程序创建消息目录。
-
wxPython
:它是wxWidgets和Python语言的强大结合。
如需更新内容,请访问http://www.wxwidgets.org/book 。
2. wxWidgets事件处理机制
2.1 事件处理流程概述
当从窗口系统接收到事件时,wxWidgets会在生成该事件的窗口所属的第一个事件处理对象上调用
wxEvtHandler::ProcessEvent
。事件表搜索顺序如下:
1. 若对象被禁用(通过调用
wxEvtHandler::SetEvtHandlerEnabled
),则跳过至步骤6。
2. 若对象是
wxWindow
,则递归调用该窗口的
wxValidator
上的
ProcessEvent
。若返回
true
,则函数退出。
3. 为该事件处理程序调用
SearchEventTable
。若失败,则尝试基类表,再尝试下一个基类表,依此类推,直到没有更多表或找到合适的函数,此时函数退出。
4. 对整个事件处理程序链进行搜索(通常链的长度为1)。若成功,函数退出。
5. 若对象是
wxWindow
且事件设置为传播(通常只有
wxCommandEvent
对象设置为传播),则递归应用
ProcessEvent
到父窗口的事件处理程序。若返回
true
,函数退出。
6. 最后,在
wxApp
对象上调用
ProcessEvent
。
2.2 事件传播特点
-
要特别注意步骤5,这是wxWidgets事件处理系统的强大特性,但人们常忽略或混淆。设置为传播的事件(通常直接或间接派生自
wxCommandEvent)会从子窗口向父窗口传播,直到达到最大传播级别或找到不调用Skip的事件处理程序。 - 当命令事件向上传播到父窗口时,若到达父对话框,事件传播会停止。这可避免在弹出模态对话框时收到来自对话框控件的意外事件。不过,事件会在框架之外继续传播。
- 基本窗口事件(如大小、移动、绘制、鼠标、键盘等)仅发送到窗口本身;具有更高意义或由窗口自身生成的事件(如按钮点击、菜单选择、树展开等)是命令事件,会发送到父窗口以查看其是否感兴趣。
-
你可以在应用程序中重写
ProcessEvent以重定向事件处理。为测试命令事件,可使用wxEvent::IsCommandEvent,比使用较慢的运行时类型系统更高效。
2.3 事件处理流程mermaid流程图
graph TD
A[开始] --> B{对象是否禁用}
B -- 是 --> F
B -- 否 --> C{对象是否为wxWindow}
C -- 是 --> D{递归调用wxValidator的ProcessEvent是否返回true}
D -- 是 --> End
D -- 否 --> E{SearchEventTable是否成功}
E -- 是 --> End
E -- 否 --> G{事件处理程序链搜索是否成功}
G -- 是 --> End
G -- 否 --> H{对象是wxWindow且事件可传播}
H -- 是 --> I{递归调用父窗口事件处理程序是否返回true}
I -- 是 --> End
I -- 否 --> F{调用wxApp的ProcessEvent}
F --> End
C -- 否 --> E
H -- 否 --> F
classDef startend fill:#F5EBFF,stroke:#BE8FED,stroke-width:2px;
classDef process fill:#E5F6FF,stroke:#73A6FF,stroke-width:2px;
classDef decision fill:#FFF6CC,stroke:#FFBC52,stroke-width:2px;
A,End:::startend
B,C,D,E,G,H,I,F:::decision
3. 常用事件宏总结
3.1 事件宏分类
在wxWidgets中,特定事件宏的文档按事件类(如
wxCommandEvent
)组织,而这些事件类又由控件类文档(如
wxButton
)引用。以下是一些常用事件类和宏的总结:
| 事件类 | 事件宏 | 说明 |
|---|---|---|
| wxActivateEvent | EVT_ACTIVATE(func) | 用户激活或停用顶级窗口时发送 |
| EVT_ACTIVATE_APP(func) | 用户激活或停用不同应用程序的窗口时发送 | |
| wxCommandEvent | EVT_COMMAND(id, event, func) | 与EVT_CUSTOM相同,但期望一个带有wxCommandEvent参数的成员函数 |
| EVT_COMMAND_RANGE(id1, id2, event, func) | 与EVT_CUSTOM_RANGE相同,但期望一个带有wxCommandEvent参数的成员函数 | |
| EVT_BUTTON(id, func) | 处理用户左键点击wxButton时生成的wxEVT_COMMAND_BUTTON_CLICKED事件 | |
| EVT_CHECKBOX(id, func) | 处理用户勾选或取消勾选wxCheckBox控件时生成的wxEVT_COMMAND_CHECBOX_CLICKED事件 | |
| EVT_CHECKLISTBOX(id, func) | 处理用户勾选或取消勾选wxCheckListBox控件中的项目时生成的wxEVT_COMMAND_CHECKLISTBOX_TOGGLED事件 | |
| … | … |
3.2 部分事件宏详细说明
-
EVT_TEXT_ENTER(id, func)
:处理用户在wxTextCtrl控件中按下Enter键时生成的wxEVT_COMMAND_TEXT_ENTER事件。注意,创建控件时需使用
wxTE_PROCESS_ENTER样式才能生成此类事件。 - EVT_UPDATE_UI(id, func) :用于处理用户界面更新伪事件,这些事件会触发应用程序更新菜单、工具栏和控件的视觉状态。
3. 常用事件宏总结(续)
3.3 更多事件类及宏说明
除了前面提到的事件类和宏,还有许多其他常用的事件类和宏,以下继续为大家详细介绍:
| 事件类 | 事件宏 | 说明 |
| — | — | — |
| wxCloseEvent | EVT_CLOSE(func) | 处理用户通过窗口管理器关闭窗口时生成的wxEVT_CLOSE_WINDOW事件,适用于wxFrame和wxDialog类,若CanVeto返回true,事件可被否决 |
| | EVT_QUERY_END_SESSION(func) | 处理会话即将结束但可被用户否决的wxEVT_QUERY_END_SESSION事件,仅适用于Windows系统的wxApp |
| | EVT_END_SESSION(func) | 处理会话即将结束时生成的wxEVT_END_SESSION事件,仅适用于Windows系统的wxApp |
| wxContextMenuEvent | EVT_CONTEXT_MENU(id, func) | 处理用户通过按下特殊键盘键(Windows下)或右键单击鼠标请求弹出菜单出现时生成的事件 |
| | EVT_COMMAND_CONTEXT_MENU(id, func) | 与EVT_CONTEXT_MENU相同,但需要一个窗口标识符 |
| wxEraseEvent | EVT_ERASE_BACKGROUND(func) | 处理窗口背景需要重绘时生成的wxEVT_ERASE_BACKGROUND事件 |
| wxEvent | EVT_CUSTOM(event, id, func) | 允许通过指定事件标识符(如wxEVT_SIZE)、窗口标识符和要调用的成员函数来添加自定义事件表条目 |
| | EVT_CUSTOM_RANGE(event, id1, id2, func) | 与EVT_CUSTOM相同,但响应一系列窗口标识符 |
| wxFocusEvent | EVT_SET_FOCUS(func) | 处理窗口获得键盘焦点时的wxEVT_SET_FOCUS事件 |
| | EVT_KILL_FOCUS(func) | 处理窗口失去键盘焦点时的wxEVT_KILL_FOCUS事件 |
| wxIdleEvent | EVT_IDLE(func) | 处理空闲时间(所有其他事件处理完毕)传递给Windows和应用程序对象的wxEVT_IDLE事件 |
| wxInitDialogEvent | EVT_INIT_DIALOG(func) | 处理对话框初始化时发送的wxEVT_INIT_DIALOG事件 |
| wxKeyEvent | EVT_CHAR(func) | 处理用户按键时生成的wxEVT_CHAR事件,提供翻译后的键码值 |
| | EVT_KEY_DOWN(func) | 处理用户按键时生成的wxEVT_KEY_DOWN事件,提供未翻译的键码值 |
| | EVT_KEY_UP(func) | 处理按键释放时生成的wxEVT_KEY_UP事件,提供未翻译的键码值 |
3.4 鼠标、滚动等事件宏
鼠标和滚动相关的事件在界面交互中非常重要,以下是这些事件类对应的宏及其说明:
鼠标事件
| 事件类 | 事件宏 | 说明 |
|---|---|---|
| wxMouseEvent | EVT_LEFT_DOWN(func) | 处理左鼠标按钮变为“按下”状态时生成的wxEVT_LEFT_DOWN事件 |
| EVT_LEFT_UP(func) | 处理左鼠标按钮变为“释放”状态时生成的wxEVT_LEFT_UP事件 | |
| EVT_LEFT_DCLICK(func) | 处理左鼠标按钮双击时生成的wxEVT_LEFT_DCLICK事件 | |
| EVT_MIDDLE_DOWN(func) | 处理中鼠标按钮变为“按下”状态时生成的wxEVT_MIDDLE_DOWN事件 | |
| EVT_MIDDLE_UP(func) | 处理中鼠标按钮变为“释放”状态时生成的wxEVT_MIDDLE_UP事件 | |
| EVT_MIDDLE_DCLICK(func) | 处理中鼠标按钮双击时生成的wxEVT_MIDDLE_DCLICK事件 | |
| EVT_RIGHT_DOWN(func) | 处理右鼠标按钮变为“按下”状态时生成的wxEVT_RIGHT_DOWN事件 | |
| EVT_RIGHT_UP(func) | 处理右鼠标按钮变为“释放”状态时生成的wxEVT_RIGHT_UP事件 | |
| EVT_RIGHT_DCLICK(func) | 处理右鼠标按钮双击时生成的wxEVT_RIGHT_DCLICK事件 | |
| EVT_MOTION(func) | 处理鼠标移动时生成的wxEVT_MOTION事件 | |
| EVT_ENTER_WINDOW(func) | 处理鼠标进入窗口时生成的wxEVT_ENTER_WINDOW事件 | |
| EVT_LEAVE_WINDOW(func) | 处理鼠标离开窗口时生成的wxEVT_LEAVE_WINDOW事件 | |
| EVT_MOUSEWHEEL(func) | 处理鼠标滚轮移动时生成的wxEVT_MOUSEWHEEL事件 | |
| EVT_MOUSE_EVENTS(func) | 处理所有鼠标事件 |
滚动事件
| 事件类 | 事件宏 | 说明 |
|---|---|---|
| wxScrollEvent | EVT_SCROLL(func) | 处理所有滚动事件 |
| EVT_SCROLL_TOP(func) | 处理滚动到顶部(最小位置)的wxEVT_SCROLL_TOP事件 | |
| EVT_SCROLL_BOTTOM(func) | 处理滚动到底部(最大位置)的wxEVT_SCROLL_BOTTOM事件 | |
| EVT_SCROLL_LINEUP(func) | 处理向上滚动一行的wxEVT_SCROLL_LINEUP事件 | |
| EVT_SCROLL_LINEDOWN(func) | 处理向下滚动一行的wxEVT_SCROLL_LINEDOWN事件 | |
| EVT_SCROLL_PAGEUP(func) | 处理向上滚动一页的wxEVT_SCROLL_PAGEUP事件 | |
| EVT_SCROLL_PAGEDOWN(func) | 处理向下滚动一页的wxEVT_SCROLL_PAGEDOWN事件 | |
| EVT_SCROLL_THUMBTRACK(func) | 处理用户拖动滚动条时频繁发送的wxEVT_SCROLL_THUMBTRACK事件 | |
| EVT_SCROLL_THUMBRELEASE(func) | 处理滚动条拇指释放时的wxEVT_SCROLL_THUMBRELEASE事件 | |
| EVT_SCROLL_ENDSCROLL(func) | 处理滚动结束事件(仅Windows系统) | |
| EVT_COMMAND_SCROLL(id, func) | 处理所有滚动事件 |
3.5 其他事件类及宏
还有一些其他的事件类和宏,涵盖了窗口移动、页面切换、绘制等多种场景:
| 事件类 | 事件宏 | 说明 |
| — | — | — |
| wxMoveEvent | EVT_MOVE(func) | 处理窗口移动时生成的wxEVT_MOVE事件 |
| wxNotebookEvent | EVT_NOTEBOOK_PAGE_CHANGED(id, func) | 处理笔记本页面选择更改事件 |
| | EVT_NOTEBOOK_PAGE_CHANGING(id, func) | 处理笔记本页面选择即将更改事件,可使用Veto否决选择更改 |
| wxPaintEvent | EVT_PAINT(func) | 处理窗口区域需要重绘时生成的wxEVT_PAINT事件 |
| wxSizeEvent | EVT_SIZE(func) | 处理窗口大小调整时生成的wxEVT_SIZE事件 |
| wxSpinEvent | EVT_SPIN(id, func) | 处理wxSpinButton或wxSpinCtrl的上下箭头点击时生成的wxEVT_SCROLL_THUMBTRACK事件 |
| | EVT_SPIN_UP(id, func) | 处理wxSpinButton或wxSpinCtrl的上箭头点击时生成的wxEVT_SCROLL_LINEUP事件 |
| | EVT_SPIN_DOWN(id, func) | 处理wxSpinButton或wxSpinCtrl的下箭头点击时生成的wxEVT_SCROLL_LINEDOWN事件 |
| | EVT_SPINCTRL(id, func) | 处理wxSpinCtrl生成的所有事件 |
| wxSplitterEvent | EVT_SPLITTER_SASH_POS_CHANGING(id, func) | 处理分割器窗格位置正在更改时生成的wxEVT_COMMAND_SPLITTER_SASH_POS_CHANGING事件 |
| | EVT_SPLITTER_SASH_POS_CHANGED(id, func) | 处理分割器窗格位置更改时生成的wxEVT_COMMAND_SPLITTER_SASH_POS_CHANGED事件,可用于在设置位置前修改或阻止更改 |
| | EVT_SPLITTER_UNSPLIT(id, func) | 处理分割器取消分割时生成的wxEVT_COMMAND_SPLITTER_UNSPLIT事件 |
| | EVT_SPLITTER_DCLICK(id, func) | 处理分割器窗格双击时生成的wxEVT_COMMAND_SPLITTER_DOUBLECLICKED事件 |
| wxSysColourChangeEvent | EVT_SYS_COLOUR_CHANGED(func) | 处理用户在控制面板中更改颜色时生成的wxEVT_SYS_COLOUR_CHANGED事件(仅Windows系统) |
| wxUpdateUIEvent | EVT_UPDATE_UI(id, func) | 处理用户界面更新伪事件,触发应用程序更新菜单、工具栏和控件的视觉状态 |
| | EVT_UPDATE_UI_RANGE(id1, id2, func) | 处理一系列标识符的wxEVT_UPDATE_UI事件 |
| wxWindowCreateEvent | EVT_WINDOW_CREATE(func) | 处理底层窗口刚创建时生成的wxEVT_CREATE传播事件 |
| wxWindowDestroyEvent | EVT_WINDOW_DESTROY(func) | 处理窗口即将销毁时生成的wxEVT_DELETE传播事件 |
4. 总结
通过对CD-ROM资源的介绍,我们了解到可以利用其中丰富的代码示例、开发工具和库来辅助wxWidgets的开发。而事件处理机制是wxWidgets开发中的核心部分,它决定了程序如何响应各种用户操作和系统事件。详细的事件宏总结为开发者提供了便捷的参考,使得在处理不同类型的事件时能够快速找到合适的宏来使用。
在实际开发中,开发者可以根据具体的需求选择合适的资源和事件处理方式,灵活运用这些知识来构建功能强大、交互性好的应用程序。同时,对事件传播和处理流程的深入理解有助于避免一些常见的开发误区,提高开发效率和程序的稳定性。
希望以上内容能帮助大家更好地掌握wxWidgets的开发技巧,在实际项目中取得更好的成果。
超级会员免费看

1268

被折叠的 条评论
为什么被折叠?



