第 8章 多重窗体与环境应用
8.1 建立多重窗体应用程序
8.2 多重窗体应用程序的执行与保存
8.3 VB工程结构
8.4 闲置循环与 Do Events语句建立多重窗体应用程序,首先应该在工程中添加多个与用户交互的窗体;然后再设计这多个窗体之间的调用关系,以及窗体的加载、卸载、删除等操作;还包括各个窗体自身的功能实现。
8.1.1多重窗体的添加添加窗体的方法有四种:
( 1)单击“工程”菜单中的“添加窗体”命令,如图 8-1。
( 2)直接点击工具栏的“添加窗体”按钮。
( 3)单击工具栏的“添加窗体”按钮旁边的下拉菜单箭头,
在出现的菜单中选择“添加窗体”,如图 8-2。
图 8-1 通过菜单添加窗体 图 8-2 通过工具栏添加窗体
8.1 建立多重窗体应用程序图 8-3 通过工程资源管理器添加窗体
( 4)工程资源管理器中,单击鼠标右键弹出快捷菜单,选择添加子菜单的“添加窗体”项,如图 8-3所示。
任选这四种方法当中的一种操作,在出现的“添加窗体”对话框中,选择“新建”选项卡中的“窗体”,单击
“打开”按钮可以新建一个窗体,或者选择“现存”选项卡浏览并加载其它已经存在的窗体,如图 8-4。
注意:
( 1)如果选择添加“现存”窗体,当出现多个窗体的名称相同而提示不能加载时,可以改变窗体的名称再添加。
( 2)添加“现存”窗体实际是在工程中包含对该文件的引用,
多个工程共享窗体,对该窗体的修改将导致其它工程中该窗体的变化,可以通过窗体“另存为”命令以不同的文件名保存该窗体文件以取消共享。
图 8-4 添加窗体
8.1.2 多重窗体的设计
1,引例学籍管理系统。
系统启动,显示登录窗体如图 8-5,输入用户名和口令点击,确定,按钮,如果用户名和口令均正确,将显示如图 8-6的学籍管理系统主窗体,同时卸载登录窗体。
图 8-5 登录窗体图 8-6 学籍管理系统主窗体在主窗体中,选择点击修改密码菜单项,将弹出修改密码窗体,如图 8-7。
图 8-7 修改密码窗体一般说来,多重窗体的设计可以按照以下步骤进行:
( 1)分析应用程序要求,划分功能模块。
( 2)分别创建各模块及其包含的各个窗体。
( 3)建立窗体之间的调用关系。
( 4)点击 [工程 ]/[属性 ]菜单,在 [启动对象 ]中选择系统运行时首先执行的对象。
( 5)运行应用程序。
多窗体设计常用方法:
Load <窗体名称 >
装入窗体到内存。但并不显示该窗体。
Unload <窗体名称 >
从内存中卸载窗体。只移走窗体的可视部分,而不包括窗体的命令和程序,和该窗体模块相关联的代码还保持在内存中。
[窗体名称 ].Show [模式 ]
显示一个窗体。如果指定的窗体在此之前已由 Load装载,则显示之;如果调用 Show方法时指定的窗体没有装载,
VB将自动装载并显示该窗体。
模式可取值 0(默认值)或 1。当模式为 0即显示无模式窗体时,随后遇到的代码要执行,比如可以显示其它的窗体。当模式为 1即显示模式窗体时,则随后的代码直到该窗体被隐藏或卸载时才能执行。
[窗体名称 ].Hide
隐藏窗体,但并没有删除。
续前引例,在登录窗体输入用户名和口令,单击“确定”按钮的代码在学籍管理系统主窗体单击修改密码菜单项的代码:
Private Sub CmdOk_Click()
… ' 声明变量
… ' 校验用户名和口令
If 用户名或密码错误 Then
MsgBox "无此用户或密码错误,请重新输入! ",vbCritical,"错误 "
Else
FrmMain.Show '载入主窗体
Unload Me '从内存删除登录窗体
End If
End Sub
在修改密码窗体单击“取消”按钮的代码:
Private Sub mnuChangePsw_Click() '单击修改密码菜单项
frmChangePsw.Show '显示修改密码窗体
End Sub
Private Sub CmdCancel_Click()
Unload Me '从内存删除修改密码窗体
End Sub
8.1.3* 多文档界面多文档界面( MDI) 与 单文档界面( SDI)
MDI指在一个父窗体下面可以同时打开多个子窗体 (多个文档窗体 );如 Word
SDI指只能打开一个文档。如,记事本”
1,创建和设计 MDI窗体 及其 子窗体
创建 MDI窗体,“工程” |“添加 MDI窗体”,在“添加 MDI窗体”
对话框中选择新建,MDI窗体”图标,单击“打开”按钮。如图
8-8。
图 8-8 添加 MDI窗体
创建子窗体,通过“工程 |添加窗体”创建一般的标准窗体,把
MDIChild属性置为 True 。 MDI窗体可以有多个子窗体。
2,MDI窗体与子窗体的交互
MDI窗体的两个属性,ActiveForm和 ActiveControl。
MDI应用程序运行时,任何时候只有一个子窗体是激活的,这个子窗体具有输入焦点。
ActiveForm返回活动窗体。
例如,Unload ActiveForm语句指关闭当前活动子窗体。
ActiveControl返回拥有焦点的控件。
例如,ActiveForm.ActiveControl.SelText引用 MDI子窗体的活动控件中的文本。
QueryUnload事件卸载 MDI窗体。
QueryUnload事件是在任一个卸载之前在所有窗体中发生,它提供了停止窗体卸载的机会,在关闭一个应用程序之前确保包含在该应用程序中的窗体中没有未完成的任务。
3,多文档界面应用程序中的“窗口”菜单
VB的 Arrange方法提供了 MDI子窗体的各种排列方式,包括,水平平铺,,,垂直平铺,,,层叠,和,排列图标,。
Arrange方法的语法格式如下:
MDI窗体,Arrange 方法值符号常数 Ar r ang e 的方法值 说明
vbCascade 0 层叠所有非最小化 M DI 子窗体。
vb T i l eH or i zo nt al 1 水平平铺所有非最小化 M DI 子窗体。
vb T i l eV er t i cal 2 垂直平铺所有非最小化 M DI 子窗体。
vb Ar r ang eI con s 3 重排最小化 M DI 子窗体的图标。
要在某个菜单上显示所有打开的子窗体标题,可以利用菜单编辑器选定该菜单的显示窗口列表项或将该菜单的 WindowList属性设置为 True。
表 8-1Arrange方法值图 8-9 多文档录入例 8-1新建一个工程,包含两个窗体:主窗体 MDIForm1和文档录入窗体 frmDocument。其中 MDIForm1是 MDI窗体,frmDocument
窗体为子窗体(即 MDIChild属性设置为 True)。 MDIForm1窗体
“文件”菜单包含“新建”、“关闭”和“退出”三个子菜单;
“窗口”菜单包含“水平平铺”、“垂直平铺”、“层叠”和
“排列图标” 。 frmDocument窗体上只有一个文本框控件 Text1,
用以录入文本。将 MDIForm1设置为启动窗体(见 8.2.1节),运行程序,首先载入
MDIForm1窗体,并自动新建“文档 1”,如图 8-9所示。
图 8-10 新建文档 2
图 8-11 窗口菜单 图 8-12垂直平铺窗口单击“文件”菜单的“新建”项,在主窗体中出现另外一个编辑文档窗口“文档 2”,如图 8-10。在“窗口”菜单中可以看见这两个窗口的名字“文档 1”和“文档 2”,并且当前“文档 2”为活动窗口,如图 8-11。选择窗口菜单中的“垂直平铺”,排列窗口的效果如图 8-12。
8.2 多重窗体应用程序的执行与保存图 8-13 设置启动窗体
8.2.1 设置启动窗体设置启动窗体的一般操作步骤:
( 1)从“工程”菜单中,单击“工程属性”选项。或者在工程资源管理器中点击鼠标右键弹出快捷菜单,选择“工程属性”
项。
( 2)在“工程属性”对话框中,选择“通用”选项卡。
( 3)在“启动对象”下拉列表框中,选择作为启动窗体的窗体。
( 4)单击“确定”按钮。
8.2.2 多重窗体工程的保存与打开保存程序文件:应保存工程中每个窗体文件和工程文件。
打开程序文件:只要打开工程文件(,vbp),系统将自动打开并装载该工程的所有文件。
生成 exe程序文件:在“文件”菜单中选取“生成
×××,exe”,从打开的“生成工程”对话框选择存放可执行文件的文件夹,并在文件名框内输入文件名,按“确定”按钮即可生成该工程的可执行文件,如图 8-14。
图 8-14生成可执行文件
8.3 VB工程结构
VB工程包括工程文件(,vbp)、窗体模块(,frm)、窗体的二进制数据文件(,frx)、标准模块(,bas)、类模块(,cls)、
资源文件(,res),ActiveX控件文件(,ocx)、用户控件(,ctl)
和属性页模块(,pag)、及其它 Activex控件、设计器、可插入对象等部件和引用。本节主要介绍窗体模块和标准模块。
8.3.1 窗体模块在工程中创建一个窗体,则同时创建一个窗体模块( *.frm),
VB工程可以包含一个或多个窗体模块。窗体模块通常包括窗体可见设计部分和代码部分。代码部分包括声明、通用过程和事件过程。若窗体中对象含有二进制属性,保存该窗体时将自动生成同名的二进制数据文件,扩展名为,frx。
窗体模块中如果包含 Form_Load过程,窗体启动时将首先执行该过程。
窗体模块可以调用在该应用程序内其它窗体模块中定义的公共函数或过程(即以 Public定义),但在调用时必须加上被调过程所在窗体的窗体名作为限定词,调用格式:
<窗体名 >.过程或函数名(参数列表)
例 8-2在 Form1中单击“输入”按钮( CmdInput)输入进行计算的数据个数及数据,单击“计算”按钮( CmdCalculate),可引用在 Form2中定义的求数组中最小值的公共函数计算输入的数据中的最小值。
图 8-15 引用其它窗体定义的函数
Private Sub CmdInput_Click() ',输入”按钮
On Error GoTo PROC_ERR ' 错误处理,转向标号 PROC_ERR处执行
b = ""
num = InputBox("输入进行计算的数据个数,")
ReDim a(num)
For i = 0 To num - 1 '输入 num个进行计算的数据
a(i) = InputBox("输入第 " & i + 1 & "个数据,")
b = b & Str$(a(i)) & ","
Next i
Text1.Text = b
Text2.Text = ""
CmdCalculate.Enabled = True
PROC_ERR,Exit Sub
End Sub
Private Sub CmdCalculate_Click() ',计算”按钮
mindata = Form2.min(a(),num) '引用 Form2中定义的计算最小值的函数
Text2.Text = Str$(mindata)
End Sub
Form2中定义的代码:
Function min(b() As Integer,n As Integer) '求 n个数中最小值
Dim temp As Integer,i As Integer
temp = b(0)
For i = 1 To n - 1
If b(i) < temp Then
temp = b(i)
End If
Next i
min = temp
End Function
思考,将语句 mindata = Form2.min(a(),num)改为 mindata = min(a(),
num),如何?
8.3.2 标准模块标准模块包括全局变量和常量声明、公共过程和函数、以及模块级声明。模块级声明是声明在标准模块中使用的变量和常量。
模块级变量用 Dim声明,全局变量用 Public声明。标准模块的文件扩展名为,bas,一个应用程序中可以包含多个标准模块文件。
图 8-16 添加模块添加方法:执行“工程”菜单中“添加模块”,或者在“工程资源管理器”窗口点击鼠标右键从弹出的快捷菜单中选择“添加模块”,在出现“添加模块”对话框中选择“新建”选项卡,如图
8-16。
注意,在标准模块定义的公共函数或过程可以在所有窗体模块中直接调用,无需加上该标准模块名作为限定。
如果例 8-2的 Form2的代码定义在标准模块中,则 Form1中引用标准模块中定义的计算最小值函数的语句为 mindata =
min(a(),num)即可。
8.3.3 Sub Main过程在运行启动窗体之前需要进行一些初始化的工作或者先运行装入数据文件的代码,再根据初始化的结果或数据文件的内容决定显示几个不同窗体中的一个,可利用 Sub Main过程控制。 例,
Sub main()
i = InputBox("请输入 1,或 2,或 3")
Select Case i
Case "1",Form1.Show
Case "2",Form2.Show
Case "3",Form3.Show
End Select
End Sub
创建方法,打开一个标准模块代码窗口,输入,Sub Main”回车,
然后在该过程中编写代码即可。
注意,
( 1) Sub Main是一个子过程且必须建立在一个标准模块中,并且一个程序中只能有一个 Sub Main。
( 2) 如果程序中设计了 Sub Main,则程序必从 Sub Main开始执行。
8.4* 闲置循环与 Do Events语句闲置循环就是当应用程序处于闲置状态时,用一个循环来执行(即闲置循环)。当执行闲置循环时,将占用全部 CPU的时间,不允许再执行其他事件过程。
DoEvents语句可以将控制切换到操作环境内核,此环境中的所有应用程序都有机会响应待处理事件。这使得应用程序不放弃焦点,其它事件和程序也能得到响应。
例 8-3界面设置两个命令按钮 Cmd1( Caption属性为“按键运行”)和 CmdExit( Caption属性为“退出”)、两个标签
( Caption属性分别为“文本框 1”和“文本框 2”),两个文本框
Text1和 Text2(用于显示运行结果),如图 8-17。
图 8-17 Doevents示例
Cmd1_Click代码:
Private Sub Cmd1_Click()
Dim i As Integer,j As Long
For i = 1 To 20
Text1.Text = i
For j = 1 To 50000
Next j
Next i
Text2.Text =,Finished”
End Sub
程序运行,直接在文本框
Text1中出现 20,同时文本框
Text2中出现,Finished”。
Cmd1_Click修改后代码:
Private Sub Cmd1_Click()
Dim i As Long,j As Long
For i = 1 To 20
Text1.Text = i
For j = 1 To 50000
DoEvents
Next
Next
Text2.Text = "Finished"
End Sub
文本框 Text1中显示由 1变化到
20,然后文本框 Text2中出现
,Finished”。这是因为在执行内层较长循环的时候系统非常繁忙,可以调用 DoEvents函数释放系统内存来完成其他请求。
注意,对于应用程序中的关键部分需要独占计算机的资源,必须防止其他任何中断(如键盘、鼠标等)时不能使用 DoEvents。