多文档界面设计
一、多文档界面概述
大多数基于Windows的大型应用程序都是多文档界面(MDI),多文档界面由父窗体和子窗体组成,是一种允许在单个容器窗体中包含多个窗体的应用程序,这种程序允许同时打开多个文档,如Micrsoft Excel和Micrsoft Word等,见图8.48。单文档界面(SDI)只能够打开一个文档,打开另一个文档时就会关闭原来打开的文档。如Windows中的计算器、记事本和画图等,见图8.49。
图8.48 WORD多文档界面
图8.49 “画图”单文档界面
在VB中,可以创建三种窗体,即普通窗体、MDI父窗体和MDI子窗体。普通窗体是指独立的窗体,它和其它窗体之间没有从属关系。MDI子窗体是指MDIChild属性为True的普通窗体。MDI窗体是由菜单、工具栏、子窗口区和状态条所组成,是所有MDI子窗体的容器,MDI父窗体在一个工程中只有一个。
二、多文档界面的工作特点
1.MDI子窗体只能在MDI父窗体的工作区中打开,最小化后将以图标形式出现在父窗体中,而不会出现在Windows 的任务栏中。当最小化父窗体时,所有的子窗体也被最小化,只有父窗口的图标出现在任务栏中。如图8.50所示:创建MDI窗体(父窗体)。
图8.50 MDI窗体
2.在运行时,当一个MDI子窗体被最大化时,其标题将与父MDI窗体的相结合。 结合后的形式为:MDI窗体标题-[MDI子窗体标题],如图8.51所示。
图8.51 合并标题的效果
3.应用程序运行时,每个子窗体的菜单都显示在MDI窗体上,而不是在子窗体本身。当某个MDI子窗体有焦点时,若该窗体有菜单,则该子窗体的菜单将代替父窗体的菜单栏上的菜单。如果没有可见的子窗体,或者如果带有焦点的窗体没有菜单,则MDI窗体将显示自己的菜单。
4.如果MDI子窗体在其父窗体装入之前被引用,则父MDI窗体将被自动装入。然而,如果父窗体在MDI子窗体装入之前被引用,则子窗体并不被装入。
5.MDI子窗体都有可调整大小的边框、控制菜单框及最大化和最小化按钮。
6.对MDIForm对象的任何引用将导致该窗体的被装入并成为可见的。
三、建立多文档界面
(一)创建多文档界面
基本步骤:
1.新建工程,添加MDI窗体。执行“工程”菜单中的“添加MDI窗体”选命令,或打开工程资源管理器,右击“窗体”文件夹,执行快捷菜单中的“添加MDI窗体”命令来实现。
2.创建应用程序的子窗体。创建一个MDI子窗体,先创建一个新的窗体或者打开一个已经存在的窗体,选中它,并在属性对话框中把MDIChild属性设为True。反复此操作,可在工程中创建多个子窗体。如图8.52所示:form1窗体灰色,已经成为了MDI子窗体。
图8.52 MDIChild属性
图8.53 工程资源管理器中的MDI子窗体
[例8-13]编写一个能浏览图片的程序。
程序运行的界面如图8.54所示:
图8.54 程序主界面运行(一)
图8.54 程序主界面运行(二)
操作步骤
(一)设计主界面。如图所示,添加相应的控件。
图8.55 主界面设计
界面上各对象的属性如表8.28所示。
表8.28 属性设置
对象 |
Name |
Caption |
窗体 |
MDIForm1 |
相片浏览 |
按钮 |
Command1 |
第一张 |
Command2 |
下一张 | |
Command3 |
上一张 | |
Command4 |
最后一张 | |
Command5 |
结束 | |
图片框 |
Picture1 |
(二)设计“第一张”窗体。如图8.56所示。
图8.56 “第一张”窗体
Form1界面上各对象的属性如表8.29所示。
表8.29 属性设置
对象 |
Name |
Caption |
Mdichild |
picture |
窗体 |
Form1 |
第一张 |
||
true |
||||
图片框 |
Picture1 |
App.path &”Blue hills.jpg” |
(三)设计“第二张”窗体。如图8.57所示。
图8.57 “第二张”窗体
界面上各对象的属性如表8.30所示。
表8.30 属性设置
对象 |
Name |
Caption |
Mdichild |
picture |
窗体 |
Form2 |
第二张 |
||
true |
||||
图片框 |
Picture1 |
App.path & ”\VB教材例\相片浏览\ Sunset.jpg” |
(四)设计“第三张”窗体。如图8.58所示。
图8.58 “第三张”窗体
界面上各对象的属性如表8.31所示。
表8.31 属性设置
对象 |
Name |
Caption |
Mdichild |
picture |
窗体 |
Form3 |
第三张 |
||
true |
||||
图片框 |
Picture1 |
App.path & ”\VB教材例\相片浏览\ Water lilies.jpg” |
(五)添加代码。在窗体MDIForm1的代码窗口里添加如下代码:
Private Sub Command1_Click()
Form1.Show
Form2.Hide
Form3.Hide
End Sub
Private Sub Command2_Click()
If Form1.Visible = True Then
Form2.Show
Form1.Hide
ElseIf Form2.Visible = True Then
Form3.Show
Form2.Hide
ElseIf Form3.Visible = True Then
Form1.Show
Form3.Hide
End If
End Sub
Private Sub Command3_Click()
End
End Sub
Private Sub Command4_Click()
If Form1.Visible = True Then
Form3.Show
Form1.Hide
ElseIf Form2.Visible = True Then
Form1.Show
Form2.Hide
ElseIf Form3.Visible = True Then
Form2.Show
Form3.Hide
End If
End Sub
Private Sub Command5_Click()
Form3.Show
Form1.Hide
Form2.Hide
End Sub
Private Sub MDIForm_Load()
Load Form1
Load Form2
Load Form3
Form1.Hide
Form2.Hide
Form3.Hide
Form1.WindowState = 2
Form2.WindowState = 2
Form3.WindowState = 2
End Sub
(二)常用的属性
MDI父窗体、MDI子窗体作为窗体具有普通窗体所具有的属性、方法和语句。同时增加了和处理多文档界面相关的属性、方法和语句。其中常用的属性有:
1.MdiChild属性
在MDI应用程序中,如果一个普通窗体的MDIChild属性的值为True,那么该窗体就是MDI窗体的一个子窗体。
2.AutoShowChildren属性
MDI窗体的AutoShowChildren属性,决定是否自动显示子窗体。如果它被设置为True,则当改变子窗体的属性后,会自动显示该子窗体;如果AutoShowChildren设置为False,则改变子窗体的属性值后,必须用Show方法把该子窗体显示出来。
3.BorderStyle属性
子窗体的BorderStyle属性,如果MDI窗体具有大小可变的边框,即BorderStyle = 2,则其初始化大小与位置取决于MDI窗体的大小,而不是设计时子窗体的大小。当MDI子窗体的边框大小不可变(即BorderStyle = 0、1或3)时,则它的大小由设计时的Height和Width属性决定。
4.Windowstate属性
当Windowstate属性值为: vbNormal或 0 (缺省值)时,表示窗体正常显示 。当其值为 VbMinimized或 1时,表示窗体为最小化,即最小化为一个图标。当其值为 VbMaximized或 2时,表示窗体为最大化,即扩大到最大尺寸。在窗体被显示之前,WindowState 属性常常被设置为0,即按窗体的 Height、Left、ScaleHeight、ScaleWidth、Top和 Width 属性设置值来显示。
举例:
Private Sub Form_Resize ()
If Form1.WindowState = vbMinimized Then
Form2.Visible = False '如果父窗体被最小化,隐藏 Form2
Else
Form2.Visible = True '如果父窗体不再是最小化,恢复 Form2
End If
End Sub
5.Screen对象的相关属性
Screen对象包含了屏幕的相关信息,通过使用该对象能对主窗口进行各种操作,如可以动态地改变主窗口的图标、标题、颜色等,也可以通过它引用其它的对象或属性。常用的属性有:
Width: 返回屏幕的宽度(像素数)。
Height:返回屏幕的高度。
在Windows环境中,要想获得屏幕上当前窗体及当前控件的信息,一般要引用Screen对象的ActiveControl、ActiveForm、ActiveReport等属性,来提供当前窗体或控件的详细特性。
如:screen.ActiveForm属性能够引用当前屏幕上激活窗体的各个属性,无需知道当前窗体的具体名称。
(三)常用方法
Arrange方法:MDI应用程序中可以包含多个子窗体。当打开多个子窗体时,用MDIform的Arrange方法能够使子窗体或其图标按一定的规律排列。
格式:〈MDI窗体名〉.Arrange〈参数〉
“参数”是一个整数,表示所使用的排列方式,其含义如表8.32所示。
表8.32 Arrange方法参数值的含义
符号常量 |
值 |
说明 |
vbCascade |
0 |
个子窗体按层叠方式排列 |
vbTitleHorizontal |
1 |
个子窗体按水平平铺方式排列 |
vbTileVertical |
2 |
个子窗体按垂直平铺方式排列 |
vbArrangeIcons |
3 |
当子窗体被最小化图标后,该方式将使图标在父窗体的底部重新排列 |
[例8-14]举于上例,编写一个能按不同方式排列的相片浏览程序。
(一)界面设计。如图8.59所示。
图8.59 程序主界面
主窗口界面(MDIForm1)上各对象的属性如表8.33所示。
表8.33 属性设置
对象 |
Name |
Caption |
窗体 |
MDIForm1 |
相片浏览 |
按钮 |
Command1 |
层叠 |
Command2 |
水平平铺 | |
Command3 |
垂直平铺 | |
Command4 |
最小化 | |
图片框 |
Picture1 |
(二)代码添加
MDIForm1上的代码如下:
Private Sub Command1_Click()
MDIForm1.Arrange 0
End Sub
Private Sub Command2_Click()
MDIForm1.Arrange 1
End Sub
Private Sub Command4_Click()
MDIForm1.Arrange 2
End Sub
Private Sub Command5_Click()
MDIForm1.Arrange 3
End Sub
Private Sub MDIForm_Load()
Form1.Show
Form2.Show
Form3.Show
Form1.WindowState = 2
Form2.WindowState = 2
Form3.WindowState = 2
End Sub
其它窗体的设计保持不变。
程序运行效果如下:
图8.60 “层叠” 运行效果
图8.61 “水平平铺”运行效果
图8.62 “垂直平铺”运行效果
图8.63 最小化子窗体后的效果
(四)Dim语句和Set语句
Dim语句用来声明图形对象、子窗体、控件对象及控件数组的,其格式为:
Dim <对象变量> as [New] <对象变量类型>
如果使用New来声明对象变量,则在第一次使用该变量时将新建该对象的实例,因此不必使用Set语句来给变量赋值。如果省略它,则在使用该变量之前,必须使用Set语句将该引用对象的变量赋值为一个已有对象。在该变量赋值之前,所声明的对象变量有一个特定值Nothing,这个值表示该变量没有指向任何一个对象。
例如,声明一个列表框对象变量objList的语句应为:
Dim object as listbox
当要求一个对象变量指向应用程序中的某一具体对象时,必须用Set语句将对象赋给对象变量,语法是:
格式:Set <变量> = <对象>
例如:
Dim MyText As TextBox ‘声明一个引用文本框的对象变量MyText
Set MyText = text1 ‘将具体要求的文本框text1赋给MyText
这样变量Mytext就代表Text1,Mytext.text等价于Text1.text。
New关键字可以和Set语句并用来创建新的实例,这样可以加快运行速度。例如:
Set MyText = New TextBox 和Dim MyText As TextBox及Set MyText = text1是等价的。
(五)QueryUnload事件
QueryUnload事件在一个窗体或应用程序关闭之前发生,此事件的典型用法是在关闭一个应用程序之前用来确认包含在该应用程序中的窗体中没有未完成的任务,可以让你在关闭窗口之后做一些操作,如确认退出。
MDI子窗体中的QueryUnload事件,优先于所有MDI窗体的QueryUnload事件。即是如果所有窗体都没有取消QueryUnload事件,则该事件首先在所有子窗体中发生,最后在MDI窗体中发生。
当一个子窗体或非MDI窗体关闭时,该窗体的QueryUnload事件在其Unload事件之前发生。
如以下代码:
Private Sub Form_QueryUnload(Cancel As Integer, UnloadMode As Integer)
MsgBox "退出1"
End Sub
Private Sub Form_Unload(Cancel As Integer)
MsgBox "退出2"
End Sub
程序运行时,先显示“退出1”,后显示“退出2”。
当一个应用程序关闭时,可使用QueryUnload或Unload事件过程将Cancel属性设置为True来阻止关闭过程。
其中QueryUnload事件过程中有参数UnloadMode,该参数可以选择一种方式结束程序。
表8.34 Unloadmode参数返回下列值:
常数 |
值 |
描述 |
vbFormControlMenu |
0 |
用户从窗体上的控制菜单中选择“关闭”指令 |
vbFormCode |
1 |
Unload语句被代码调用 |
vbAppWindows |
2 |
当前Microsoft Windows操作环境会话结束 |
vbAppTaskManager |
3 |
Microsoft Windows任务管理器正在关闭应用程序 |
vbFormMDIForm |
4 |
MDI子窗体正在关闭,因为MDI窗体正在关闭 |
[例8-15]在例8-14的基础上,在MDIForm1的代码窗口中增加下列代码:
Private Sub MDIForm_QueryUnload(Cancel As Integer,_
UnloadMode As Integer)
Select Case UnloadMode
Case 0 To 5
If MsgBox("你确定要退出程序吗?", vbQuestion + vbYesNo) = vbNo Then Cancel = True
End Select
End Sub
这样就不管你的程序是按ALT+F4,或是单击关闭按钮,还是使用其它模式都可以弹出消息框。
程序运行如下:
图8.64 退出确认