当 MDI 应用程序在一次会话中要打开、保存和关闭几个子窗体时,应当能够引用活动窗体和保持关于子窗体的状态信息。这个主题描述了一些用来指定活动子窗体或者控件、加载和卸载 MDI 窗体及其子窗体、以及保持子窗体的状态信息的编码技巧。
有时要提供一条命令,它用于对当前活动子窗体上具有焦点的控件进行操作。例如,假设想从子窗体的文本框中把所选文本复制到剪贴板上。在 Mdinote.vbp 示例应用程序中,“编辑”菜单上的“复制”项的 Click 事件将会调用 EditCopyProc,它是把选定的文本复制到剪贴板上的过程。
由于应用程序可以有同一子窗体的许多实例,EditCopyProc 需要知道使用的是哪一个窗体。为了指定这一点,使用 MDI 窗体的 ActiveForm 属性,该属性可以返回具有焦点的或者最后被激活的子窗体。
注意 当访问 ActiveForm 属性时,至少应有一个 MDI 子窗体被加载或可见,否则会返回一个错误。
当一个窗体中有几个控件时,也需要指定哪个控件是活动的。象 ActiveForm 属性一样,ActiveControl 属性能返回活动子窗体上具有焦点的控件。下边是副本例程的示例,从子窗体菜单、MDI 窗体菜单或者是工具栏按钮上可对它进行调用。
Private Sub EditCopyProc () '
将选定文本复制到剪贴板上。ClipBoard.SetText _
frmMDI.ActiveForm.ActiveControl.SelText
End Sub
假如,正在编写被多个窗体实例调用的代码,不用窗体标识符访问窗体的控件或属性是一个好办法。例如,用 Text1.Height
引用 Form1上文本框的高度,而不是使用 Form1.Text1.Height
。这样,该代码总是影响当前窗体。
在代码中指定当前窗体的另一种方法是用 Me 关键字。用 Me 关键字来引用当前其代码正在运行的窗体。当需要把当前窗体实例的引用参数传递给过程时,这个关键字很有用。
详细信息 有关通过 Dim 语句用 New 关键字来创建多个窗体实例的信息,请参阅“编程基础”中的“变量、常数和数据类型概述”,和《语言参考》的“Dim 语句”。
加载子窗体时,其父窗体(MDI 窗体)会自动加载并显示。而加载 MDI 窗体时,其子窗体并不会自动加载。
在 MDI NotePad 示例中,子窗体是缺省的启动窗体,因而在程序运行时,子窗体和 MDI 窗体两者都会加载。如果在 MDI NotePad 应用程序中改变启动窗体为 frmMDI(在“工程属性”的“一般”选项卡上),然后运行应用程序,则只有 MDI 窗体被加载。当从“文件”菜单中选取“新建”命令时,才会加载第一个子窗体。
AutoShowChildren 属性可用来加载隐藏状态的 MDI 子窗口,使它们处于隐藏状态直至用 Show 方法把它们显示出来。这就允许在子窗体变成可见之前更新标题、位置和菜单等各种细节。
不能把 MDI 子窗体或者 MDI 窗体显示为模式窗体(用带 vbModal 参数的 Show 方法)。如果想在 MDI 应用程序中使用模式对话框,可使用 MDIChild 属性设置为 False 的窗体。
如果 MDI 子窗体具有大小可变的边框〔即 BorderStyle = 2),在其装载时,Microsoft Windows 将决定其初始的高度、宽度和位置。边框大小可变的子窗体,其初始大小与位置取决于 MDI 窗体的大小,而不是设计时子窗体的大小。当 MDI 子窗体的边框大小不可变(即 BorderStyle = 0,1 或 3)时,则它将用设计时的 Height 和 Width 属性被载入。
如果设置 AutoShowChildren 为 False,则在 MDI 子窗体载入以后,把它设为可见状态之前,可以改变其位置。
详细信息 请参阅《语言参考》的 AutoShowChildren 属性和 Show 方法”。
在用户决定退出 MDI 应用程序时,必须有保存信息的机会。为了使其能够进行,应用程序必须随时都能确定自上次保存以来子窗体中的数据是否有改变。
通过在每个子窗体中声明一个公用变量来实现此功能。例如,可以在子窗体的声明部分声明一个变量:
Public boolDirty As Boolean
Text1 中的文本每一次改变时,子窗体文本框的 Change 事件就会将 boolDirty
设置为 True。可添加此代码以指示自上次保存以来 Text1 的内容已经改变。
Private Sub Text1_Change ()
boolDirty = True
End Sub
反之,用户每次保存子窗体的内容时,文本框的 Change 事件就将 boolDirty
设置为 False,以指示 Text1 的内容不再需要保存。在下列代码中,假设有一个叫做“保存”(mnuFileSave) 的菜单命令和一个用来保存文本框内容的名为 FileSave 的过程:
Sub mnuFileSave_Click () '
保存Text1
的内容。FileSave
'
设置状态变量。boolDirty = False
End Sub
当用户决定退出应用程序时,boolDirty
标志就很有用了。当用户从 MDI 窗体的“控制”菜单中选取“关闭”,或者从提供的菜单项,例如“文件”菜单上的“退出”命令,上述情况就会出现。如果用户使用 MDI 窗体的“控制”菜单来关闭应用程序,Visual Basic 将试图卸载 MDI 窗体。
当 MDI 窗体被卸载时,QueryUnload 事件首先为 MDI 窗体调用,然后再为每一个打开的子窗体调用。如果在这些 QueryUnload 事件过程中没有代码,则取消 Unload 事件,然后,每一个子窗体被卸载,最后,MDI 窗体被卸载。
由于 QueryUnload 事件在窗体卸载之前被调用,因此在窗体卸载前可以给用户一个机会来保存窗体。下述代码使用 boolDirty
标志来决定是否要提醒用户在子窗体卸载之前进行保存。请注意,可以在工程的任何地方访问公共窗体级变量值。这个代码假定有一个名叫 FileSave 的过程,它将 Text1 的内容保存到一个文件中。
Private Sub mnuFExit_Click() '
当用户在MDI
应用程序中选取“文件提出”命令时,卸载'MDI
窗体,为每个打开的子窗体调用QueryUnload
事件。Unload frmMDI
End
End Sub
Private Sub Form_QueryUnload(Cancel As Integer, _
UnloadMode As Integer)
If boolDirty Then
'
调用例程来询问用户且必要时保存文件。FileSave
End If
End Sub
详细信息 请参阅《语言参考》的“QueryUnload 事件”。