《Cross - Platform GUI Programming with wxWidgets》主要介绍了使用wxWidgets进行跨平台GUI编程的相关知识,包括wxWidgets的基本概念、入门示例、事件处理、窗口基础、绘图与打印、输入处理、窗口布局等内容。
### 1. wxWidgets概述
- **定义与功能**:wxWidgets是用于编写桌面或移动应用程序图形用户界面的编程工具包,也是一个框架,为程序员提供大量类和方法,可创建包含标准控件、绘制图像、响应多种输入的应用程序,且其功能不仅限于GUI开发,还涉及应用程序开发的多个方面。
- **使用优势**
- **跨平台性**:可使应用程序在不同操作系统上保持原生外观和感觉,如在Windows、Mac OS X和Linux上呈现出符合相应平台风格的界面。
- **开源免费**:开发者可免费使用,且代码开源,便于开发者根据需求修改源代码。
- **社区支持**:拥有活跃的社区,提供邮件列表、网站、论坛等资源,方便开发者交流、获取帮助,还有众多衍生项目。
- **行业应用广泛**:用户涵盖从个人开发者到大型企业、从学术机构到科研领域等众多领域,众多知名企业和开源项目都在使用。
- **历史发展**:年由Julian Smart在爱丁堡大学开发,最初用于部署跨平台的绘图工具,后逐渐发展壮大,不断有新的开发者加入,功能持续完善,经历了多次版本更新和功能扩展,未来计划包括改进工具、增强功能等。
- **架构与端口**
- **架构分层**:包括公共代码层、通用代码层、wxUniversal层、平台特定代码层、贡献代码层和第三方代码层,各层协同工作以实现wxWidgets API。
- **主要端口**:如wxMSW(适用于Microsoft Windows操作系统)、wxGTK(用于GTK +环境)、wxX11(基于X11和wxUniversal)、wxMotif(用于Motif环境)、wxMac(针对Mac OS)、wxCocoa(针对Mac OS X的Cocoa API)、wxWinCE(适用于Windows CE平台)、wxPalmOS(用于Palm OS 6)、wxOS2(用于OS/2或eComStation)、wxMGL(基于SciTech Software的MGL层)等,不同端口在不同操作系统或环境下提供相应功能。
### 2. 入门示例
- **最小示例程序结构**
- **应用程序类**:每个wxWidgets应用程序需定义一个派生自wxApp的类,如MyApp,其OnInit函数在程序启动时被调用,用于创建主窗口、处理命令行参数、设置数据等,若返回true则启动事件循环。
- **框架类**:MyFrame是主框架类,派生自wxFrame,包含构造函数、事件处理函数(如OnQuit、OnAbout)和事件表,用于创建带有菜单和状态栏的主窗口,并处理相关事件。
- **事件处理**:通过事件表将菜单事件(如wxID_ABOUT、wxID_EXIT)与相应的处理函数(OnAbout、OnQuit)关联,处理函数实现具体的功能,如显示关于对话框或关闭窗口。
- **程序流程**
- **启动与初始化**:根据平台,由wxWidgets提供的main、WinMain或等效函数运行,初始化内部数据结构并创建MyApp实例,然后调用MyApp::OnInit。
- **窗口创建与显示**:MyApp::OnInit创建MyFrame实例,MyFrame构造函数创建窗口、设置图标、菜单和状态栏,最后显示框架并返回true启动事件循环。
- **事件循环与处理**:wxWidgets等待事件,将事件分发到相应的处理函数,应用程序持续运行,直到所有顶层窗口关闭。
### 3. 事件处理
- **事件驱动编程原理**:GUI应用程序通过事件循环等待用户或其他来源的事件,如窗口刷新、鼠标操作、键盘输入、套接字连接等,然后将事件分发到相应的处理函数进行处理,大多数GUI应用程序虽看似多任务并行,但实际非多线程,任务依次执行。
- **事件表与静态事件处理**
- **事件表创建步骤**:定义派生自wxEvtHandler的类,为需处理的事件添加成员函数,用DECLARE_EVENT_TABLE声明事件表,在源文件中用BEGIN_EVENT_TABLE和END_EVENT_TABLE实现事件表,并添加事件表条目(如EVT_BUTTON)将事件映射到处理函数。
- **事件处理流程示例**:以MyFrame类为例,当用户点击菜单或按钮时,wxWidgets根据事件表将事件发送到相应的处理函数(如OnQuit、OnAbout、OnButtonOK),处理函数根据事件类型执行相应操作,如关闭窗口、显示对话框或执行其他自定义逻辑。
- **动态事件处理**:使用wxEvtHandler::Connect和wxEvtHandler::Disconnect函数在运行时指定事件与处理函数的映射关系,如在MyFrame类中可通过Connect函数为菜单事件动态添加处理函数,这种方式可根据程序需求在不同时间使用不同的事件处理函数,且能更精细地控制事件处理,如开启或关闭单个事件处理函数,还允许不同对象共享事件处理函数。
- **事件传播与处理顺序**:事件在窗口组件层次结构和继承层次结构中传播,对于命令事件(基于wxCommandEvent),会递归应用于窗口父级的事件处理程序,但部分系统事件(如wxActivateEvent、wxCloseEvent等)不会传播到父级,因为它们仅与特定窗口相关。
- **自定义事件**:若要定义自定义事件,需派生合适的类(如从wxCommandEvent或wxNotifyEvent派生),添加动态类型信息和Clone函数,定义事件处理函数的typedef,声明事件类型表,定义事件表宏,最后在程序中使用自定义事件,如在自定义控件中发送事件,在应用程序中捕获并处理。
### 4. 窗口基础
- **窗口概念与属性**
- **定义与类型**:窗口是具有共同属性(如可调整大小、可绘制、可显示和隐藏等)的矩形区域,分为顶级窗口(如wxFrame、wxDialog、wxPopup)和其他窗口,顶级窗口可独立存在于桌面,可包含菜单、工具栏和状态栏,且可被拖动和调整大小,其他窗口通常包含在父窗口内。
- **属性详解**:包括客户区(可绘制或放置子窗口的区域)、滚动条(可自动或手动管理)、光标和插入符(用于指示鼠标位置和文本输入位置)、坐标系统(原点在左上角,单位为像素)、颜色和字体(可设置背景、前景色和字体)、窗口变体(在Mac OS X上可改变窗口大小)、大小调整(可响应大小改变事件)、输入处理(可接收鼠标和键盘输入)、空闲时间处理(可在空闲时执行任务)等。
- **窗口创建与销毁**
- **创建方式**:一般在堆上使用new创建,多数窗口类可一步或两步创建,如wxButton,一步创建可利用构造函数的默认值,两步创建需先使用默认构造函数再调用Create函数,创建时需传递父窗口指针、窗口标识符、位置、大小、样式、验证器和名称等参数,部分参数有默认值,窗口创建后可显示(Show)或隐藏(Hide)。
- **销毁机制**:顶级窗口使用Destroy或Close销毁,子窗口通常由父窗口销毁,当窗口被销毁时会发送wxEVT_DESTROY事件,窗口创建和销毁过程中还涉及内存管理和相关函数调用,如初始化应用程序对象、清理对象等操作。
- **窗口样式与风格**
- **窗口样式**:是创建窗口时指定替代行为和外观的方式,用C++位或运算符组合,如wxFrame的样式包括标题栏、最小化和最大化框、边框样式等,不同窗口类有各自的基本样式,部分样式仅适用于特定平台或窗口类。
- **额外样式**:用于设置无法用常规样式表示的值,如
wxWS_EX_VALIDATE_RECURSIVELY用于控制验证的递归性,wxWS_EX_BLOCK_EVENTS用于阻止事件向上传播,通过wxWindow::SetExtraStyle函数设置。
- **风格设置**:如背景风格(wxBG_STYLE_SYSTEM、wxBG_STYLE_COLOUR、wxBG_STYLE_CUSTOM)可决定窗口背景的绘制方式,可通过相关函数获取和设置。
- **常用窗口类介绍**
- **基础窗口类**:wxWindow是所有窗口的基类,提供基本功能;wxControl是控件的抽象基类,用于显示数据并响应输入;wxControlWithItems是包含多个项目的控件的抽象基类,管理项目的字符串标签和客户端数据。
- **顶级窗口类**:wxFrame是常用的主应用程序窗口,可包含菜单、工具栏和状态栏,可调整大小;wxDialog用于呈现信息、选项或选择,可模态或非模态显示;wxPopupWindow是临时窗口,装饰较少;wxMDIParentFrame用于管理多个文档界面(MDI)的子窗口,外观和行为在不同平台有所不同。
- **容器窗口类**:wxPanel用于在非对话框窗口上布置控件;wxNotebook用于通过选项卡切换页面;wxScrolledWindow可滚动子窗口和图形;wxSplitterWindow可管理两个子窗口,可分割和合并。
- **非静态控件类**:wxButton是常见的按钮控件,可显示文本或位图标签;wxCheckBox用于表示复选框,有两种或三种状态;wxChoice是下拉列表选择控件;wxComboBox是可编辑的下拉列表;wxListBox用于选择字符串列表中的项目;wxRadioBox用于选择互斥选项;wxRadioButton是单选按钮;wxScrollBar用于表示滚动条;wxSpinButton用于增减数值;wxSpinCtrl结合了文本框和旋转按钮;wxSlider用于通过滑块改变数值;wxTextCtrl用于显示和编辑文本,支持多种样式和功能。
- **静态控件类**:wxGauge用于显示进度或数量;wxStaticText用于显示只读文本;wxStaticBitmap用于显示图像;wxStaticLine用于显示水平或垂直分隔线;wxStaticBox用于将其他控件分组,绘制矩形框并可带文本标签。
- **菜单类**:wxMenu用于创建菜单,可包含普通命令、复选框、单选按钮、分隔符和子菜单等项目,菜单可弹出显示,事件在菜单本身及相关窗口中传递,可通过多种方式创建和管理菜单,如使用wxMenuBar将菜单添加到框架,通过事件表处理菜单事件。
- **控制栏类**:wxMenuBar用于在框架顶部显示菜单;wxToolBar包含按钮和控件,可提供快速访问命令的功能;wxStatusBar用于在框架底部显示状态信息,可包含多个字段,可通过相关函数创建、管理和更新控制栏。
### 5. 绘图与打印
- **设备上下文(Device Contexts)**
- **概念与作用**:所有绘图操作都在设备上下文上进行,设备上下文是对绘图表面(如窗口、位图、打印机等)的抽象,通过创建相应的设备上下文类(如wxClientDC、wxPaintDC、wxMemoryDC等)来进行绘图操作,其优点是可使绘图代码适用于不同设备上下文,通过参数化和适当缩放实现跨设备绘图。
- **坐标系统与单位**:设备上下文有自己的坐标系统,原点在左上角,可通过SetDeviceOrigin改变原点位置,存在逻辑单位和设备单位的区别,映射模式定义了逻辑单位与设备单位的转换关系,默认映射模式为wxMM_TEXT(逻辑单位为像素),还可通过SetUserScale施加额外缩放。
- **裁剪区域**:可通过SetClippingRegion设置裁剪区域,限制绘图范围,图形只会在裁剪区域内显示,可通过相关函数获取和操作裁剪区域。
- **主要设备上下文类**
- **wxClientDC**:用于在窗口客户区外部的绘图事件(如鼠标事件处理)中绘图。
- **wxPaintDC**:用于在窗口的绘制事件处理程序中绘图,创建该对象可告知wxWidgets窗口已重绘,避免无限发送绘制事件,在绘制事件中应尽量仅重绘无效区域,可通过相关函数获取更新区域。
- **wxBufferedDC和wxBufferedPaintDC**:是双缓冲绘图的替代类,可减少绘图闪烁,wxBufferedDC用于替代wxClientDC,wxBufferedPaintDC用于替代wxPaintDC,可通过设置缓冲区和相关参数优化绘图。
- **wxMemoryDC**:用于在内存中绘制到位图,通过SelectObject关联位图,绘图完成后需调用SelectObject(wxNullBitmap)解除关联,可用于创建和操作位图图形。
- **wxMetafileDC**(仅在Windows和Mac OS X上可用):用于创建Windows元文件或Mac PICT格式的绘图表面,可将绘图指令保存为可被其他应用程序解释或渲染的元文件。
- **wxScreenDC**:用于在屏幕上绘图或复制屏幕内容,常用于给拖动操作提供反馈或截取屏幕截图,但在其他应用程序绘制区域上绘图时可能受限。
- **wxPrinterDC和wxPostScriptDC**:用于打印操作,wxPrinterDC在Windows和Mac上映射到相应打印系统,在其他Unix系统上若没有标准打印模型则可能使用wxPostScriptDC(除非有GNOME打印支持),wxPostScriptDC专门用于创建PostScript文件发送到打印机,使用时需注意其一些特性(如获取文本大小信息的方式)。
- **绘图工具(Drawing Tools)**
-