本节介绍一下Windows窗体设计中的一些概念和原则。
控件的名称
当开发人员在窗体中新增一个控件时,系统会给这个控件设置默认名称,比如对于Label控件,其默认名称可能为lable1、label2等,对于TextBox控件其默认名称可能为textBox1、textBox2等等。
如下图所示,笔者设计了一个“用户信息”窗体,在默认情况下,各个控件的名称如下图所示。
这是一种非常糟糕的窗体设计结果。在编写该窗体的C#代码时,由于无法同时看到窗体设计界面,因此很难记下各种控件的名称及其功能。当窗体控件比较多时,此时的程序代码的编写和维护时相当困难的。
因此开发人员应当养成在窗体上新建控件就立即修改控件名称的习惯。这样能有效的改进软件的用户界面的设计质量,也是窗体后台代码高质量的基础。对于Label控件,由于基本上不参与编程,只是在用户界面上显示一段不可改变的静态文本,因此可以不设置Label控件的名称,但当在少数情况下,当窗体后台代码需要操作Label控件的文本等属性值时,为了提高代码的质量也应当修改Label控件的名称。比如对于下面这个窗体,各个数据输入控件的名称设置如下。
跟代码变量命名规则类型,窗体控件也有命名规则,业界主流的控件命名规则可能有多种,各种规则之间差别不大,笔者采用的命名规则大致如下[袁永福版权所有]
控件名称一般为表示控件类型的前缀加上表示控件作用的字符组成。常用控件类型和前缀对应关系如下表所示
控件类型
|
前缀
|
Button 按钮
|
btn
|
CheckBox 复选框
|
chk
|
ColumnHeader 视图列表头
|
col
|
ComboBox 组合框
|
cbo
|
ContextMenu 快捷菜单
|
ctm
|
DataGrid 数据网格控件
|
dg
|
DataGridView 数据网格视图控件
|
dgv
|
DateTimePicker 时间输入框
|
dtp
|
DomainUpDown 数值框
|
dud
|
Form 窗体
|
frm
|
GroupBox 组合框
|
grp
|
HscrollBar 水平滚动条
|
hsb
|
ImageList 图标列表
|
img
|
Label 文本标签
|
lbl
|
LinkLabel 带链接的文本标签
|
lbl
|
ListBox 列表框
|
lst
|
ListView 视图列表
|
lvw
|
Menu 菜单
|
menu
|
MenuItem 菜单项
|
menu
|
NumericUpDown 数值框
|
nud
|
Panel 面板
|
pnl
|
PictureBox 图片框
|
pic
|
ProgressBar 进度条
|
prg
|
RadioButton 单选框按钮
|
rdo
|
Spliter 拆分条
|
spl
|
StatusBar 状态栏
|
stu
|
StatusBarPanel 状态栏区域
|
pnl
|
StatusStrip 状态栏
|
stu
|
TabControl 分页控件
|
tab
|
TabPage 分页标签页面
|
page
|
TextBox 文本框
|
txt
|
Timer 定时器
|
tmr
|
ToolBar 工具条
|
tbr
|
ToolStrip 工具栏
|
tsp
|
ToolStripButton 工具栏按钮
|
btn
|
ToolStripComboBox 工具栏下拉组合框
|
cbo
|
ToolStripDropDownButton 工具栏下拉列表
|
btn
|
ToolStripDropDownMenu 工具栏菜单项目
|
menu
|
ToolStripLabel 工具栏静态文本
|
lbl
|
ToolStripProgressBar 工具栏进度条
|
prg
|
ToolStripTextBox 工具栏文本框
|
txt
|
TreeView 树状视图列表
|
tvw
|
VScrollBar 垂直滚动条
|
vsb
|
WebBrowser 浏览器控件
|
wb
|
对于其他非常用的控件类型的前缀读者可以自己琢磨或者请教他人,控件名称前缀只是一个比较小的细节问题,即使有误也无伤大雅。[袁永福版权所有]
笔者一般使用英文或者缩写来表示控件的作用,若没有合适的英文则采用汉语全拼音或者干脆用中文汉字,但绝不会用中文汉语拼音首字母,因为汉语拼音首字母很难仅仅从字母上猜出其表示的汉字,而猜测英文缩写相对容易得多。
如下图所示,可能有些人使用汉语拼音首字母来设置控件的名称,比如“姓名”文本框取名“txtXM”,这是一种不好的控件命名方式,因为很多时候是实在是难于从拼音首字母中猜测控件的作用,控件名称的低可读性降低了程序代码的可读性。
因此按照比较合理的命名方式,“姓名”文本框的名称就采用TextBox控件的前缀“txt”和表示姓名的英文“Name”组合而成为“txtName”。
一般来说商业软件不是“一次开发,长期使用”,而是“一次开发,长期修改,长期使用”,因此开发商业软件需要考虑到未来的修改和升级换代,此时程序代码不但要耐用,还需要耐看耐改,程序代码需要具备良好的可读性,而给控件设置合适的名称就是一个基础工作。其实除了控件的名称,其他的诸如数据库表名字段名,窗体名称,程序模块名称等等都需要遵守一定的命名规范。[袁永福版权所有]
首先的设置好控件的TabIndex属性值。在程序运行显示窗体时,用户可以按下Tab键来切换输入焦点,而切换顺序就依照各个控件的TabIndex属性。一般的输入焦点切换顺序按照从左到右,从上到下。因此需要设置左上方位的控件的TabIndex属性值为小,右下方为的控件的TabIndex属性值为大。但实际开发中还是按照具体功能需求来安排输入焦点切换顺序。
在设置各个控件的TabIndex属性值时不应设置为连续的值,比如设置第一个控件的TabIndex属性值为1,第二个控件为2,第三个控件为3,等等等。采用这种设置时,当未来在输入焦点顺序中插入新的控件,则会需要修改大量的控件的TabIndex属性值。为此笔者建议输入的各个控件的TabIndex属性值不联系,比如有10的间隔,此时可以设置第一个控件的TabIndex属性值为10,第二个控件为20,第三个控件为30,等等等。这样就为未来插入新的控件留下TabIndex顺序的空间。如下图所示
在这个“用户信息”窗体设计的例[袁永福版权所有]子中,当该窗体运行显示后,用户可以按下Tab键从左到右从上到下的切换焦点。
有些控件并不能接受输入焦点,比如Label控件,但仍然需要为这类控件设置合适的TabIndex属性值。因为Label控件虽然不能接受输入焦点,但仍然能接受快捷键,比如在“用户信息”的窗体设计中,笔者设置第一个Label控件的文本为“姓名 (&N):”,则程序运行后显示该窗体时,用户按下“Alt+N”组合键时,Label控件就感应到快捷键并试图设置输入焦点到自己,由于Label控件不能接受输入焦点,因此系统就会将输入焦点自动切换到Label控件的下一个焦点顺序的控件上。也就是TabIndex值为20的文本框上。这样用户就使用快捷键“Alt+U”就能快速切换焦点到“姓名”文本框了。
当用户界面上数据输入域很多时,这种快速切换输入焦点的功能是很人性化的,方便用户使用纯键盘操作来高速输入和修改数据,显得用户界面做的很专业。若没有这种功能,则用户需要频繁的切换鼠标和键盘来输入数据,大大拖累的操作速度。
商业程序的用户界面要求比较高,因为使用者可能好几年天天面对相同的用户界面,累计下来会重复进行几万次操作,此时用户界面需要耐看耐用,这需要在很多细节上做好功夫,其中设置各[袁永福版权所有]个控件的TabIndex属性值就是一个基础工作,必须花点心思做好。
Z-Index
在WinForm窗体设计中有一个Z-Index的概念。窗体布局是采用绝对坐标方式的,每一个控件都有Left和Right属性用于确定控件的左上角在窗体中的X-Y坐标。
当窗体有多个控件时,控件之间可能存在相互重叠的现象,这类似图像处理中层的概念。也就是说一个控件单独的占有一个控件布局层,多个控件就会有多个布局层的叠加,而越靠近窗体的控件就越容易被覆盖,于是从窗体开始计算,每个控件布局层都有一个从0开始计算的序号,这个序号就是Z-Index。
从另外一种方式理解,窗体上的控件布局是不仅仅是X-Y坐标系那种二维的,而是三维的,第三维就是Z坐标轴,它是从窗体向用户延伸的,控件是分布在窗体和用户之间。此时可以说用户是俯看用户界面,若不注意是不会感觉到第三维的存在。而且控件在第三维中的坐标值就是Z-Index,这个值是从0开始的,不会重复;Z-Index值大的控件可以覆盖掉值小的控件。
我们还可以从第三种方式看Z-Index值,窗体对象有一个Controls的属性,该属性值可以看做一个控件数组,窗体上所有的控件都在这个数组中。系统创建窗体时,是从这个数组逆向遍历获得控件对象,然后依次放置在窗体上,很显然在数组中靠前的控件可以覆盖掉靠后的控件,于是控件在这个数组中的逆向序号也可以看做Z-Index值。
实际上其他软件开发技术中也有Z-Index属性,比如VB,还有Web开发中才CSS样式也支持Z-Index属性值。
Z-Index与其他控件相关,因此控件本身不会有Z-Index属性,而且根据控件在窗体中的布局动态的计算出来的。
在VS.NET的窗体设计器中,不能直接设置控件的Z-Index值,但可以使用布局工具条上的“置于顶层”和“置于低层”按钮来将控件沿着Z坐标轴置于最大值或最小值,也就是沿着Z坐标轴移动控件,使其最靠近用户或者最靠近窗体。
在窗体设计中,设置控件在Z轴上的先后顺序也是有一些原则的,那就是重要的控件需要置前,不能被不重要的控件覆盖掉。如下图所示
文本标签的Z-Index值大于文本框的,这种用户界面是很不好的,会遮挡文本框中的部分类型,而且也不美观,因此需要调整为文本框靠前,也就是如下图的效果。
如果用户界面排版时被迫发生一些重叠遮盖,也必须保证重要的控件不被遮盖。
一般来说,若设计人员心中已经知道用户界面的设计,在窗体上从左到右、从上到下的依次添加控件,控件的TabIndex和Z-Index值都是不断增加的,此时做好之后大多就无需调整了。但在实际中设计好的窗体经常会添加或删除控件,或者大幅移动控件的位置,此时需要注意调整控件的TabIndex和Z-Index值。[袁永福版权所有]
在同一个软件中,甚至同一家企业开发的所有的软件中,对于窗体控件纵向应当采用相同的对齐方式,可以左对齐、居中对齐或者右对齐。不过笔者建议左对齐。
如下图所示,对于“用户信息”窗体,控件设计时采用左对齐时窗体的运行时用户界面如下
而采用居中对齐时窗体运行时的用户界面如下
采用右对齐时窗体运行时的用户界面如下
对比这三种情况,应该是控件左对齐排版最好,其次是右对齐,居中对齐最差。因此一般都是采用左对齐方式。
不过不管采用哪种控件对齐方式,一定要记住在同一个软件中所有的用户界面中采用统一的对齐方式,不能一个窗体采用左对齐而另外一个窗体采用右对齐,这是一种相当不专业的表现。
在VS.NET中统一控件的对齐方式是比较简单的,首先将控件按照大致的位置布局好,然后选中所有要参与对齐操作的控件,点击工具条上的对齐功能按钮就可。
下图就是VS.NET提供的对齐工具条。
该工具条上常用的按钮功能有
移动控件,使得所有控件的左边缘对齐。
| |
移动控件,使得所有的控件的垂直中轴线重合。
| |
移动控件,使得所有控件的右边缘对齐。
| |
移动控件,使得所有控件的顶边缘对齐。
| |
移动控件,使得所有控件的水平中轴线重合。
| |
移动控件,使得所有控件的底边缘对齐。
| |
设置所有控件的宽度值等于当前控件的值。
| |
设置所有控件的高度值等于当前控件的值。
| |
设置所有控件的宽度和高度等于当前控件的值。
| |
适当的水平移动控件,使得各个控件水平方向的间距相等。
| |
适当的水平移动控件,使得各个控件水平方向的间距增加一些,各个控件的间距增加量相同。
| |
适当的水平移动控件,使得各个控件水平方向的间距减少一些,各个控件的间距减少量相同。
| |
适当的水平移动控件,使得各个控件水平方面紧密的靠在一起,之间没有间隙。
| |
适当的上下移动控件,使得各个控件垂直方向的间距相等。
| |
适当的上下移动控件,使得各个控件垂直方向的间距增加一些。
| |
适当的上下移动控件,使得各个控件垂直方向的间距减小一些。
| |
适当的上下移动控件,使得各个控件垂直方向紧密的靠在一起,之间没有间隙。
| |
使得控件在Z顺序方向变得靠前,不被其他控件遮盖。
| |
使得控件在Z顺序方向变得靠后,不会覆盖其他控件。
|
例如有几个控件的位置设计如下