来自MSDN-2001-OCT: Visual Tools and Languages/Visual Studio 6.0 Documentation/Visual Basic Documentation/Using Visual Basic/Programmer’s Guide/Part 2: What Can You Do With Visual Basic/Programming with Objects
一、与对象有关的术语
(1)在 Visual Basic 中,对象是由类创建的,因此对象被说成是类的一个实例。类定义对象的界面,不管对象是否是公共的和在什么环境下建立的都是这样。类的描述保存在类型库中,而且通过对象浏览器可以查看。
(2)为了使用对象,必须在对象变量中保存其引用。绑定的类型决定使用对象变量访问对象方法的速度。对象变量可以是后期绑定(最慢),或者是事前绑定。事前绑定可以是 DispID 绑定或者 vtable 绑定(最快)。
(3)属性和方法的集合称作界面。Visual Basic 对象的缺省界面是支持所有三种绑定窗体的双重接口。如果对象变量已经声明了类型(即 Dim ... As classname),它将使用最快的绑定窗体。
(4)除缺省界面外,Visual Basic 对象能够为实现多态提供额外的界面。多态可以操作不同种类的对象,而不用担心每个对象是什么类型。多界面是部件对象模型 (COM) 的一个特征,它允许展开过时的程序,添加新功能而不需拆散老代码。
(5)Visual Basic 中的类也可以是数据识别的。通过直接绑定到一个外部数据源,类可以作为数据使用者,或者通过从一个外部源提供数据,它还可以作为其他对象的数据源。
二、和对象相关的语法
2.1 找出对象所属的类
(1)通用对象变量(即,用 As Object 声明的变量)可以保持许多不同类的变量。同样,用 Visual Basic 内建的 Form 和 Control 类型声明的变量可以包含不同类的窗体和控件。
(2)TypeOf 关键字只能用在 If ... Then ... Else 语句中。必须在代码中直接包含类名。例如, If TypeOf MyControl Is CheckBox Then
。
(3)TypeName 函数更灵活些。代码中到处可以使用,并且因为它用字符串返回类名,所以可将它与一字符串变量的值相比较。
(1)CallByName 函数允许您使用一个字符串在运行时指定一个属性或方法。
(2)尽管 CallByName 函数在某些情况下可能很有用,但是,还是需要在衡量其实用性时考虑对性能可能的影响 — 同后期绑定相比,使用 CallByName 来调用一个过程只会稍稍慢一点儿。如果您正调用的函数将要被重复调用很多次,例如在一个循环内部,则 CallByName 将会对性能产生严重的影响。
2.3 对一个对象执行多个动作
(1)通过使用 With...End With 语句,可使该代码更容易编写、阅读和更有效地运行。
(2)还可以通过将 With...End With 语句置入另一个 With...End With 语句内实现嵌套的 With 语句。
2.4 使用缺省属性
(1)很多对象具有缺省属性。使用缺省属性能够简化代码,因为设置属性值时,不必具体指明该属性。
(2)当对象引用保存在 Variants 类型的变量中,而不是在对象变量中时,访问缺省属性是不同的。这是因为 Variants 能包含多种不同类型的数据。例如,能够使用 Variants 中的引用读取 Text1 的缺省属性,但是试图将字符串“goodbye”赋给缺省属性的做法是行不通的。相反,它将用该字符串代替该对象引用,并改变 Variants 的类型。
Dim vnt As Variant '设置缺省属性 (Text) 为“hello”。
Text1 = "hello" '把对 Text1 的引用放入 Variants 。
Set vnt = Text1 '显示 Text1 的缺省属性,并且给出 ' Variants 包含对象引用。
MsgBox vnt , , "IsObject? " & IsObject( vnt) '试图设置 Text1 的缺省属性。
vnt = "goodbye"
MsgBox vnt , "IsObject? " & IsObject( vnt)
End Sub
三、对象数组和集合
3.1 创建对象数组
(1)窗体变量数组:如果数组声明使用了 New 关键字,则当使用该数组的元素时,Visual Basic 将自动为数组中每个元素创建一个新窗体实例。
(2)控件变量数组:与窗体数组不同,控件数组不能使用 New 关键字声明。
3.2 创建对象集合
集合提供了跟踪对象很有用的方法。与数组不同,集合本身也是对象。当增加和删除集合对象的成员时,它的大小不会改变。
Collection 对象是由 VBA 提供的。
3.3 Visual Basic 集合对象
(1)象其它任何对象一样,当包含其引用的最后一个变量被设置成 Nothing 或不可见时,Collection 对象将被撤消。它包含的所有对象引用将被释放。如果使用集合来跟踪窗体,当窗体被卸载之后,应使用集合的 Remove 方法从集合中删除该对象引用。注意 只要对该窗体的引用仍然存在,就不能收回窗体使用的内存,并且 Collection 对象保存的引用象对象变量中的引用一样完好。
(2)集合对象的构成:Collection 对象将每一项存储于 Variants 对象中。于是,能够添加到 Collection 对象里的内容列表就和能够存储到 Variants 中的内容列表是相同的。这包括标准数据类型、对象和数组- 但不包括用户定义类型。
(3)应该知道进行权衡:使用 Collection 对象能够编写清楚且容易维护的代码- 所花费的仅是将一些项存储在 Variant 中。不管 Variants 中存储的是什么,它都占 16 字节,因此使用 Collection 对象不如使用数组的效率高。然而,集合对象能按键进行快速的查找,而数组却不能。
例如,如果把字符串或数组赋给 Variants,Variants 将包含一个指向字符串和数组数据备份的指针。在 32 位系统中,指针只使用了 Variants 的 4 个字节,而且 Variants 中实际上不存在数据。
若要存储一个对象,Variants 将包含该对象引用,就象对象变量所做的一样。对字符串和数组来说,也只使用 Variants 的 4 个字节。
数字数据类型存储在 Variants 中。不管什么样的数据类型,Variants 仍然占 16 个字节。
(4)集合对象的属性和方法: Add、Count、Item、Remove。集合中的增加、删除和检索的基本功能需要关键字和索引。关键字是一个 String 的值。索引是长整型,介于 1 和集合中项的数目之间。使用 before 和 after 命名的参数,可以控制项索引的初始值,但是随着其它项的增加和删除,其值会发生改变。
提示 为改善性能,应使用 For Each 对 Collection 对象中的项进行迭代。使用 For Each 迭代要比使用索引快很多倍。这并不是对所有集合都正确- 它取决于集合内部存储数据的方法。
重点 当添加和删除集合对象元素时,集合对象会自动地维护其数字索引编号。因此给定元素的数字索引随之改变。不能在程序中存储数字索引值,并用它检索同一个元素。为达到该目的,应使用键。
(5)给集合添加项 colWorkOrders.Add woNew,woNew.ID,after:=2
(6)从集合中删除项 colWorkOrders.Remove "W017493"
(7)从集合中检索项:Item 方法用于从集合中检索特定项。
如果使用整数作为关键字,在将它们传递到 Item 或 Remove 方法之前,必须使用 CStr 函数将其转换成字符串。通常集合对象都假定整数是索引。提示 Collection 对象不能决定所传递的值是索引还是键。如果想把值解释为键,并且包含该值的变量是除 String 以外的任何值,可以使用 CStr 函数进行转换。如果想把值解释为索引,并且包含该值的变量不是整型数据类型中的一种,使用 CLng 进行转换。
(8)对于集合对象来说,Item 方法是缺省方法,因此当访问集合中的项时,可忽略它。
(9)提示 如果想调用集合中对象的多个属性或方法,首先将该对象引用复制到一个强类型的对象变量中。把引用放到一个强类型的对象变量中,然后使用,比使用集合里对象的引用要快(例如,Dim woCurrent As WorkOrder),因为 Collection 对象是把项存储在 Variants 中。 Variants 中的对象引用总是最后绑定。
3.4 Visual Basic 中的集合
(1)
Forms 集合是集合,变量 col
也声明为 Collection,为什么不能将指向 Forms 的引用赋给变量 col
?
其原因是 Collection 类和 Forms 集合都不是多态的,即它们不能相互交换,因为是从各自的代码库开发的。它们没有相同的方法,没有用相同的方法存储对象引用,或者没有使用相同种类的索引值。
(2)基于 0 的集合示例是 Forms 和 Controls 集合。基于 1 的集合的示例是集合对象。Visual Basic 中旧的集合大多是基于 0 的。而新添加的集合大多基于 1。
(3)Forms 集合只能使用数字索引来访问。这是因为没有唯一的字符串值与窗体关联。例如,多个窗体可以有相同的标题,或者加载的多个窗体有相同的 Name 属性。
(4)Forms 集合获取窗体的唯一方法是加载窗体。如果使用 New 操作符建立窗体,或者通过引用一个声明为 As New 的变量建立窗体,那么该窗体是不能被添加到窗体集合里的,除非使用 Load 语句进行加载。
Forms 和控件集合没有 Remove 方法。可以使用 Load 和 Unload 语句间接的向这些集合中添加和从这些集合中删除窗体和控件。
(5)Forms 集合的最准确的说明是:它包含的是程序中当前加载的所有窗体。但是,如果工程中使用 Microsoft Forms(为了与 Microsoft Office 兼容被包括的),就会发现这些窗体都在一个名为 UserForms 的单独集合里。因此该 Forms 集合所包含的就是程序中当前加载的所有 Visual Basic 窗体。
3.5 集合中的枚举算子
(1)使 For Each ... Next 能工作的是一个称为 enumerato 的很小的对象。枚举算子记录集合中项的位置,并在需要时返回下一项。
枚举数组时,在运行中 Visual Basic 创建一个数组枚举算子对象。集合具有自己的枚举算子对象,它也是需要时创建的。
(2)Visual Basic 中集合的枚举算子不会跳过项。例如,假设枚举一个包含 "A"、"B" 和 "C" 的集合,并且进行枚举时删除了 "B",则在操作时 Visual Basic 不会跳到 "C" 上。
(3)枚举算子可能不捕捉添加的项:当枚举集合时,如果给集合添加了项,一些枚举算子将能包含添加的项,而一些枚举算子则不会。例如,枚举 Forms 集合时就不枚举刚加载的任何窗体。
如果将它们添加到集合末尾,则在枚举时集合,对象就能枚举添加的项。因此下列循环永远不会终止(即直到按 CTRL+BREAK 组合键):
Dim vnt As Variant
col . Add "Endless"
col . Add "Endless"
For Each vnt In col
MsgBox vnt
col . Add "Endless"
Next
另一方面,添加到集合开始的项不会包含在枚举里。
Dim @H_684_404@vnt As Variant
@H_684_404@col @H_684_404@. @H_684_404@Add "Will be enumerated"
For Each @H_684_404@vnt In @H_684_404@col
@H_684_404@MsgBox @H_684_404@vnt
'在开始处添加项。
@H_684_404@col @H_684_404@. @H_684_404@Add "Won't be enumerated" @H_684_404@, @H_684_404@Before @H_684_404@: = 1
Next
四、查找对象信息
(1)Visual Basic 为创建的类建立类型库信息,为其包含的对象提供类型库,并且允许访问其它应用程序提供的类型库。
(2)可以使用对象浏览器显示工程和库中的有效的类,包括自己定义的类。按 F2 键。可以使用 CTRL+TAB 在对象浏览器和代码窗口之间切换。
(3)有用的功能:“向后”按钮、属性、组成员、复制、查看定义、引用、搜索
(4)可以使用对象浏览器给自己的过程、模块、类、属性和方法添加描述及“HelpContextIDs”。使用自己的类时就能找到这些有用的描述。
可以创建一个帮助文件以备自用,并将主题连接到自己的类及其成员中。如果希望为自己的工程指定一个帮助文件,可在“工程”菜单中打开“工程属性”对话框,使用其中的“通用”选项卡。