vb对象编程相关_第1页
vb对象编程相关_第2页
vb对象编程相关_第3页
vb对象编程相关_第4页
vb对象编程相关_第5页
已阅读5页,还剩96页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

与对象有关的术语下面是一些快速浏览的术语,在讨论 Visual Basic 的对象及其功能时会遇到。如果是从其它程序设计语言或者从使用 ActiveX(从前称为 OLE)术语转到 Visual Basic,那么这些主题对实现转换是有帮助的。若是刚开始接触对象,可能会感到有点混乱。这是正常的,通过对将要遇到的这些术语的快速浏览,就会对它们如何互相配合有个大概了解。随着在本章其余部分接触更多的有关对象的信息,再回头浏览这些主题,就能将各部分零散的信息形成一个总体。由此开始对象是被封装的 也就是说,它同时包含其代码和数据,这比传统的编写代码方法更容易维护。Visual Basic 对象具有属性、方法和事件。属性是描述对象的数据。方法告诉对象应做的事情。事件是对象所产生的事情,事件发生时可以编写代码进行处理。在 Visual Basic 中,对象是由类创建的,因此对象被说成是类的一个实例。类定义对象的界面,不管对象是否是公共的和在什么环境下建立的都是这样。类的描述保存在类型库中,而且通过对象浏览器可以查看。为了使用对象,必须在对象变量中保存其引用。绑定的类型决定使用对象变量访问对象方法的速度。对象变量可以是后期绑定(最慢),或者是事前绑定。事前绑定可以是 DispID 绑定或者 vtable 绑定(最快)。属性和方法的集合称作界面。Visual Basic 对象的缺省界面是支持所有三种绑定窗体的双重接口。如果对象变量已经声明了类型(即 Dim . As classname),它将使用最快的绑定窗体。除缺省界面外,Visual Basic 对象能够为实现多态提供额外的界面。多态可以操作不同种类的对象,而不用担心每个对象是什么类型。多界面是部件对象模型 (COM) 的一个特征,它允许展开过时的程序,添加新功能而不需拆散老代码。Visual Basic 中的类也可以是数据识别的。通过直接绑定到一个外部数据源,类可以作为数据使用者,或者通过从一个外部源提供数据,它还可以作为其他对象的数据源。步入和谐的大厅如果对所有这些似乎已经很熟悉了,那么可浏览本章的其余部分。如果不熟,也不必担心,所有这些术语的说明都有策略地分布在本文中(并不是很凌乱地出现)。找出对象所属的类通用对象变量(即,用 As Object 声明的变量)可以保持许多不同类的变量。同样,用 Visual Basic 内建的 Form 和 Control 类型声明的变量可以包含不同类的窗体和控件。在使用这些变量时,可能要根据对象的不同类而采取不同的操作例如,某些对象可能不支持个别的属性和方法。Visual Basic 提供了两种方法:TypeOf 关键字和 TypeName 函数。TypeOf 关键字只能用在 If . Then . Else 语句中。必须在代码中直接包含类名。例如, If TypeOf MyControl Is CheckBox Then。TypeName 函数更灵活些。代码中到处可以使用,并且因为它用字符串返回类名,所以可将它与一字符串变量的值相比较。使用字符串名调用属性和方法大多数情况下,您可以在设计时发现对象的属性和方法,并且编写代码以处理它们。但是,在少数情况下,您可能不知道某个对象的一些高级属性和方法,或者,您可能只是想要这种灵活性,即允许最终用户在运行时指定属性或执行方法。例如,请考虑下面的情况,某个客户端应用程序,它通过传递一个运算符到服务器程序来计算由用户输入的表达式。现在,假定您要经常性地向需要新运算符的服务器添加新函数。那么,不幸的是,在客户端应用程序能够使用新的运算符之前,您需要重新编辑和重新发布它。为了避免这种情况,可以使用 CallByName 函数把新运算符当作字符串来传递,而不需要更改应用程序。CallByName 函数允许您使用一个字符串在运行时指定一个属性或方法。CallByName 函数的用法如下:Result = CallByName(Object, ProcedureName, CallType, Arguments()CallByName 的第一个参数包含要对其执行动作的对象名。第二个参数,ProcedureName,是一个字符串,包含将要调用的方法或属性过程名。CallType 参数包含一个常数,代表要调用的过程的类型:方法 (vbMethod)、property let (vbLet)、property get (vbGet),或 property set (vbSet)。最后一个参数是可选的,它包含一个变量数组,数组中包含该过程的参数。假定您有一个服务器应用程序,MathServer,并且它具有一个新的函数 SquareRoot。该应用程序中有两个 TextBox 控件:Text1 包含要计算的表达式;Text2 用于输入该函数的名称。要对 Text1 中的表达式调用 SquareRoot 函数,您可以在一个命令按钮的 Click 事件中使用下面的代码:Private Sub Command1_Click() Text1.Text = CallByName(MathServer, Text2.Text, vbMethod, Text1.Text)End Sub如果用户在 Text1 中输入 64 / 4,在 Text 2 中输入 SquareRoot,则上面的代码将调用 SquareRoot 函数(要求一个必需的参数,它是一个包含将要计算的表达式的字符串),并且在 Text1 中返回 4 (16 或64/4的平方根)。当然,如果用户在 Text2 中输入了一个无效的字符串,或者该字符串包含一个属性名而不是方法名,或者该方法要求附加的必需的参数,那么将会产生一个运行时错误。可以猜到,当您使用 CallByName 来预处理这些或其他的错误时,需要添加强健的错误处理程序代码。尽管 CallByName 函数在某些情况下可能很有用,但是,还是需要在衡量其实用性时考虑对性能可能的影响 同后期绑定相比,使用 CallByName 来调用一个过程只会稍稍慢一点儿。如果您正调用的函数将要被重复调用很多次,例如在一个循环内部,则 CallByName 将会对性能产生严重的影响。对一个对象执行多个动作经常需要在同一对象中执行多个不同的动作。例如,需要对同一对象设置几个属性。途径之一是使用多条语句。Private Sub Form_Load() Command1.Caption = OK Command1.Visible = True Command1.Top = 200 Command1.Left = 5000 Command1.Enabled = TrueEnd Sub应注意的是所有这些语句使用同一个对象变量 Command1。通过使用 With.End With 语句,可使该代码更容易编写、阅读和更有效地运行。Private Sub Form_Load() With Command1 .Caption = OK .Visible = True .Top = 200 .Left = 5000 .Enabled = True End WithEnd Sub还可以通过将 With.End With 语句置入另一个 With.End With 语句内实现嵌套的 With 语句。使用缺省属性很多对象具有缺省属性。使用缺省属性能够简化代码,因为设置属性值时,不必详细指明该属性。Value 是对象缺省属性,这两个语句是等价的:object = 20和object.Value = 20为了说明它们是如何工作的,在窗体上绘制命令按钮和文本框。将下列语句添加到命令按钮的 Click 事件中:Text1 = hello运行该应用程序,并单击命令按钮。因为 Text 是文本框的缺省属性,所以文本框将显示文本“hello”。通过对象变量使用缺省属性当对象的引用被保存在对象变量中时,仍然可以使用缺省属性。下面的代码段说明了这一点。Private Sub Command1_Click() Dim obj As Object 把对 Text1 的引用放入对象变量。 Set obj = Text1 设置缺省属性 (Text) 的值。 obj = helloEnd Sub在上面的代码中,obj = hello 和 obj.Text = hello 是完全相同的。通过 Variants 使用缺省属性当对象引用保存在 Variants 类型的变量中,而不是在对象变量中时,访问缺省属性是不同的。这是因为 Variants 能包含多种不同类型的数据。例如,能够使用 Variants 中的引用读取 Text1 的缺省属性,但是试图将字符串“goodbye”赋给缺省属性的做法是行不通的。相反,它将用该字符串代替该对象引用,并改变 Variants 的类型。为了说明这一点,以前面示例为例,在命令按钮的 Click 事件中输入下面的代码:Private Sub Command1_Click() 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当运行该应用程序并单击命令按钮时,首先出现的信息框显示 Text1 缺省属性的当前值“hello”,它通过查看 Text1 可得到证实。信息框的标题证明 Variant 包含有一个对象引用 即对 Text1 的引用。当单击信息框中的“确定”按钮时,“goodbye”赋给该 Variants,并破坏了 Text1 的引用。接着显示另一信息框,并显示该 Variants 的内容 正如所看到的那样,它与 Text1.Text 的当前值不匹配。信息框的标题证明, Variants 不再包含对象引用 它现在包含字符串“goodbye”。详细信息 有关 Variants 和其它数据类型的详细信息,请参阅“编程基础”中的“变量、常数和数据类型概述”。使用对象和 Variants 的其它内容将在“Visual Basic 集合对象”中讨论。创建对象数组 正象声明和使用任何数据类型的数组那样,也能够声明和使用对象类型的数组。这些数组既可以是固定大小的,也可以是动态的。窗体变量数组与声明其它任何类型数组的方法相同,可以使用 Private、Dim、ReDim、Static 或 Public 声明窗体数组。如果数组声明使用了 New 关键字,则当使用该数组的元素时,Visual Basic 将自动为数组中每个元素创建一个新窗体实例。Private Sub Command1_Click () Dim intX As Integer Dim frmNew(1 To 5) As New Form1 For intX = 1 To 5 frmNew(intX).Show frmNew(intX).WindowState = vbMinimized 为了不让它们第一次以正常大小出现而 创建最小化窗体,可改变 上面两行的顺序。 NextEnd Sub按命令按钮执行上述代码,将建立五个最小化的 Form1 实例。注意如果查看任务栏,可看到六个 Form1。额外的 Form1 实例不是最小化的 它是刚开始使用的那个。控件变量数组与声明任何其它类型数组的方法相同,可以使用 Private、Dim、ReDim、Static 或 Public 声明控件数组。然而与窗体数组不同,控件数组不能使用 New 关键字声明。例如,可以声明数组为特定的控件类型:ReDim ActiveImages(10) As Image当声明数组为特定控件类型时,只能将该类型的控件赋给数组。例如,在前面的声明中,只能将图像控件赋给该数组 但是这些图像控件可以来自不同的窗体。将其与内置 Controls 集合进行比较,内置 Controls 集合能包含很多不同类型的控件 所有这些控件必须在同一窗体中。另外,可以声明类属控件变量数组。例如,若要跟踪拖放到某一特定控件中的每个控件,而且不允许任何控件被拖放多次。通过对控件变量的动态数组的管理可以做到这点,只要让该动态数组包含每个被拖放控件的引用即可。Private Sub List1_DragDrop(Source As VB.Control, _ X As Single, Y As Single) Dim intX As Integer Static intSize As Integer Static ctlDropped() As Control For intX = 1 To intSize 如果数组中有被拖放的控件,则它 已经被拖放到这儿一次。 If ctlDropped(intX) Is Source Then Beep Exit Sub End If Next 扩展数组。 intSize = intSize + 1 ReDim Preserve ctlDropped(intSize) 保存被拖放控件的引用。 Set ctlDropped(intSize) = Source 给列表框添加控件名。 List1.AddItem Source.NameEnd Sub该示例使用 Is 操作符将控件数组中的变量和控件参数进行比较。Is 操作符可用来测试 Visual Basic 对象引用的一致性:如果两个不同引用的比较结果为同一对象,Is 操作符返回 True。该示例还使用 Set 语句将 Source 参数中的对象引用赋予数组中的元素。详细信息请参阅语言参考中的“Is 操作符”。在“编程基础”的“数组”和“动态数组”中介绍数组。关于跟踪对象的更简易的方法,请参阅本章后面的“创建对象集合”。创建对象集合 集合提供了跟踪对象很有用的方法。与数组不同,当增加和删除集合对象的成员时,它的大小不会改变。例如,若要跟踪拖放到某一特定控件中的每个控件,并且不允许多次拖放任何控件。通过对集合进行管理可做到这点,该集合包含每个被拖放控件的引用:Private Sub List1_DragDrop(Source As VB.Control, _X As Single, Y As Single) Dim vnt As Variant Static colDroppedControls As New Collection For Each vnt In colDroppedControls 如果集合中有被拖放的控件,则 它已经被拖放到这儿一次。 If vnt Is Source Then Beep Exit Sub End If Next 保存被拖放控件的引用。 colDroppedControls.Add Source 在列表框中添加控件名。 List1.AddItem Source.NameEnd Sub该示例使用 Is 操作符将 colDroppedControls 集合中的对象引用和包含被拖放控件引用的事件参数进行比较。Is 操作符可用来测试 Visual Basic 对象引用的一致性:如果两个不同引用的比较结果为同一对象,Is 操作符将返回 True。该示例还使用集合对象中的 Add 方法将对被拖放控件的引用放到集合中。与数组不同,集合本身也是对象。变量 colDroppedControls 被声明为 As New,因此在代码中变量第一次被引用时将创建该集合类的实例。由于变量被声明为 Static,因此当事件过程结束时,该集合对象不会消失。详细信息 请参阅语言参考的“Is 操作符”。本章后面的“Visual Basic 集合对象”中将讨论 Collection 对象的属性和方法。有关上述代码与需要使用数组的代码的比较,请参阅本章前面的“创建对象数组”。要了解如何在自己集合类中包括集合对象,建立更强健的集合,请参阅本章后面的“创建自己的集合类”。本章前面的“Visual Basic 中的对象”讨论如何建立和破坏对象。Visual Basic 集合对象集合是方法将一系列相关的项构成组的一种方法。Visual Basic 中集合可用于跟踪很多事情,例如程序中加载的窗体(窗体集合),或者在窗体中的所有控件(控件集合)。Visual Basic 提供的类属 Collection 类可用来定义自己的集合。需要多少集合对象,就可以建立多少 Collection 对象 即 Collection 类的实例。还可使用集合对象作为自己的集合类和对象模型的基础,它将在本章后面的“创建自己的集合类”和“对象模型”中讨论。例如,集合是跟踪多窗体的最好方法。在“创建用户界面”中的“多文档界面 (MDI) 应用程序”里讨论用户可以打开任何数目文档窗口的应用程序。以下代码段演示如何使用集合对象的 Add 方法,对用户建立的 MDI 子窗体列表进行管理。该代码假定已经存在一个名为 mdiDocument 的窗体,其 MDIChild 属性设置为 True。父 MDIForm 中的模块级集合。Public colDocuments As New Collection建立新的 MDI 子文档窗体的代码。Private Sub mnuFileNew() Dim f As New mdiDocument Static intDocumentNumber As Integer intDocumentNumber = intDocumentNumber + 1 下面的语句创建窗体。 f.Caption = Document & intDocumentNumber 给集合添加对象引用。 colDocuments.Add f f.ShowEnd SubcolDocuments 的作用象是内置窗体集合的一个子集,它只包含窗体 mdiDocument 的一些实例。每添加一个新窗体,自动调节集合的大小。可使用 For Each . Next 在集合内进行迭代。如果赋予窗体一个可以检索的键,那么可提供一文本字符串作为 Add 方法的第二个参数,如本节后面部分所述。在变量 colDocuments 的声明中,New 关键字导致当该变量第一次被引用时,在代码中创建集合对象。因为集合是类,而不是数据类型,所以必须建立集合实例,并且在变量中记录对该实例(对象)的引用。象其它任何对象一样,当包含其引用的最后一个变量被设置成 Nothing 或不可见时,Collection 对象将被撤消。它包含的所有对象引用将被释放。因此,变量 colDocuments 在父 MDIForm 中声明,于是它将存在于程序存活期中的整个过程。注意如果使用集合来跟踪窗体,当窗体被卸载之后,应使用集合的 Remove 方法从集合中删除该对象引用。只要对该窗体的引用仍然存在,就不能收回窗体使用的内存,并且 Collection 对象保存的引用象对象变量中的引用一样完好。集合对象的构成Collection 对象将每一项存储于 Variants 对象中。于是,能够添加到 Collection 对象里的内容列表就和能够存储到 Variants 中的内容列表是相同的。这包括标准数据类型、对象和数组 但不包括用户定义类型。不管 Variants 中存储的是什么,它都占 16 字节,因此使用 Collection 对象不如使用数组的效率高。然而,不能 ReDim 一个 Collection 对象,ReDim Collection 对象能够使代码更清楚、更容易维护。此外,集合对象按键能进行快速的查找,而数组却不能。注意 准确一点说,即使是把数据存储在其它地方,Variants 也总是只占 16 个字节。例如,如果把字符串或数组赋给 Variants,Variants 将包含一个指向字符串和数组数据备份的指针。在 32 位系统中,指针只使用了 Variants 的 4 个字节,而且 Variants 中实际上不存在数据。若要存储一个对象,Variants 将包含该对象引用,就象对象变量所做的一样。对字符串和数组来说,也只使用 Variants 的 4 个字节。数字数据类型存储在 Variants 中。不管什么样的数据类型,Variants 仍然占 16 个字节。除了 Variants 大小之外,还有很多情况需要使用 Collection 对象来存储上面列出的所有数据类型。应该知道进行权衡:使用 Collection 对象能够编写清楚且容易维护的代码 所花费的仅是将一些项存储在 Variant 中。集合对象的属性和方法每个集合对象都有属性和方法,使用它们能够插入、删除和检索该集合中的项。属性或方法描述Add 方法给集合添加项。Count 属性返回集合中项的数目。只读。Item 方法通过索引或关键字,返回项。Remove 方法通过索引或关键字,从集合中删除项。这些属性和方法仅仅是集合最基本的功能。例如,要确保集合只包含一种对象,Add 方法并不能检查将要添加到集合里的对象类型。通过建立自己的集合类能够提供更强健的功能,以及额外的属性、方法和事件,正如本章后面的“创建自己的集合类”中所述。集合中的增加、删除和检索的基本功能需要关键字和索引。关键字是一个 String 的值。它可以是能转换成字符串的名字、驾驶执照号、社会安全号或者简单的整数。Add 方法允许将关键字与项相关联,如本节后面部分所述。索引是长整型,介于 1 和集合中项的数目之间。使用 before 和 after 命名的参数,可以控制项索引的初始值,但是随着其它项的增加和删除,其值会发生改变。注意 索引从 1 开始的集合称为基于 1,如“Visual Basic 中的集合”中所述。使用索引能够在进行集合的项中迭代。例如,假定变量 mcolEmployees 中包含对集合对象的一个引用,下列代码使用两种方法把 Employee 对象集合中所有雇员的薪水提高 10%。Dim lngCt As LongFor lngCt = 1 To mcolEmployees.Count mcolEmployees(lngCt).Rate = _ mcolEmployees(lngCt).Rate * 1.1NextDim emp As EmployeeFor Each emp In mcolEmployees emp.Rate = emp.Rate * 1.1Next提示 为改善性能,应使用 For Each 对 Collection 对象中的项进行迭代。使用 For Each 迭代要比使用索引快很多倍。这并不是对所有集合都正确 它取决于集合内部存储数据的方法。给集合添加项Add 方法用于将项添加到集合。语法是:Sub Add (item As Variant , key As Variant , before As Variant , after As Variant )例如,使用工作定单 ID 属性作为关键字,将工作定单对象添加到工作定单集合里,代码可编写为:colWorkOrders.Add woNew, woNew.ID这里假定 ID 属性是字符串。如果属性是数字(例如 Long),则应使用 CStr 函数将它转换成关键字所要求的字符串值:colWorkOrders.Add woNew, CStr(woNew.ID)Add 方法支持命名的参数。为了添加一项作为第三个元素,代码可编写为:colWorkOrders.Add woNew, woNew.ID, after:=2可以使用 before 和 after 命名的参数管理有序的对象集合。例如,before:=1 将在集合的开始插入一项,因为集合对象是基于 1 的。从集合中删除项Remove 方法用于从集合中删除项。语法是:object.Remove indexindex 参数可以是所删除项在集合中的位置,或者是该项的关键字。如果集合中第三个元素的关键字是“W017493”,则可使用这两条语句中的任何一条删除它:colWorkOrders.Remove 3- 或 -colWorkOrders.Remove W017493从集合中检索项Item 方法用于从集合中检索特定项。语法是:Set variable = object.Item(index)和 Remove 方法一样, index 可以检索项在集合中的位置,或者是该项的关键字。使用 Remove 方法中的相同示例,这两条语句中的任一条都可检索集合中的第三个元素:Set woCurrent = colWorkOrders.Item(3)- 或 -Set woCurrent = colWorkOrders.Item(W017493)如果使用整数作为关键字,在将它们传递到 Item 或 Remove 方法之前,必须使用 CStr 函数将其转换成字符串。通常集合对象都假定整数是索引。提示 Collection 对象不能决定所传递的值是索引还是键。如果想把值解释为键,并且包含该值的变量是除 String 以外的任何值,可以使用 CStr 函数进行转换。如果想把值解释为索引,并且包含该值的变量不是整型数据类型中的一种,使用 CLng 进行转换。Item 是缺省方法对于集合对象来说,Item 方法是缺省方法,因此当访问集合中的项时,可忽略它。所以前面的代码示例也可以写成:Set woCurrent = colWorkOrders(3) - 或 -Set woCurrent = colWorkOrders(W017493)重点 当添加和删除集合对象元素时,集合对象会自动地维护其数字索引编号。因此给定元素的数字索引随之改变。不能在程序中存储数字索引值,并用它检索同一个元素。为达到该目的,应使用键。使用 Item 方法调用属性和方法为了使用对象引用,不能从集合中检索该对象引用,并把它放到对象变量中。当对象仍然在集合里时能够使用其引用。例如,假设上述代码中的 WorkOrder 对象具有 Priority 属性。下面的语句都可用于设置工作定单的优先级:colWorkOrders.Item(W017493).Priority = 3colWorkOrders(W017493).Priority = 3可行的原因是 Visual Basic 要从左到右计算表达式。当遇到 Item 方法时 显式的或隐式的 Visual Basic 为指定的项(此时是键为 W017493 的 WorkOrder 对象)取得一个引用,并使用该引用计算该行的其余部分。提示 如果想调用集合中对象的多个属性或方法,首先将该对象引用复制到一个强类型的对象变量中。把引用放到一个强类型的对象变量中,然后使用,比使用集合里对象的引用要快(例如,Dim woCurrent As WorkOrder),因为 Collection 对象是把项存储在 Variants 中。 Variants 中的对象引用总是最后绑定。详细信息 对很多一般的程序设计任务来说,集合对象也是数组的很有用的可选方案。 请参阅“再论编程”中的“用集合替代数组”。Visual Basic 提供很多内置集合。有关它们与集合对象的比较,请参阅“Visual Basic 中的集合”。Visual Basic 中的集合什么是集合?在“Visual Basic 集合对象”中,集合定义为一种把有相关的对象分组的方法。这种定义留下很多解释余地,与其说它是一种定义还不如说它是一个概念更合适。实际上,当比较集合时就会发现,Visual Basic 所提供的各种集合之间都有很大的差别。例如,下列代码会引起错误:Dim col As CollectionSet col = Forms 错误!这是怎么回事?Forms 集合是集合,变量 col 也声明为 Collection,为什么不能将指向 Forms 的引用赋给变量 col?其原因是 Collection 类和 Forms 集合都不是多态的,即它们不能相互交换,因为是从各自的代码库开发的。它们没有相同的方法,没有用相同的方法存储对象引用,或者没有使用相同种类的索引值。这使得 Collection 类名似乎是多余的,因为它仅仅代表许多可能实现集合方法的一种。该主题探讨一些实现方法的差别,后面将会遇到这些差别。基于 0 和基于 1 的集合集合是基于 0 还是基于 1,要取决于开始索引是哪一个。可以猜想,前者的意思是集合中第一项的索引为 0,后者的意思是集合中第一项的索引为 1。基于 0 的集合示例是 Forms 和 Controls 集合。基于 1 的集合的示例是集合对象。Visual Basic 中旧的集合大多是基于 0 的。而新添加的集合大多基于 1。基于 1 的集合使用时更加直观,因为索引的范围是从 1 到 Count,其中,Count 是能返回集合中项数目的属性。对应基于 0 的集合索引来说,其范围则是从 0 到 Count-1。索引和键值正象 Visual Basic 中的 Collection 对象那样,Visual Basic 中很多集合可以使用数字索引或字符串键来访问其中的项。(然而,Visual Basic 中的 Collection 对象不用指定键就能添加项。)相反,Forms 集合只能使用数字索引来访问。这是因为没有唯一的字符串值与窗体关联。例如,多个窗体可以有相同的标题,或者加载的多个窗体有相同的 Name 属性。添加和删除项在能否向集合中添加项这点上,集合之间也是有区别的,如果可以,这些项是如何添加到集合中的。例如,不能使用 Visual Basic 代码向 Printers 集合添加打印机。因为 Collection 对象是一般性程序设计工具,它比其它集合更加灵活。它具有 Add 方法可以将项添加到集合里,也有 Remove 方法可以将项从集合中删除。与之形成对比的是,Forms 集合获取窗体的唯一方法是加载窗体。如果使用 New 操作符建立窗体,或者通过引用一个声明为 As New 的变量建立窗体,那么该窗体是不能被添加到窗体集合里的,除非使用 Load 语句进行加载。Forms 和控件集合没有 Remove 方法。可以使用 Load 和 Unload 语句间接的向这些集合中添加和从这些集合中删除窗体和控件。窗体集合中的成员正如上面所述,窗体在加载之前不能添加到 Forms 集合中。因此 Forms 集合的最准确的说明是:它包含的是程序中当前加载的所有窗体。即使它不完全准确。如果工程中使用 Microsoft Forms(为了与 Microsoft Office 兼容被包括的),就会发现这些窗体都在一个名为 UserForms 的单独集合里。因此该 Forms 集合所包含的就是程序中当前加载的所有 Visual Basic 窗体。而 Collection 类十分准确指定的内容是:能够存储到 Variants 里的任何东西。于是集合对象能包含对象或者整数,但不能包含用户定义类型。遗憾的是,该说明的覆盖范围很广 集合类给定的一个实例能够存储任何数据类型、数组和对象的混合组合。提示 正如“创建自己的集合类”中所述,建立自己的集合类的最重要原因是能够控制自己的集合中的内容 称为类型安全性概念。集合的枚举可以使用 For Each . Next 对集合中的项枚举,而不用担心集合是基于 0 还是基于 1。当然,这很难作为集合的一个定义特性,因为 Visual Basic 也允许使用 For Each . Next 对数组中的项枚举。使 For Each . Next 能工作的是一个称为 enumerato 的很小的对象。枚举算子记录集合中项的位置,并在需要时返回下一项。枚举数组时,在运行中 Visual Basic 创建一个数组枚举算子对象。集合具有自己的枚举算子对象,它也是需要时创建的。枚举算子不会跳过项Visual Basic 中集合的枚举算子不会跳过项。例如,假设枚举一个包含 A、B 和 C 的集合,并且进行枚举时删除了 B,则在操作时 Visual Basic 不会跳到 C 上。枚举算子可能不捕捉添加的项当枚举集合时,如果给集合添加了项,一些枚举算子将能包含添加的项,而一些枚举算子则不会。例如,枚举 Forms 集合时就不枚举刚加载的任何窗体。如果将它们添加到集合末尾,则在枚举时集合,对象就能枚举添加的项。因此下列循环永远不会终止(即直到按 CTRL+BREAK 组合键):Dim col As New CollectionDim vnt As Variantcol.Add Endlesscol.Add EndlessFor Each vnt In col MsgBox vnt col.Add EndlessNext另一方面,添加到集合开始的项不会包含在枚举里。Dim col As New CollectionDim vnt As Variantcol.Add Will be enumeratedFor Each vnt In col MsgBox vnt 在开始处添加项。 col.Add Wont be enumerated, Before:=1Next为什么需要枚举算子?每次 For Each . Next 开始时,通过发出一新枚举算子,集合允许嵌套的枚举。例如,假定在变量 mcolStrings 中有一个 Collection 对象的引用,并且该集合只包含字符串。下列代码打印两个不同字符串的所有组合:Dim vnt1 As VariantDim vnt2 As VariantFor Each vnt1 In mcolStrings For Each vnt2 In mcolStrings If vnt1 vnt2 Then Debug.Print vnt1 & & vnt2 End If NextNext详细信息 请参阅本章后面的“创建自己的集合类”。查找对象信息对象浏览器是基于类型库的,类型库是包含属性、方法、事件、命名常数以及其它许多方面信息在内的、类的详细描述的资源。Visual Basic 为创建的类建立类型库信息,为其包含的对象提供类型库,并且允许访问其它应用程序提供的类型库。可以使用对象浏览器显示工程和库中的有效的类,包括自己定义的类。用这些类所创建的对象都拥有同样的成员 属性、方法和事件 这些都可以在对象浏览器中看到。图 9.1 对象浏览器要显示对象浏览器,请 从“查看”菜单选择“对象浏览器”。 - 或 -按 F2 键。- 或 -在工具栏上单击“对象浏览器”。按照缺省规定,对象浏览器不能接连接其它窗口。这样可以使用 CTRL+TAB 在对象浏览器和代码窗口之间切换。也可以通过在对象浏览器中单击右键打开上下文菜单,并单击“可连接的”改变这种情况。注意当对象浏览器处于可以连接状态时,不能使用 CTRL+TAB 从代码窗口切换至对象浏览器。以下主题详细讨论对象浏览器的功能。 对象浏览器的内容 对象浏览器显示类及其成员。提示对象内容的描述性的文字,并给出函数模板。 查找和浏览对象 即使只记得名字的一部分,也可以找到对象及其成员。 添加对象的描述 为类及其成员添加的描述可以帮助对类的使用。 在过程之间移动 可以在工程内找到模块和过程,并跳转到其代码处。 浏览其它应用程序的对象 可以在自己的程序中使用其它应用程序中的对象;对象浏览器将显示其它应用程序所提供的自动化对象。 添加对象的描述 可以使用对象浏览器给自己的过程、模块、类、属性和方法添加描述及“HelpContextIDs”。使用自己的类时就能找到这些有用的描述。注意 也可以从“工具”菜单中使用“过程属性”对话框给属性、方法和事件添加描述。要输入描述字符串,并将类及其成员与帮助主题进行链接,请按照以下步骤执行: 1. 按 F2 键打开“对象浏览器”。在“属性/库”框中选择所需的工程。2. 在“类”列表中,在类名处单击右键弹出上下文菜单,然后单击“属性”打开“成员选项”对话框。 或者,也可以在“成员”列表中对已添加到类中的属性、方法或事件名单击右键。在上下文菜单中,单击“属性”。如果成员是 Private 的或 Friend的,则打开“成员选项”对话框。如果成员是 Public 的 即类的界面部分 将代之以打开“过程属性”对话框。注意 这两种对话框的区别是“过程属性”对话框有一个“高级”按钮可用来将一个成员指定为该类的缺省成员,这一点将在本章后边的“使属性或方法成为缺省的”中进行描述。3. 为了当这个类或成员在“对象浏览器”中被选中,并单击“?”时,该帮助主题的上下文标识符能被显示,应在“帮助上下文标识符”框中键入该帮助主题的上下文标识符。 注意 可以创建一个帮助文件以备自用,并将主题连接到自己的类及其成员中。如果希望为自己的工程指定一个帮助文件,可在“工程”菜单中打开“工程属性”对话框,使用其中的“通用”选项卡。4. 在“描述”框中,键入关于该类或成员的简短描述。5. 单击“确定”返回“对象浏览器”。键入的描述字符串应该出现在浏览器底部的描述面板中。6. 对每一个类和其中的的每一个成员重复第 2 步到第 5 步。 注意 不能为枚举添加浏览器字符串或帮助主题。详细信息 枚举在“再论编程”中的“通过枚举使用常数集进行工作”中进行介绍。类:将用户定义类型和过程组织在一起用户定义类型是一个使相关数据项成组的强大工具。例如,假设此处要定义名为 udtAccount 的用户定义类型:Public Type udtAccount Number As Long Type As Byte CustomerName As String Balance As DoubleEnd Type可以声明一个 udtAccount 类型的变量,分别给各个字段赋值,然后将整个记录传递给打印它的过程,并将其保存至数据库中,对其执行计算,验证各字段的数值,等等。用户定义类型尽管功能强大,但也给编程者带来了一些问题。例如所创建的提款过程可能出错,如果当提款超过帐上余额,程序中又没有措施防止其它代码对余额字段减时就会出错。换句话说,过程和用户定义类型的结合效果取决于规则、内存和维护代码的编程者的知识水平。对象:具有态的用户定义类型面向对象的编程通过将数据和过程结合成一个单一实体解决了上述问题,如图 9.5 所示。图 9.5 对象使数据和过程相结合当用户定义类型 udtAccount 变成 Account 类时,其数据变成了私有型,访问它们的过程移动类中并变成了属性和方法。这就是所谓的封装的意思 这就是说,对象是一个包括了代码和数据的单元(如果愿意,也可称其为密封舱)。当从 Account 类创建一个 Account 变量时,访问其数据的唯一途径就是通过构成其界面的属性及方法。以下的代码段说明在 Account 类中的过程是如何支持封装的:帐户余额对外界代码是隐藏的。Private mdblBalance As Double帐户余额的只读属性允许外部的代码获取帐户余额。Public Property Get Balance() As Double Balance = mdblBalanceEnd Property提取存款的方法改变了帐户的余额,但仅限于不发生透支错误的情况。Public Sub Withdrawal(ByVal Amount As Double) If Amount Balance Then Err.Raise Number:=vbObjectError + 2081, _ Description:=Overdraft End If mdblBalance = mdblBalance - AmountEnd Sub现在,暂不要考虑如何将过程放进类中,也不要考虑如何理解属性过程和私有变量的语法。要记住的重点就是可以定义一个对象来封装数据和确保数据的可靠。有了 Account 对象,就永远不必关心是否调用了正确的过程更新帐户,因为可以调用的那些过程都已经组装进对象中了。详细信息 “定制窗体类”部分将属性和方法的创建放入已熟悉

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论