如果说创建类的历史与使用 Visual Basic 编程的历史一样长,也许会感到惊奇。但这是真的:Form1,每次开始一个工程都要碰到的这个老相识,实际上就是一个类。
为了说明这一点,打开一个新的“标准 EXE”工程。添加一个按钮到 From1,并在单击事件中放置如下的代码:
Private Sub Command1.Click()
Dim f As New Form1
f.Show
End Sub
按 F5 键运行这个工程,并单击该按钮。啊!出现了 Form1 的另一个实体!单击其中的按钮,又有另一个窗体!所创建的每一个实体看上去都是一样的,并且有同样的表现,因为它们都是 Form1 类的实体。
如果已阅读了“编程基础”中的“使用对象”,就会知道一个被声明成“As New”的对象变量,在代码中第一次被引用之前所包含的是“Nothing”。 当变量第一次被使用时,Visual Basic 注意到其中包含特定数值“Nothing”,就要创建一个该类的实例(这也是一件好事,否则 f.Show
将引起错误)。
也许会有点奇怪,在代码中怎样就能引用 Form1,它好象是一个对象变量。这并不离奇,Visual Basic 为每一个窗体类创建了一个隐藏的全局对象变量。看起来就象 Visual Basic 向工程添加了下列声明:
Public Form1 As New Form1
当选择 Form1 作为启动对象时,或者在代码中键入 Form1.Show
,就引用了这个隐藏的全局对象变量。因为它被声明为“As New”,因此当代码中第一次使用这个预先声明的变量时,将创建 Form1
类的一个实例。
隐藏该声明的理由是每次更改窗体的 Name 属性时,Visual Basic 都要改变它。通过这种方法,隐藏的变量总是与窗体类有同样的名字。
在上述练习中创建的 Form1 的哪一个实例与隐藏的全局变量相关联?如果认为是第一个,则是对的。Form1
是工程的缺省启动对象,对 Visual Basic 而言它和在代码中使用预先声明的全局变量一样。
提示 在一个窗体卸载后,总是必须将对该窗体的任何引用设置为“Nothing”,以便释放其所使用的内存和资源。最经常被忽略的引用是这个隐藏的全局窗体变量。
在“编程基础”中,已经了解到要引用一个对象,需要一个对象变量,一个对象只有当至少存在一个对象变量包含对它的引用时才能存在。那么,是什么使得其它的实例能够存在呢?
Form1 的第二个实例,及以后的其它实例,都有一个对象变量,只要是调用其 Show 方法时就一直存在。然后该变量退出可见范围,并且被设置为“Nothing”。但是 Visual Basic 保持一个名为 Forms 的特殊的集合,这可以在第六章“创建用户界面”中的“再论窗体”中看到。该 Forms 集合包含了对工程中每一个已被装载的窗体的引用,所以总是可以找到和控制它们。
注意 正如所了解的那样,并不是对所有的类来说都是这样。例如,自己设计的类将不会有隐藏的全局变量或全局集合来跟踪它们- 这些是窗体类的特定功能。但是,可以声明自己的全局变量,也可以创建自己的集合- 就象在“创建自己的集合类”中所描述的那样。
第一次为窗体类添加属性时,可以直接把一个命令按钮(或其它的控件)拖放到 Form1 中。这样就添加了一个只读的 Command1 属性给窗体类。此后,当需要调用命令按钮的方法或属性时就是引用 Form1 的这一属性:
Command1.Caption = "Click Me"
在改变窗体中任何控件的 Name 属性时,Visual Basic 悄悄地改变了只读属性的名称以使二者匹配。
如果以前练习示例的工程还打开着,可以按 F2 键打开对象浏览器能见到 Command1 属性。在“工程/库”框中,选中 Project1,可以在类窗格中见到 Form1。向下滚动成员窗格直到发现 Command1,选中它。
Command1 边上有一个属性符号。从说明窗格中可以知道它是 WithEvents 属性。正如在“向类中添加事件”中所述,这表示属性(或对象变量)具有与之相关的事件过程。作为事件过程之一的 Command1_Click() 也许是自编写 Visual Basic 代码以来的第一个。
把控件放到窗体上不是向窗体类添加成员的唯一方法。还可以在建立新变量和过程时添加定制的属性、方法和事件。
为了说明这点,请把下列代码添加到 Form1 的声明部分:
'Form1
类的Comment
属性Public Comment As String
请把下列代码添加到 Form1 的 Click 事件:
Private Sub Form_Click()
MsgBox Comment, , "My comment is:"
End Sub
最后,如下所示向 Command1_Click() 事件过程添加一行代码:
Private Sub Command1.Click()
Dim f As New Form1
f.Comment = InputBox("What's my comment?")
f.Show
End Sub
按 F5 键运行该工程。单击 Command1,出现输入框时,输入一些有趣的注释然后单击 OK。当 Form1 的新实例出现时,单击它以显示其 Comment 属性。
单击第一个 Form1 实例,可以看到其 Comment 属性是空白的。这是由于 Visual Basic 把该实例当作启动对象,不可能有机会设置其 Comment 属性。
如果仔细观察可以发现,添加到 Form1 类中代码并不设置该对象本身的 Comment 属性- 它只设置已被创建的 Form1 新实例的 Comment 属性。
设置其它窗体的属性和调用其它窗体的方法是一项非常有用的技术。例如,一个 MDIForm 在打开一个新的子窗口时可以通过设置其属性、调用其方法来对它初始化。
还可将此技术用于在窗体之间传递信息。
提示 可以为窗体创建定制的事件。本章后面的“向窗体中添加事件”中将逐步介绍。
通过向其代码模块添加代码的方式可以给窗体类添加属性、方法和事件。还可以用同样方法向类模块添加属性、方法和事件。对于 Visual Basic 专业版或企业版,该方法还可添加到 UserControl 和 UserDocument 代码模块。
当读到“向类中添加属性和方法”及“向类中添加事件”这些节时,应记住文中所描述的对窗体类所做的每一件事同样适用于类模块。
详细资料 什么是类模块?在“类模块循序渐进”中介绍了如何定义类并列举了通过类创建的对象的存活期。