




版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
第12章
多重窗体与MDI窗体程序设计多重窗体与MDI窗体概述多重窗体程序设计MDI窗体程序设计12.1多重窗体与MDI窗体概述多重窗体是指一个应用程序中有多个并列的普通窗体,每个窗体都是一个对象,可以有属于自己的对象、属性和事件过程,完成不同的功能。MDI窗体是指一个应用程序(父窗体)中包含多个文档(子窗体),绝大多数基于Windows的大型应用程序都是MDI窗体,如MicrosoftExcel和MicrosoftWord等应用程序都是MDI窗体程序。MDI窗体可以同时打开多个文档,它简化了文档之间的信息交换。在多重窗体中,窗体分为模态(Modal)和非模态(Nonmodal)两种类型。在屏幕上显示后用户必须响应的窗体叫模态(Modal)窗体,除非用户单击OK(确定)或Cancel(取消)按钮、或者关闭这个窗体,否则这种窗体将一直得到输入焦点。用户可以随意在其间切换的窗体叫非模态(Nonmodal)窗体或无模式窗体。为了方便用户使用,大多数Windows下的应用程序在显示信息时,都使用非模态窗体。因此,在VisualBasic中建立新窗体时,非模态窗体是缺省设置。窗体的很多属性都可以独立设置,其中包括窗体的标题、大小、边框类型、前景颜色、背景颜色、显示字库和背景画面等。MDI窗体允许创建在单个容器窗体中包含多个窗体的应用程序,允许用户同时显示多个文档,每个文档显示在它自己的窗体中。MDI窗体是有父子关系的窗体,可以根据窗体作用的不同,来确定窗体是父窗体还是子窗体。文档或子窗体被包含在父窗体中,父窗体为应用程序中所有的子窗体提供工作空间,用户在父窗体完成几乎所有的工作。例如:MicrosoftExcel允许创建并显示不同样式的多文档窗体,每个子窗体都被限制在Excel父窗体的区域之内。当最小化Excel父窗体时,所有的文档窗体都被最小化,只有父窗体的图标显示在任务栏中。当关闭Excel父窗体时,所有的文档窗体都被关闭,但关闭某个文档窗口时,Excel父窗体不会被关闭。具体什么时候选用单窗体程序,什么时候使用多重窗体或MDI窗体呢?这需要根据应用程序的目的,来决定使用哪种界面样式最好。例如:日历程序最好设成单窗体程序,因为没有必要同时打开一个以上日历;一个处理保险索赔的应用程序可能要设计成MDI窗体,使用多文档界面样式,因为一个职员很可能会同时处理一个以上索赔,或者需要对两个索赔进行比较;而一个管理信息系统(MIS系统),需要完成的功能比较多,比如最基本的功能添加、修改、删除和查询记录等,这些功能的实现都需要窗体界面,而这些窗体一般都是并列使用,所以像学生成绩管理系统这样的应用程序一般设计成多重窗体程序。12.2多重窗体程序设计在多重窗体程序中,要建立的界面由多个窗体组成,每个窗体的界面的设计与前面学过的完全一样。程序代码也是针对每个窗体编写的,因此也与单一窗体程序设计中的代码编写类似,只要注意各个窗体之间的相互关系就可以了。多重窗体实际上是单一窗体的集合,而单一窗体是多重窗体程序设计的基础。掌握了单一窗体程序的设计,多重窗体的程序设计是很容易的。12.2.1添加窗体如果想在现有的工程中添加一个窗体,需要使用“添加窗体”对话框,如右图所示,可以用三种方法打开“添加窗体”对话框:“新建”选项卡(1)通过“工程”(Project)菜单中的“添加窗体”(AddForm)命令。(2)单击工具栏上的“添加窗体”按钮。(3)在“工程资源管理器”窗口内单击右键,在弹出菜单中选择“添加”,再在下一级子菜单中选择“添加窗体”。在“添加窗体”对话框里,可以选择“新建”选项卡新建一个窗体,也可以选择“现存”选项卡把一个属于其他工程的窗体添加到当前工程中,这是因为每个窗体都是以独立的文件保存的(扩展名为frm)。当新建一个窗体时,可以选择欲建立窗体的类型(VisualBasic的不同版本预定义窗体集也不一样),默认是建立一个新的空白窗体,你可以选择建立为特定任务设计的半成品窗体。程序中第一个窗体被默认命名为Form1,后续的窗体则分别命名为Form2、Form3等,为了便于在代码中引用窗体,最好是根据窗体的功能进行重新命名。当添加一个已经存在的窗体到当前工程时,有两个问题需要注意:(1)该工程内的每个窗体的Name属性不能相同,否则不能将现存的窗体添加进来。(2)在该工程内添加进来的现存窗体实际上在多个工程中共享,因此,对该窗体所做的改变,会影响到共享该窗体的所有工程。12.2.2设置启动对象在单一窗体程序中,程序的执行没有其他选择,即只能从这个窗体开始执行。多重窗体程序由多个窗体构成,而且多个窗体多是并列关系,VisualBasic怎么知道是从哪个窗体开始执行呢?程序运行过程中,首先执行的对象被称为启动对象。VisualBasic规定,对于多重窗体程序,必须指定其中一个对象为启动对象。缺省情况下,第一个创建的窗体被默认指定为启动对象,即启动窗体。启动对象既可以是窗体,也可以是Main子过程。如果启动对象是Main子过程,则程序启动时不加载任何窗体,以后由该过程根据不同的情况决定是否加载或加载哪一个窗体。需要注意的是,Main子过程必须放在标准模块中,绝对不能放在窗体模块内。可以通过“工程”菜单中“工程属性”命令来指定启动对象。执行该命令后,将打开“工程属性”对话框,然后选择该对话框中的“通用”选项卡,将显示的对话框如图右所示。“通用”选项卡在前图所示的对话框中,单击“启动对象”栏右端的箭头,将下拉显示当前工程中所有窗体的列表,如下图所示。此时条形光标位于当前启动对象上,如果需要改变,则单击作为启动对象的名字,然后单击“确定”按钮,即可把所选择的窗体设置为启动对象。指定启动对象12.2.3与多重窗体程序设计有关的语句和方法在单窗体程序设计中,所有的操作都在一个窗体中完成,不需要在多个窗体间切换。而在多窗体程序中,需要打开、关闭、隐藏或显示指定的窗体,这可以通过相应的语句和方法来实现。下面介绍与多重窗体程序设计有关的语句和方法。1.Load语句该语句把一个在编程环境中已经建立的窗体装入内存。当VisualBasic执行了该语句后,窗体并没有显示出来,只是被调入内存,但你可以在程序中的任一事件过程中访问它,而且使用它所定义的任何属性和方法。用Load语句装入新窗体的语法格式为:例如,语句:LoadForm2,则工程中名称为Form2的窗体就会被调入内存。如果想把该窗体的Caption属性设置为“系统主界面”,可在任何事件过程中键入下述语句:Form2.Caption="系统主界面"。在首次使用Load语句将窗体调入内存时依次触发窗体的Initialize和Load事件。Load窗体名称2.Unload语句该语句与Load语句的功能相反,它从内存中删除指定的窗体。该语句的语法格式为:Unload窗体名称Unload的一种常见用法是UnloadMe,其意义是关闭窗体自己。在这里,关键字Me代表UnloadMe语句所在的窗体。3.Show方法该方法用来显示一个窗体,它兼有加载和显示窗体两种功能。也就是说,使用Show方法时,如果窗体不在内存中(即以前没有执行Load语句),则Show方法自动把窗体装入内存,然后再显示出来。Show方法的语法格式为:[窗体名称.]Show[模式]如果省略了“窗体名称”,则显示当前窗体。参数“模式”用来确定窗体是以模态加载还是非模态加载,它可以取0和1两个值(注意不是False和True)。当“模式”值为1(或常量vbModal)时,表示窗体是“模态型”窗体。在这种情况下,鼠标只在此窗体内起作用,不能到其他窗口内操作,只有在关闭该窗口后才能对其他窗口进行操作。例如,MicrosoftWord中“帮助”菜单的“关于”命令所打开的对话框窗口就是这种窗口。当“模式”值为0(或省略该参数)时,表示窗体为“非模态型”窗口,不用关闭该窗体就可以对其他窗口进行操作。例如,要以非模态窗体形式显示Form2,可使用如下语句:Form2.Show。VisualBasic提供独立的Load语句使程序能够预先将窗体装入内存,这样,Show方法执行得会非常快,用户往往感觉不到任何延迟。建议你最好预先装入窗体,特别是当窗体包含很多对象或艺术修饰时,这样做尤其必要。4.Hide方法该方法用来将窗体暂时隐藏起来,但并没有从内存中删除,因此它与Unload语句的作用是不一样的。其语法格式为:当省略窗体名称时,默认隐藏当前窗体。Hide方法和Unload语句的区别:使用Hide方法把窗体隐藏后,窗体虽然看不见了,但它仍驻留在内存中,可以供程序使用。隐藏窗体和通过设置窗体的Visible属性使窗体不可见的效果是相同的。使用Unload语句卸载窗体,是把窗体从内存中清除,卸载窗体释放了用来存储窗体对象和图形的内存空间,但并不释放窗体事件过程占用的空间,这些事件过程常驻内存。窗体被卸载后,其运行时的值和属性也就丢失了。当再装入该窗体时,这些值恢复为程序代码中设定的初始值。[窗体名称.]Hide12.2.4不同窗体间数据的存取不同窗体数据的存取分为两种情况:(1)存取控件中的属性在当前窗体中要存取另一个窗体中某个控件的属性,表示如下:另一个窗体名称.控件名.属性例如,设置当前窗体(Form1)中的文本框(Text1)的值,使它等于另一个窗体(Form2)中的两个文本框(Text1和Text2)的数值之和,实现的语句如下:(2)存取变量的值根据变量的定义位置和所使用的变量定义语句的不同,VisualBasic中的变量可以分为3类,即局部变量、模块变量及全局变量,其中模块变量包括窗体模块变量和标准模块变量。各种变量位于不同的层次。Text1.Text=Val(Form2.Text1.Text)+Val(Form2.Text2.Text)在过程(事件过程或通用过程)内定义的变量叫做局部变量,其作用域是它所在的过程。某一过程的执行只对该过程内的变量产生作用,对其他过程中相同名字的局部变量没有任何影响。因此,可以在不同的过程中定义相同名字的局部变量,它们之间没有任何关系。对于局部变量,可以使用Dim或Static语句声明,也可以在需要时直接给出变量名。变量的类型可以使用类型说明符标识。如果没有类型说明符,VisualBasic把该变量指定为变体数据类型。窗体变量可用于该窗体内的所有过程。一个窗体可以包含若干个过程,当同一窗体内的不同过程使用相同的变量时,则可以使用窗体变量。在使用窗体变量前,必须先声明,也就是说窗体变量不能默认声明。其方法是在程序代码窗口的“对象”框中选择“通用”,并在“过程”框中选择“声明”。声明的时候,可以使用Dim、Private或Public语句。标准模块变量与窗体变量是类似,这里不在叙述。全局变量的作用域最大,可以在工程的每个模块、每个过程使用。和模块级变量类似,全局变量也在“通用”部分声明。所不同的是,全局变量必须用Public或Global语句声明,不能用Dim语句声明,更不能用Private语句声明。同时,全局变量只能在标准模块中声明,不能在过程或窗体模块中声明。在应用程序中任何地方都可以修改全局变量,因此使用全局变量要格外小心,特别是在没有强制要求定义变量的情况下。我们在多个窗体之间存取变量时,变量必须是窗体级变量,先用Public语句声明,其引用格式如下:例如,工程中有两个窗体(Form1和Form2),在Form1的“通用”里这样声明一个变量:PublictestAsString,则在Form2中就可以这样引用Form1中的变量:a=Form1.test为了方便起见,要在多个窗体中存取的变量一般放在一个标准模块内,用Public语句或Global语句声明成全局变量。窗体名称.变量名12.2.5多重窗体程序设计举例例12.1
输入学生五门课程的成绩,计算总分及平均分并显示。本例有三个窗体,名称分别为frmMain、frmInput和frmOutput,其中frmMain作为本程序的主窗体,frmInput和frmOutput分别作为本程序的输入和输出窗体。另外,还要添加一个标准模块Module1,在这个标准模块内声明多窗体间共用的全局变量。工程资源管理器窗口如下图所示。工程资源管理器窗口frmMain窗体如下图所示,这是本程序的主窗体,运行后看到的第一个窗体。该窗体上有三个命令按钮,标题分别为:“输入成绩”、“计算成绩”和“结束程序”;名称分别为:cmdInput、cmdOutput和cmdExit,其中“输入成绩”和“计算成绩”按钮分别用来显示frmInput和frmOutput窗体。frmMain窗体frmInput窗体如左图所示,这是当在主窗体上单击了“输入成绩”按钮后弹出的窗体。该窗体上有五个用于输入学生成绩的文本框,名称分别为:txtMath、txtChem、txtEng、txtPhy和txtChin。还有一个命令按钮,标题为“确定”,名称为:cmdOk。frmOutput窗体如右图所示,这是当在主窗体上单击了“计算成绩”按钮后弹出的窗体。该窗体上有用于显示学生平均成绩和总分的标签,名称为:labelAverage和LabelTotal。还有一个命令按钮,标题为“返回”,名称为“cmdReturn”。
frmInput窗体frmOutput窗体在Module1标准模块内,声明了在多个窗体间共用的全局变量,即:PublicsMathAsSinglePublicsChemAsSinglePublicsEngAsSinglePublicsPhyAsSinglePublicsChinAsSingle主窗体frmMain的事件过程如下:PrivateSubcmdInput_Click()Me.HidefrmInput.ShowEndSubPrivateSubcmdOutput_Click()Me.HidefrmOutput.ShowEndSubPrivateSubcmdExit_Click()EndEndSub输入成绩窗体frmInput的事件过程为:PrivateSubcmdOk_Click()sMath=Val(txtMath.Text)sChem=Val(txtChem.Text)sEng=Val(txtEng.Text)sPhy=Val(txtPhy.Text)sChin=Val(txtChin.Text)Me.HidefrmMain.ShowEndSub计算成绩窗体frmOutput的事件过程如下:PrivateSubForm_Load()DimsTotalAsSinglesTotal=sMath+sChem+sEng+sPhy+sChinlabelAverage.Caption=sTotal/5LabelTotal.Caption=sTotalEndSubPrivateSubcmdReturn_Click()Me.HidefrmMain.ShowEndSub对于不同窗体间数据的存取,我们在前面已介绍了两种方法,大家可以试着用另一种方法来实现本程序的功能。例12.2
设计一个模拟登陆系统程序,当输入正确的用户名和密码时,显示程序主窗体,并在主窗体上显示用户名。当用户输入错误时,提示用户重新输入,并且最多可以输入三次。本例程序需要两个窗体(frmLogin和frmMain),一个标准模块(Module1)。frmLogin窗体就是一个自定义对话框,如下图所示。窗体上有两个文本框分别用来接收用户输入的用户名和密码,它们的名称为txtName和txtPwd,其中txtPwd的PasswordChar属性设置为“*”。窗体上还有两个命令按钮,标题为“确定”和“取消”,名称为“cmdOK”和“cmdCancel”。为了不让用户随意改变窗体的大小,再把窗体的BorderStyle属性设置为3。frmLogin窗体frmMain窗体比较简单,用一个标签(LabelName)显示当前用户的用户名,一个命令按钮(cmdExit)用来关闭本窗口,如下图所示。frmMain窗体在标准模块(Module1)内声明一个全局变量,用来存放用户输入的用户名,如下:PublicuserAsStringfrmLogin窗体内的事件过程如下:DimtryAsIntegerPrivateSubcmdCancel_Click()UnloadMeEndSubPrivateSubcmdOK_Click()IftxtName.Text=""ThenMsgBox"请输入用户名!",vbOKOnly+vbExclamation,"错误"txtName.SetFocusExitSubEndIfIftxtPwd.Text=""ThenMsgBox"请输入密码!",vbOKOnly+vbExclamation,"错误"txtPwd.SetFocusExitSubEndIfIfTrim(txtName.Text)="vb"AndTrim(txtPwd.Text)="love"ThenMsgBox"你是合法用户,欢迎使用!",vbOKOnly+vbInformation,"欢迎进入"user=Trim(txtName.Text)UnloadMefrmMain.ShowElsetry=try+1Iftry>=3ThenUnloadMeExitSubEndIfMsgBox"用户名或密码错误!您还有"&3-try&"次机会!",vbOKOnly+vbCritical,"警告"txtName.SetFocustxtName.Text=""txtPwd.Text=""EndIfEndSubfrmMain窗体内的事件过程比较简单,如下所示:PrivateSubForm_Load()LabelName.Caption=userEndSubPrivateSubcmdExit_Click()UnloadMeEndSub12.3MDI窗体程序设计MDI窗体程序由父窗口和子窗口组成,父窗口又称MDI窗体,它被作为子窗口的容器。子窗口又称文档窗口,它用于显示各个文档,所有的子窗口都具有相同的功能。12.3.1MDI窗体特性在运行时,MDI窗体及其所有的子窗体都呈现特定的性质,如下所述。(1)所有子窗体均显示在MDI窗体的工作空间内。像其他的窗体一样,用户能移动子窗体和改变子窗体的大小,不过,它们被限制于这一工作空间内。(2)最小化一个子窗体时,它的图标将显示于MDI窗体上而不是在任务栏中。最小化MDI窗体时,此MDI窗体及其所有子窗体将由一个图标来代表。还原MDI窗体时,MDI窗体及其所有子窗体将按最小化之前的状态显示出来。(3)最大化一个子窗体时,它的标题会与MDI窗体的标题组合在一起并显示于MDI窗体的标题栏上。(4)通过设定AutoShowChildren属性,子窗体可以在窗体加载时自动显示(True)或自动隐藏(False)。(5)活动子窗体的菜单(若有)将显示在MDI窗体的菜单栏中,而不是显示在子窗体中。MDI窗体程序在所谓的“以文档为中心的应用”中特别有用,在这种应用程序中,通常同时使用多个窗口来显示或编辑文档。12.3.2创建MDI应用程序前面已经学习过,可以通过“添加窗体”对话框添加窗体,但这不是MDI窗体,只是多个普通窗体而已。如果创建一个MDI窗体应用程序,可以按以下步骤执行:(1)在“工程”菜单中单击“添加MDI窗体”菜单项,可以创建MDI应用程序的父窗体。注意,一个应用程序只能有一个MDI窗体,如果工程已经有了一个MDI窗体,则该“工程”菜单上的“添加MDI窗体”命令就不可使用。MDI应用程序的父窗体是子窗体的容器,在该窗体中可以有菜单栏、工具栏、状态栏等,但不可以有文本框等控件。(2)如果要创建子窗体,首先在“工程”菜单中单击“添加窗体”菜单项,创建一个普通的窗体,然后将该窗体的MDIChild属性设为True。一个应用程序可以包含许多相似或者不同样式的MDI子窗体。若要建立多个子窗体,则重复上述操作就可以了。不过,创建以文档为中心的应用程序,一般要求在运行时能提供若干子窗体以存取不同的文档,而在设计时事先创建好若干个子窗体的方法是不可取的。一般是先创建一个子窗体作为这个应用程序文档的模板,然后通过对象变量来实现。例如,假设已经建立了一个名称为“frmMDIChild”的子窗体模板,则使用下面的语句:就会为“frmMDIChild”建立一个新的实例NewDoc,新实例具有与“frmMDIChild”窗体相同的属性、控件和代码。在运行时,子窗体显示在MDI父窗体工作空间之内(其区域在父窗体边框以内及标题与菜单栏之下)。在设计时,子窗体并未被限制在MDI窗体区域之内,可以添加控件、设置属性、编写代码以及设计子窗体功能,就像在其他VisualBasic窗体中做的那样。DimNewDocAsNewfrmMDIChild通过查看MDIChild属性或者检查工程资源管理器,可以确定窗体是否是一个MDI子窗体。VisualBasic在“工程资源管理器”中为MDI窗体与MDI子窗体显示了特定的图标,如下图所示。“工程资源管理器”中的MDI窗体、MDI子窗体和标准窗体例12.3
设计一个简单的多文档记事本程序,在这个应用程序中,用户可以打开多个文档进行简单编辑。用我们前面介绍的方法,建立MDI窗体应用程序的父窗体,在父窗体上设计程序中需要的菜单,各菜单项的属性如下表所示菜单项Name属性菜单项Name属性文件mnuFile编辑mnuEdit….新建mnuNew….剪切mnuCut….保存mnuSave….全选mnuSelect….-mnuBar….退出mnuExit菜单属性列表还要添加一个通用对话框控件(CommonDialog1)用来打开“另存为”对话框。最后把父窗体的Caption属性设置为“多文档记事本”,设计完整的父窗体如下图所示。设计完整的父窗体添加MDI窗体程序的子窗体,首先添加一个普通窗体,然后把它的MDIChild属性设置为True,名称为“frmChild”,Caption属性为“文档”。要实现应用程序的编辑功能,需要在子窗体中引入一个文本框控件(Text1),设置Text1的MultiLine属性为True,ScrollBars属性值为3,即水平和垂直滚动条都存在。在程序代码中,需要建立一个子程序来完成新建文档的功能。则在父窗体的“通用”里新建一个过程LoadNewDoc,用来完成新建文档的功能,代码如下所示:PrivateSubLoadNewDoc()StaticDocCountAsLong'定义一个用于记数的静态变量DimfrmDocAsfrmChild'定义frmDoc作为窗体对象DocCount=DocCount+1'每调用一次,记数加1SetfrmDoc=NewfrmChild'新建一个文档窗体frmDoc.Caption="文档"&DocCountfrmDoc.ShowEndSub在父窗体的“文件”菜单中“新建”菜单项的Click事件过程中编写如下代码:关于父窗体的“文件”菜单中其他菜单项的事件过程,涉及到后面的文件操作,这里不再介绍,有兴趣的同学可以自己试着编写代码。下面介绍“编辑”菜单中“剪切”菜单项和“全选”菜单项代码的编写。在程序运行时建立了子窗体的许多实例(副本)来存取多个文档时,它们具有相同的属性和代码,然后操作特定的窗体和特定的控件、保持各自的状态信息,这对程序员来说是一个非常重要的问题。在VisualBasic中,提供了访问MDI窗体的两个属性:ActiveForm和ActiveControl,前者表示具有焦点的或者最后被激活的子窗体,在程序中用它可以自动识别当前活动窗体,后者表示活动子窗体上具有焦点的控件。PrivateSubmnuNew_Click()LoadNewDocEndSub“剪切”菜单项的Click事件过程中的代码如下:“全选”菜单项的Click事件过程中的代码如下:PrivateSubmnuCut_Click()'将父窗体中活动的子窗体中的选中文本复制到剪贴板Clipboard.SetTextMDIForm1.ActiveForm.ActiveControl.SelText'清除活动窗体选中的文本MDIForm1.ActiveForm.ActiveControl.SelText=""EndSubPrivateSubmnuSelect_Click()'使用SelStart和SelLength选定文本MDIForm1.ActiveForm.Text1.SelStart=0MDIForm1.ActiveForm.Text1.SelLength=Len(MDIForm1.ActiveForm.Text1.Text)EndSub最后,在frmChild窗体的Form_Resize事件过程中添加如下代码:上述代码的作用是,当子窗体的尺寸改变时,其中的文本框也跟着改变。PrivateSubForm_Resize()MDIForm1.ActiveForm.Text1.Left=MDIForm1.ActiveForm.ScaleLeftMDIForm1.ActiveForm.Text1.Top=MDIForm1.ActiveForm.ScaleTopMDIForm1.ActiveForm.Text1.Width=MDIForm1.ActiveForm.ScaleWidthMDIForm1.ActiveForm.Text1.Height=MDIForm1.ActiveForm.ScaleHeightEndSub12.3.3MDI窗体及子窗体1.加载MDI窗体及子窗体加载子窗体时,其父窗体(MDI窗体)会自动加载并显示。而加载MDI窗体时,其子窗体并不会自动加载。在例12.3中,子窗体是缺省的启动窗体,因而在程序运行时,子窗体和MDI窗体两者都会加载。如果在应用程序中改变启动窗体为MDIForm1,然后运行应用程序,则只有MDI窗体被加载。当从“文件”菜单中选取“新建”命令时,才会加载第一个子窗体。MDI窗体有AutoShowChildren属性,决定是否自动显示子窗体。如果该属性被设置为True,则当改变子窗体的属性(如Caption等)后,会自动显示该子窗体,不再需要使用Show方法;如果设置该属性为False,则改变子窗体的属性值后,不会自动显示该子窗体,子窗体处于隐藏状态,直至用Show方法把它们显示出来。这就允许在子窗体变成可见之前更新标题、位置和菜单等各种细节。2.设置子窗体的大小和位置如果MDI子窗体具有大小可变的边框〔即BorderStyle=2〕,在其装载时,Windows将决定其初始的高度、宽度和位置。边框大小可变的子窗体,其初始大小与位置取决于MDI窗体的大小,而不是设计时子窗体的大小。当MDI子窗体的边框大小不可变(即BorderStyle=0、1或3)时,则它将用设计时的Height和Width属性被载入。如果设置AutoShowChildren为False,则在MDI子窗体载入以后,把它设为可见状态之前,可以改变其大小和位置。定位窗体的代码最好放在窗体的Load过程中,这样会在窗体实际出现在屏幕上之前将窗体位置确定。要将窗体居中,需要在窗体的Load过程中简单地添加代码来计算并指定窗体左上角的位置,如下列代码所示:利用坐标系统可以将窗体定位于屏幕或MDI窗体的任意位置。Me.Left=(Screen.Width-Me.Width)/2Me.Top=(Screen.Height-Me.Height)/23.MDI窗体程序子窗体的排列顺序和方式在MDI应用程序中,缺省状态下子窗体是按照窗口打开的顺序排列的:当前活动窗体排在最前端,最先打开的窗体排在最底端。我们可以借助ZOrder方法动态地改变子窗体的排列顺序。ZOrder方法的语法为:其中,Position取值为0时表示对象移至最前端,为1时表示对象移至最底端,缺省时值为0。例如,某一MDI应用程序有三个子窗体:Form1、Form2和Form3,若要将Form3移至最底端,则可在设计代码时加上Form3.Zorder1即可。利用Zorder方法我们也可以创建浮动窗体,浮动窗体总是浮动到表面,也就是说它可以被其他窗体覆盖,但马上自动变成当前窗口并显示在所有窗体的最上层。窗体名称.ZOrder[Position]要创建浮动窗体,需要在窗体上添加一个定时器控件,并将它的Interval属性设置为想让窗体浮现的时间,如500毫秒。在Timer1_Timer事件过程中编写如下代码,便可以使用ZOrder方法使窗体浮动到顶部:使用过Word的用户都知道,Word可同时打开多个文档,并能以不同方式对文档窗口进行排列,如平铺、层叠等。这种重新排列子窗体的功能,在MDI应用程序中是可以通过编程来实现的。具体方法就是在相应的菜单控件的Click事件中调用Arrange方法,使用Arrange方法可以重新对齐子窗体,可以层叠、水平平铺或者沿着MDI窗体的下部排列子窗体图标等方式来显示子窗体。Arrange方法的语法为:PrivateSubTimer1_Timer()ZOrderEndSubMDI窗体对象.ArrangeArrangement其中,Arrangement用来指定如何排列MDI应用程序的子窗体,其值可以是常数或数值,Arrangement的取值如下表所示。常数值描述vbCascade0层叠所有非最小化MDI子窗体vbTileHorizontal1水平平铺所有非最小化MDI子窗体vbTileVertical2垂直平铺所有非最小化MDI子窗体vbArrangeIcons3重排最小化MDI子窗体的图标Arrangement的取值例如:若“平铺”菜单项名为mnuHorizon,可编写如下代码,实现子窗体的平铺:当平铺或者层叠有着固定边框类型的子窗体时,每个子窗体都像具有可变尺寸边框那样被定位,这使得子窗体可能重叠。即使MDI窗体被最小化,仍可以重新排列窗口和图标,当MDI窗体最大化时,可以看到重排的结果。PrivateSubmnuHorizon_Click()MDIForm1.ArrangevbTileHorizontal'MDIForm1为MDI窗体名称EndSub4.维护子窗体的状态信息当子窗体被卸载时,其中的内容也会随之消失,所以在用户决定退出MDI应用程序时,必须有保存信息的机会,让用户执行存盘操作,这样才能确保数据不会丢失。当数据没有改变而去存盘是没有意义的,因此,应用程序必须随时都能确定自上次保存以来子窗体中的数据是否有改变。这可以通过在每个子窗体中声明一个公用变量来实现此功能,例如:当子窗体中的内容改变时,可将此变量设为True。在保存完数据后,再设为False。PublicDataChangeedAsBoolean在MDI应用程序中,在关闭应用程序时,VisualBasic将试图卸载MDI窗体,当MDI窗体被卸载时,QueryUnload事件首先为MDI窗体调用,然后再为每一个打开的子窗体调用。如果在这些QueryUnload事件过程中没有代码,则取消Unload事件,然后,每一个子窗体被卸载,最后MDI窗体被卸载。由于QueryUnload事件在窗体卸载之前被调用,因此在窗体卸载前可以给用户一个保存窗体、文件和一些数据的机会。我们可以在该事件过程中,判断前面声明的那个公用变量标志,然后提示用户是否执行保存操作,也可以在窗体的卸载事件(Unload)中判断此变量标志,这样,在MDI应用程序退出时就不会丢失数据了。5.显示所有已打开子窗体标题如果想要实现这一功能,只要在设计MDI窗体及子窗体时的“窗口”菜单时,将WindowList属性设置为True(即选中该复选框)即可。在运行时,VisualBasic自动管理与显示标题清单,并在当前正有焦点的标题旁边显示一个复选标志。另外,还在窗口清单的上方自动放置一个分隔符条。WindowList属性在运行时是只读的,只能在设计时设置。只能将菜单栏中的某一个菜单的WindowList属性设置为True,打开窗口的列表只出现在WindowList属性设置为True的菜单对象中,如果单击窗口列表中的某一个窗体名称,就可以激活那个窗体。12.3.4MDI窗体的菜单和工具栏设计MDI应用程序的菜单设计与一般应用程序的菜单设计方法一致,可利用“菜单编辑器”来完成,但MDI应用程序的菜单还有其特殊性。在MDI应用程序中,每一个子窗体的菜单都显示在MDI窗体上,而不是在子窗体本身。当子窗体有焦点时,该子窗体的菜单(如果有的话)就代替菜单栏上的MDI窗体的菜单。如果没有可见的子窗体,或者带有焦点的子窗体没有菜单,则显示MDI窗体的菜单。MDI应用程序使用几套菜单的情况很普遍。当打开一个文档时,应用程序显示与该类文档相关的菜单。通常,没有可见子窗体时会显示一个不同的菜单。例如,当没有文件打开时,MicrosoftExcel只显示“文件”与“帮助”菜单。当用户打开一个文件时,其他菜单就会显示出来,如“文件”、“编辑”、“视图”、“插入”、“格式”、“工具”和“窗口”等。管理MDI应用程序中菜单的一个方法是把希望在任何时候都显示的菜单控件放在MDI窗体上,当运行该应用程序时,如果没有可见的子窗体,会自动显示MDI窗体菜单。把应用于子窗体的菜单控件放置到子窗体中,在运行时,只要有一个子窗体可见,这些菜单标题就会显示在MDI窗体的菜单栏中。虽然子窗体的菜单可替代主窗体的菜单,但在编写菜单命令的响应事件的处理时却不相同。在VisualBasic中,只能在本窗体内响应菜单命令,因此主菜单的命令处理只能在主窗体模块中进行,而子窗体的命令处理只能在子窗体模块中进行。即使子窗体的菜单显示在主窗体的菜单位置,但它还是子窗体的菜单。有些应用程序支持多种类型的文档。例如,在MicrosoftAccess中,可以打开表格、查询、窗体和其他文档类型。要在VisualBasic中创建这样的应用程序,应使用两个子窗体。设计一个带有执行工作单任务菜单的子窗体和另一个带有完成图表任务菜单的子窗体。在运行时,当工作单窗体的实例有焦点时,则显示工作单菜单,而当选取图表时,则显示图表窗体的菜单。如果所有的工作单和图表都关闭,则显示MDI窗体的菜单。大多数MDI应用程序的菜单栏中都有“窗口”这一特殊菜单项,这是一个显示所有打开的子窗体标题的特殊菜单,如下图所示。另外,有些应用程序将操纵子窗体的命令,比如“层叠”、“平铺”与“排列图标”,也放在这个菜单中。工具栏(也称为发条或者控制栏)已经成为许多基于Windows的应用程序的标准功能,它提供了应用程序中最常用的功能。利用工具栏可以对应用程序中最常用的命令快速访问,还可以进一步增强应用程序的界面。VisualBasic中的“窗口”菜单创建工具栏的方法有两种:手工创建或使用ToolBar等控件创建。1.手工创建工具栏手工创建工具栏是利用图片框和命令按钮或图像框控件制作,比较烦琐。具体步骤如下:(1)在MDI窗体上放置一个图片框(PictureBox)控件,并设置其Align属性,通常Align属性可以设置为1或2。当Align属性值为1时,图片框的宽度会沿MDI窗体顶端自动伸展,直到填满MDI窗体工作空间;当Align属性值为2时,图片框的宽度会沿MDI窗体底端自动伸展,直到填满MDI窗体工作空间。工作空间就是窗体边框以内的区域,不包括标题条、菜单栏或所有的工具栏、状态栏或者可能在窗体上的滚动条。前面我们说过,只能把那些直接支持Align属性的控件放置在MDI窗体上,而图片框是支持这一属性的唯一的标准控件。(2)在图片框中,可以放置任何想在工具栏上显示的控件。典型地,用命令按钮或Image控件来创建工具栏按钮。要在图片框中添加控件,单击工具栏中的控件按钮,然后在图片框中画出它。(3)设置设计时属性。使用工具栏的一个好处是可以显示一个形象的命令图示,Image控件是作为工具栏按钮的一个很好的选择,因为可以用它来显示一个位图。在设计时设置其Picture属性来显示一个位图,再通过设置工具栏按钮的ToolTipText属性,实现自动提示功能。设置工具栏按钮的ToolTipText属性后,运行时当用户把鼠标指针停留在该按钮上时,就可以自动显示ToolTipText属性的内容。(4)调整各工具栏按钮的位置和大小(也可以在Form_Load事件过程中编程实现)。(5)编写各工具栏按钮的代码。因为工具栏频繁地用于提供访问某些应用程序命令的快捷方法,因而在大部分时间内都是在按钮的Click事件中调用其他过程。例如,在VisualBasic的工具栏上的“保存”按钮,它的功能和“文件”菜单中“保存工程”菜单项的功能完全一样。与其把这些功能代码重复两次,还不如把代码放到窗体的一个公用过程中,然后在上面的任何一个事件过程调用这个过程。下图是一个含有Image控件的工具栏。手工创建的工具栏2.使用ToolBar和ImageList控件创建工具栏使用ToolBar控件创建工具栏非常容易且很方便,它在VisualBasic的专业版与企业版中是可用的。使用这种方法创建工具栏比手工创建要方便得多,而且外形更美观,更接近于Windows的风格。ToolBar控件包含用来创建工具栏的按钮对象的集合,也就是显示在工具栏上的一组按钮。每个按钮对象都可有图像、标题和提示,其中,图像是由相关的ImageList控件所提供。使用ToolBar和ImageList控件来创建工具栏的步骤如下:(1)鼠标右键单击工具箱,选“部件”命令,打开“部件”对话框(也可以在“工程”菜单中选择“部件”菜单项打开)。单击“部件”对话框的“控件”选项卡,在控件的列表里选中“MicrosoftWindowsControls6.0”复选框,将ToolBar和ImageList等控件添加到工具箱,新添加的控件如右图所示。工具箱(2)分别双击ToolBar和ImageList控件,把它们添加到窗体上。(3)设置ImageList控件的属性。ImageList控件不单独使用,专门为其他控件提供图像库,是一个图像容器控件。工具栏按钮的图像就是通过ToolBar控件从ImageList控件的图像库中获得的。用鼠标右键单击ImageList控件,选择“属性”命令,可以打开“属性页”对话框,在“属性页”对话框里设置ImageList控件的属性。该对话框包括三个选项卡:通用、图像和颜色。其中“通用”选项卡用于设置图片大小,“图像”选项卡用于插入图片,“图像”选项卡如下图所示。ImageList控件的“图像”选项卡在“图像”选项卡中,单击“插入图片”按钮,选择希望作为工具栏按钮图标的图片,图像文件的扩展名为.ico、.bmp、.gif、.jpg等。插入图片后,“索引”框将从1开始,按插入顺序自动编号,此编号与ToolBar控件属性页中“按钮”选择项的“图像”框中的数字相对应,“图像”框中的数字为1,则工具栏上该按钮的图标就是ImageList控件中索引值为1的图片。“关键字”表示每个图像的标识名,可以在ToolBar控件中引用。“删除图片”按钮,用于删除选中的图片。“图像数”表示已经插入的图像数目。(4)右击ToolBar控件,选择“属性”,打开ToolBar控件的属性页对话框。它也有三个选项卡:通用、按钮和图片。单击“通用”选项卡,在“图像列表”下拉框中选择所需要的ImageList控件,建立ImageList控件与ToolBar控件间的关联,如右图所示。ToolBar控件的“通用”选项卡在“样式”下拉框中可以选择工具栏的不同样式:0-tbrStandard型或1-tbrFlat型。0-tbrStandard型工具栏按钮呈突出状,单击时有按下并弹起的效果;1-tbrFlat型则呈平面,当鼠标移至按钮上方时,按钮突出显示,与Windows95下的工具栏按钮风格类似。“可换行的”复选框被选中表示当工具栏的长度不能容纳所有工具按钮时,在下一行显示。如果不选中该复选框,则当工具栏的长度不能容纳所有工具按钮时,剩余的就不再显示。切换到“按钮”选项卡,如下图所示。ToolBar控件的“按钮”选项卡最开始
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2025年农村一二三产业融合发展的农业产业结构优化升级报告
- 社交电商裂变营销2025年:品牌故事与用户增长策略解析报告
- 共享农业体验园生态农业观光园可持续发展战略报告
- 2024古籍赠送法律协议
- 基于2025年远程医疗技术的分级诊疗模式在传染病防控中的应用报告
- 2023年驾照考试科目一知识点归纳总结
- 2023年继电保护工第二版初级工理论题库
- 2023年造价员考试真题试题和答案
- 2023年经济师中级经济基础知识试题及答案版
- 2025年新能源汽车买卖合同书含充电设施安装
- 医院护理人员招聘考试试题与答案
- 国企干部备案管理办法
- 企业能力分级管理办法
- 部队生殖健康课件
- 2025年高考真题-化学(湖南卷) 含答案
- 客户拜访技巧讲课件
- 空分项目可行性研究报告
- 2025至2030年中国黄芪行业市场深度分析及投资前景规划报告
- 工业互联网与石化化工行业融合应用参考指南(2025年)
- JG/T 380-2012建筑结构用冷弯薄壁型钢
- JG/T 3033-1996试验用砂浆搅拌机
评论
0/150
提交评论