# 7.2 窗口布局控件
wxWidgets使用的窗口布局控件的算法和其它GUI程序开发框架的算法,例如Java的AWT,GTK+以及Qt等是非常相似的.它们都是基于这样的一个假设,那就是每一个窗口可以报告它们自己需要的最小尺寸以及当它们父窗口的大小发生改变的时候它们的可伸缩能力.通常这也意味着程序代码中没有给对话框中的控件设定固定的大小,取而代之的是设置了一个窗口布局控件,这个窗口布局控件会被寻问它最需要的合适大小,而窗口布局控件则会一次询问它内部的那些窗口,空白区域,控件以及其它的窗口布局控件最合适的大小,以此类推.要注意布局控件并非是wxWindow的派生类,因此不具有TAB顺序,所需要的系统开销也比一个真实的窗口要小的多.布局控件建立的是一种包含继承关系,在一个复杂的对话框里,这种包含继承关系的层级可能会很深,但是所有这些布局控件中的窗口或控件在窗口继承关系中可能都是兄弟控件,它们都以这个对话框作为自己的父窗口.
在对话框编辑软件中,布局控件的包含继承关系以一种更直观的图形化方式表示.下图演示了Anthemion软件公司的 DialogBlocks软件编辑一个个人对话框时候的样子,这个对话框我们会在第9章,"创建自己的对话框"中作为一个例子.一个红色的方框围绕在当前选择的控件上,而蓝色的方框则用来指示其直接父容器的范围,左边显示的是对话框的容器继承关系树,当然所有这些控件还是有它们自己的窗口继承关系的,正如我们前面提到的那样,窗口继承关系树和容器继承关系树有很大的区别.
![](img/mht3736%281%29.tmp)
为了更清楚的说明容器继承关系和窗口继承关系的不同,我们用下图来大概的表示上图中的容器继承关系.下图中,阴影部分代表实际的窗口,而白色区域则代表布局控件.可以看出,对话框首先使用了两个垂直布局控件,以便在对话框周围释放出一个合理的边界区域,里面的那个垂直布局控件中有两个水平布局控件和一些其它的控件,其中一个水平布局控件中还定义了一截空白区域以便使得其中一个控件远离同组中另外的控件.正象你看到的那样,使用布局控件就象使用一堆大小不等的硬纸片进行摆放,然后把各个窗口控件放置到硬纸片的合适的位置.当然这个比喻并不完全贴切因为,硬纸片的大小是不会伸缩的.
![](img/mht3749%281%29.tmp)
目前为止wxWidgets总共支持五类布局控件,每一中布局控件或者用来实现一种特殊的布局方式,或者用来实现和布局相关的一种特殊的功能比如在某些控件周围围绕一个静态的文本框.接下来的小节我们会对它们进行一一的介绍.
布局控件的通用特性
所有的布局控件都是容器,这就是说,它们都是用来容纳一个或多个别的窗口或者元素的,不论每个单独的布局控件怎样排放它们的子元素,所有的子元素都必然有下面这些通用的特性.
最小大小: 布局控件中的每个元素都有计算自己的最小大小的能力(这往往是通过每个元素的DoGetBestSize函数计算出来的).这是这个元素的自然大小.举例来说,一个复选框的自然大小等于其复选框图形的大小加上其标签的最合适大小.当然,你可以给某个控件在其构造函数中指定固定的大小,并且在把它增加到布局控件中时指定wxFIXED_MINSIZE以改变自动计算的最小大小.需要注意的是,不是每个控件都可以计算自己的大小,对于类似列表框这样的控件来说,你必须清晰的指明它的大小,因为它们没有自然大小.另外一些控件则只拥有自然高度不拥有自然宽度,比如一个单行的文本框.下图演示了当对话框中只有一个控件的时候,以上三种控件怎样扩展对话框以适合自己的最小大小.
![](img/mht375C%281%29.tmp)
![](img/mht375F%281%29.tmp)
![](img/mht3762%281%29.tmp)
边界: 每个元素都应该有一个边界.所谓边界指的是用来和别的元素分开的空白区域,边界的最小大小必须被显式的指定,一般设置为5个象素.下图演示了对话框只有一个按钮控件但是指定了0,5和10作为最小边界值的时候的样子.
![](img/mht3774%281%29.tmp)
![](img/mht3777%281%29.tmp)
![](img/mht378A%281%29.tmp)
对齐方式: 每个元素都可以被以居中或者对齐某个边的方式放置.下图演示了一个水平的布局控件,在其中增加了一个列表框,一个和三个按钮,其中第一个按钮以居中方式增加,第二个则为上对齐,第三个则为下对齐方式.对齐既可以是水平方向的也可以是垂直方向的,但是对于大多数布局控件来说,只有一个方向是有效的.比如对于水平布局控件来说,只有垂直方向是有效的,因为水平方向的空间是被所有的子元素分割的,因此设置水平对齐方式是没有意义的(当然,为了达到水平对齐的效果,我们可能需要插入一个水平方向的空白区域,关于这点我们不作太多的说明).
![](img/mht378D%281%29.tmp)
伸缩因子: 如果一个布局控件的空间大于它所有子元素所需要的空间,那么我们需要一个机制来分割多余的空间.为了实现这个目的,布局控件中的每一个元素都可以指定一个伸缩因子,如果这个因子设置为默认值0,那么子元素将保持其原本的大小,大于0的值用来指定这个子元素可以分割的多余空间的比例,因此如果两个子元素的伸缩因子为1,其它子元素的伸缩机制为0,那么这两个子元素将会各占用多余空间的50%的大小,下图演示了一个对话框有三个按钮它们的初始大小和其中一个的伸缩因子设为1以后各自的大小.
![](img/mht3790%281%29.tmp)
![](img/mht37A3%281%29.tmp)
注意在wxWidgets的手册中,有时不使用伸缩因子(stretch factor)这个词,而用比例(proportion)这个词表示相同的含义.
- 第一章 介绍
- 1.1 为什么要使用wxWidgets?
- 1.2 wxWidgets的历史
- 1.3 wxWidgets社区
- 1.4 wxWidgets和面向对象编程
- 1.5 wxWidgets的体系结构
- 1.6 许可协议
- 第一章小结
- 第二章 开始使用
- 2.1 一个小例子
- 2.2 应用程序类
- 2.3 Frame窗口类
- 2.4 事件处理函数
- 2.5 Frame窗口的构造函数
- 2.6 完整的例子
- 2.7 wxWidgets程序一般执行过程
- 2.8 编译和运行程序
- 第二章小结
- 第三章 事件处理
- 3.1 事件驱动编程
- 3.2 事件表和事件处理过程
- 3.3 过滤某个事件
- 3.4 挂载事件表
- 3.5 动态事件处理方法
- 3.6 窗口标识符
- 3.7 自定义事件
- 第三章小结
- 第四章 窗口的基础知识
- 4.1 窗口解析
- 4.2 窗口类概览
- 4.3 基础窗口类
- 4.4 顶层窗口
- 4.5 容器窗口
- 4.6 非静态控件
- 4.7 静态控件
- 4.8 菜单
- 4.9 控制条
- 第四章小结
- 第五章绘画和打印
- 5.1 理解设备上下文
- 5.2 绘画工具
- 5.3 设备上下文中的绘画函数
- 5.4 使用打印框架
- 5.5 使用wxGLCanvas绘制三维图形
- 第五章小节
- 第六章处理用户输入
- 6.1 鼠标输入
- 6.2 处理键盘事件
- 6.3 处理游戏手柄事件
- 第六章小结
- 第七章使用布局控件进行窗口布局
- 7.1 窗口布局基础
- 7.2 窗口布局控件
- 7.3 使用布局控件进行编程
- 7.4 更多关于布局的话题
- 第七章小结
- 第八章使用标准对话框
- 8.1信息对话框
- 8.2 文件和目录对话框
- 8.3 选择和选项对话框
- 8.4 输入对话框
- 8.5 打印对话框
- 第八章小结
- 第九章创建定制的对话框
- 9.1 创建定制对话框的步骤
- 9.2 一个例子:PersonalRecordDialog
- 9.3 在小型设备上调整你的对话框
- 9.4 一些更深入的话题
- 9.5 使用wxWidgets资源文件
- 第九章小结
- 第十章使用图像编程
- 10.1 wxWidgets中图片相关的类
- 10.2 使用wxBitmap编程
- 10.3 使用wxIcon编程
- 10.4 使用wxCursor编程
- 10.5 使用wxImage编程
- 10.6 图片列表和图标集
- 10.7 自定义wxWidgets提供的小图片
- 第十章小结
- 第十一章剪贴板和拖放操作
- 11.1 数据对象
- 11.2 使用剪贴板
- 11.3 实现拖放操作
- 第十一章小结
- 第十二章高级窗口控件
- 12.1 wxTreeCtrl
- 12.2 wxListCtrl
- 12.3 wxWizard
- 12.4 wxHtmlWindow
- 12.5 wxGrid
- 12.6 wxTaskBarIcon
- 12.7 编写自定义的控件
- 第十二章小结
- 第十三章数据结构类
- 13.1 为什么没有使用STL?
- 13.2 字符串类型
- 13.3 wxArray
- 13.4 wxList和wxNode
- 13.5 wxHashMap
- 13.6 存储和使用日期和时间
- 13.7 其它常用的数据类型
- 第十三章小结
- 第十四章文件和流操作
- 14.1 文件类和函数
- 14.2 流操作相关类
- 第十四章小结
- 第十五章内存管理,调试和错误处理
- 15.1 内存管理基础
- 15.2 检测内存泄漏和其它错误
- 15.3 构建自防御的程序
- 15.4 错误报告
- 15.5 提供运行期类型信息
- 15.6 使用wxModule
- 15.7 加载动态链接库
- 15.8 异常处理
- 15.9 调试提示
- 第十五章小结
- 第十六章编写国际化程序
- 16.1 国际化介绍
- 16.2 从翻译说起
- 16.3 字符编码和Unicode
- 16.4 数字和日期
- 16.5 其它媒介
- 16.6 一个小例子
- 第十六章小结
- 第十七章编写多线程程序
- 17.1 什么时候使用多线程,什么时候不要使用
- 17.2 使用wxThread
- 17.3 用于线程同步的对象
- 17.4 多线程的替代方案
- 第十七章小结
- 第十八章使用wxSocket编程
- 18.1 Socket类和功能概览
- 18.2 Socket及其基本处理介绍
- 18.3 Socket标记
- 18.4 使用Socket流
- 18.5 替代wxSocket
- 第十八章小结
- 第十九章使用文档/视图框架
- 19.1 文档/视图基础
- 19.2 文档/视图框架的其它能力
- 19.3 实现Undo/Redo的策略
- 第十九章小结
- 第二十章完善你的应用程序
- 20.1 单个实例和多个实例
- 20.2 更改事件处理机制
- 20.3 降低闪烁
- 20.4 实现联机帮助
- 20.5 解析命令行参数
- 20.6 存储应用程序资源
- 20.7 调用别的应用程序
- 20.8 管理应用程序设置
- 20.9 应用程序安装
- 20.10 遵循用户界面设计规范
- 20.11 全书小结