客户端用Net-Library和SQL SERVER连接 6 VB中的对象 面向对象编程(Object-Oriented Programming,简称OOP)是当今最流行的编程模式。尽管VB是事件驱动的,但是它也很好地支持了面向对象的编程,完全可以编写出面向对象的代码。在第1章第1.3节介绍了面向对象的基本概念、设计方法和语言要点等面向对象的一般方法。本章介绍面向对象的方法和技术在VB中的应用。严格说来,VB的面向对象特性并不如C++那样彻底,但是,由于VB具有的简洁性、通用性等特点,使得它仍然是最收欢迎的首选程序设计语言。 可以使用Visual Basic提供的对象,如控件、窗体和数据访问对象,也可以在一个Visual Basic应用程序内部控制另一个应用程序对象,甚至可以建立自己的对象,定义它们的属性和方法。 INTRANET
6.1 VB中的对象基本概念 6.1.1 对象是类的实例 正如第1章所述,对象是代码和数据的封装体,这个封装体可以作为一个单位来处理。对象可以是应用程序的一部分,比如可以是控件或窗体。整个应用程序也是一个对象。表6.1列出了VB中可用到的几种类型的对象。
类(Class)是面向对象编程的基础。类和Type数据结构的区别在于,Type数据结构只有数据成员,没有成员函数,而类即包含数据成员,还包括属性和方法。类就是一个没有图形用户界面(GUI)的ActiveX控件。在VB中,遗憾的是类不能继承。 Visual Basic中的每个对象都是用类定义的。用模具和坯子之间的关系作比喻,就会明白对象和它的类之间的关系。类好比是瓷器生产中的模具,对象好比是用模具成型出来的坯子。类就是对象的模板,对象是类的实例。
在VB “工具箱”上的控件代表类。直到在窗体上画出这些被称作控件的对象为止,它们实际上并不存在。在创建控件之时也就是在复制控件类,或建立控件类的实例。这个类实例就是应用程序中引用的对象。还用瓷器生产过程中的模具和瓷器比喻,假如工具箱里的某个“命令按钮”表示“碗”哪>撸梢杂盟⒍喔觥巴”的实例,这些“碗”具有相同的尺寸和形状,就像“命令按钮”具有相同属性种类和事件种类。可以为这些“碗”画不同颜色的花边和图案,就像“命令按钮”的不同“Caption”属性赋值;依此类推,“列表框”控件表示“8寸盘子”的模具,可以用它建立多个“8寸盘子”的实例,而这些“8寸盘子”可以涂上各种底色等等。
6.1.2 对象的使用方法 对象可以提供现成代码,省却书写麻烦。例如,虽然可以自己创建打开文件和保存文件的对话框,但实际上大可不必这样做。取而代之的是利用VB提供的公共对话框CommonDialog控件(一个对象)。 VB提供了把来自不同资源的对象组合起来的工具。现在可把VB的各种强有力的特性以及支持自动化(先前以OLE自动化闻名)的应用程序结合起来,建立定制的解决方法。自动化是部件对象模式(COM)的一个特性,它是应用程序使用的工业标准。 可以把VB内部的控件结合在一起,也可以使用其他应用程序提供的对象。例如,可以考虑把下列对象放入VB窗体: Microsoft Excel Chart对象、Microsoft Excel Worksheet对象和Microsoft Word Document对象等等。
在运行时可以设置并可获得值的属性叫做读写属性,在运行时只能读取不能设置的属性叫做只读属性。 用属性控制对象 个别属性随着可以设置和取得它们的值的时间不同而不同。有的属性可以在设计时设置,可在“属性”窗口设置这些属性的值而无须编写任何代码。而有的属性在设计时是不可用的,这些属性只有通过代码在运行时设置。 在运行时可以设置并可获得值的属性叫做读写属性,在运行时只能读取不能设置的属性叫做只读属性。 在改变对象的外观或特性时可以设置属性的值。例如,通过改变TextBox控件的Text属性值,就可以改变文本框的内容。用下列语法设置属性值:
Text1.Visual = True ‘显示文本框 Text1.Text = “欢迎!” ‘在文本框中显示“欢迎!” ObjectName.property = expression 对象名. 属性名=属性值表达式 下面是设置属性的语句: Text1.Top = 200 ‘设置Top属性为200缇 Text1.Visual = True ‘显示文本框 Text1.Text = “欢迎!” ‘在文本框中显示“欢迎!” 要想在代码执行附加动作(例如给另一个对象赋值)之前得知对象的状态,这时就要读取属性值。例如,在运行代码之前能够返回TextBox控制的Text属性值,以确定文本框的内容,这里,代码可能改变值。
在大多数情况下可以用以下语法获得属性值: variable = ObjectName . property 变量名= 对象名. 属性名 下面是读取属性的语句: y=Text1.Top ‘读取文本框Text1的Top属性,将其赋值给长整数型变量y 。 s=Text1.Text ‘读取文本框Text1的Text属性,将其赋值给变量字符串型变量s 。 属性值可以作为较复杂的表达式的一部分,而不必将属性赋予变量。例如,下面的语句将属性值作为条件语句中的条件表达式:
句将属性值作为条件语句中的条件表达式: If Text1.Visual Then Text1.Text = “我是可见状态!” Else Text1.Text = “我是隐蔽状态!” End if 如果不只一次使用一个属性值,而且将这个值存储到一个变量中,代码的执行会更快。
用方法来执行动作 在代码中使用方法时如何书写语句,这取决于该方法要求多少参数,以及是否返回一个值。如果方法不要求参数,则用以下语法编写代码: ObjectName . method 对象名 . 方法 例如,下面的语句是图片控件对象Picture1引用刷新图片方法Refresh的语法: Picture1 . Refresh ‘强迫重画控件,该方法既不需要参数,也无返回值。 如果方法要用多个参数,就用逗号将它们分开。例如,画圆方法Circle就要用代表窗体上圆的位置坐标、半径和颜色的参数: ‘在窗体对象Form1上以点(1600,1800)为圆心坐标,以1200缇为半径化一个兰色的圆。 Form1 . Circle (1600,1800),1200,vbBlue
如果要保存方法的返回值,就必须把参数用括号括起来。例如,GetDate方法从剪贴板返回一张图片: Picture1 = Clipboard.GetData(vbCFBitmap) 如果没有返回值,则参数不会出现在括号中。例如,在列表框对象List1中添加项目方法AddItem的语句: List1. AddItem “中国” ‘在列表框控件对象List1中添加项目“中国” 。
6.2 VB中的对象之间的关系 如前所述,在同一窗体上放置两个命令按钮时,它们是两个具有不同Name属性设置值(Command1和Command2)的分开的对象,但都分享同一个类,即命令按钮。 它们也共享这样一个特征,即它们在同一个窗体上。窗体上的其它控件也包含在该窗体中。这就把控件放在一个层次上了。要引用控件就必须先引用窗体,就如同达电话拨号一样,先要拨国家号码或区域号码,然后再拨具体的电话号码;或者要找房间号,必须先引用楼号、单元号等等。
6.2.1 对象的层次和对象集合 对象层次提供了一种组织结构,它决定了对象之间的相互关系以及访问它们的方法。在大对数情况下不必考虑VB环境中的其他对象的层次。但是,在操作其他应用程序的对象时,应当熟悉那个程序的对象层次。在使用数据访问对象时,应当熟悉数据访问对象层次。 对象集合有自己的属性和方法。对象集合中的对象作为集合的成员被引用。集合中的每个成员从0开始顺序编号,这就是成员的索引号。例如,控件集合包含已给窗体上的所有控件。 图5-8 Image示例程序运行结果
例如,下列代码遍历控件集合,并在列表框中列出每个成员的名字。 For Each Control In Form1.Controls List1.AddItem Control.Name ‘把每个控件的名字送到列表框。 Next Control 有两种通用方法可用来对集合对象成员寻址: 1)指定成员的名称。例如,以下两个表达式等价: Controls(“List”) Controls! List1 2)利用成员的索引号。例如,下面是对索引号为3的控件对象成员寻址: Controls(3)
一旦能够从整体上对全体成员寻址,而且还能够个别地对单个成员寻址,就可用任何一种方式应用属性和方法。例如,将ListBox控件的Top属性设置为200可以用下面的方法致之一。 方法一: Controls!List.Top = 200 方法二: For Each Control In Form1.Controls() Control.Top = 200 ‘将每一个成员的Top属性设置为200。 Next Contro
在VB中一个对象集合包含其他对象成员的一般情况是很普遍的。表6.2列出了VB中最常用的公共集合。 6.2.2 对象的包含与相互通讯 对象的包含 在VB中,一些对象可以作为“容器”包含其他对象。例如,窗体作为容器对象通常包含一个或数个控件对象。把一个对象当作其他对象的容器的好处在于,在代码中引用容器即可明了要使用哪个对象。 对象集合 在VB中一个对象集合包含其他对象成员的一般情况是很普遍的。表6.2列出了VB中最常用的公共集合。
Prints 包含可用的打印机对象 容器对象 在窗体内,可用Container属性改变对象的容器。以下控件对象可以作为容器包含其他控件对象: Fram控件; PictureBox控件; ToolBar控件(仅对专业版和企业版而言)。 下面的示例程序演示了如何在窗体上将命令按钮从一个容器移到另一个容器。打开新工程,并在窗体上画出Frame控件、PictureBox控件和CommandButton控件。 下列代码在窗体单击事件中,每单击一次窗体,使计数器变量增加1,并通过Select Case循环使命令按钮在两个容器之间移动。 。
Private Sub Form_Click() Static intX As Integer Select Case intX Case 0 Set Command1.Container = Picture1 Command1.Top = 0 Command1.Left = 0 Case 1 Set Command1.Container = Frame1 Command1.Top = 140 Case 2
Case 3 Set Command1.Container = Frame1 Command1.Top = 140 Command1.Left = 0 Case 4 Set Command1.Container = Picture1 Command1.Top = 0 End Select intX = intX + 1 End Sub
图6-1 窗体Form1在运行之前Command1的位置 窗体Form1在运行之前如图6-1所示,单击一次窗体,命令按钮控件Command1进入容器Picture1内,如图6-2所示;再单击一次窗体,命令按钮控件Command1进入容器Frame1内,如图6-3所示;依此类推。 图6-1 窗体Form1在运行之前Command1的位置
图6-2 命令按钮控件Command1进入容器Picture1内
图6-3 命令按钮控件Command1进入容器Frame1内
6.3 VB中的对象创建方法 创建对象的最简单方法是在“工具箱”中双击控件工具按钮。但是对于VB中所有可用对象以及来自其他应用程序的所有可用对象来说,要想充分体现它们的优势,可在程序运行时用VB的可编程性能创建对象。运行时用代码创建对象主要有以下几种方法: 1)用对象变量创建对象引用。 2)用模块类“从零开始”创建自己对象。 3)用集合对象创建自己的集合 本章介绍前两种方法,第3种方法将在有关数据库应用程序设计的章节中讲解。
6.3.1 用对象变量创建对象引用 在第4章介绍了变量的基本概念。变量除了用来存储值以外,还用来引用对象。如同给变量赋值一样,可以把对象赋值给对象变量。 用对象变量引用对象主要有以下优点: 1)变量名往往比变量所含的值(引用的对象)短而好记。 2)在运行代码时,为了引用其它对象,应使用对象变量。 3)引用包含对象的变量比反复引用对象本身有更高的效率。
声明一个对象变量,对象变量的类由Class指定。关于New关键字和 Class参数的说明见后续章节。 声明对象变量 声明对象变量的方法和声明其它变量一样,要用Dim、ReDim、Static、Private和Public等保留字。仅有的不同点在于可选的New关键字和Class参数。 1.格式 {Dim∣ReDim∣Static∣Private∣Public} VariableName As∣New∣ Class 变量名 As∣New∣ 类名 2.功能 声明一个对象变量,对象变量的类由Class指定。关于New关键字和 Class参数的说明见后续章节。
3.示例 1)‘声明一个叫做“FormVar”的对象变量,它引用应用程序中的(预先设计好了的)被称作frmMain(Class参数)的窗体,因此“FormVar”是一个窗体类。 Dim FormVar As New frmMain ‘ 声明一个类型为frmMain的对象变量。 2)‘声明一个叫做“anyForm”的对象变量,它引用应用程序中的任何窗体,Form是一般类参数。 Dim anyForm As Form ‘一般窗体变量。 3)‘声明一个叫做“anyText”的对象变量,它可以引用应用程序中的任何一个文本框。 Dim anyText As TextBox ‘它可引用任何文本框。 4)‘声明一个对象变量,它能够引用任何类型的控件。 Dim anyControl As control‘一般控件变量。
4.说明 可以声明一个引用应用程序中的指定窗体的窗体变量,但不能声明引用特定控件的控件变量。可以声明能够引用控件的特定类型(如TextBox或列表框)的控件变量,但不是引用那种类型的一个特定控件(如txtEntry 或List1),但是可把特定的控件赋予那种类型的变量。
赋值对象变量 象普通变量那样,可以给已经声明过的对象变量赋一个合适的值,这个值必须是声明时的Class参数类。用Set语句将对象赋予对象变量。 1.格式 Set VariableName = object Set 变量名 = 窗体对象名|控件类名 2.功能 将object参数指定的窗体对象名或者控件类名赋值给VariableName指定的对象变量。 3.示例 Dim FormVar As form ‘声明一个引用窗体类的对象变量。 Set FormVar = frmMain ‘将预先设计好了的窗体对象frmMain赋值给FormVar 4.说明 无论何时,只要希望对象变量引用对象,就可使用Set语句。有时可用对象变量,尤其可用控件变量直接缩短要键入的代码。
特定对象类型与一般对象类型 特定对象变量必须引用特定类型的对象或类。特定的窗体变量只能引用应用程序中的一个窗体。与此相似,特定的控件变量只能引用应用程序中的特定类型的控件。 一般对象变量可在多种特定对象类型中引用其中一种,例如,一般窗体变量可引用应用程序中的任何窗体;一般控件变量可引用应用程序中任何窗体上的任何控件。 VB中的四种一般对象如表6.3所示。
在不知道变量运行时是否引用特定类型的对象时,一般对象变量是很有用的。例如,如果要书写代码,并使之在应用程序的任何窗体中都可操作,则必须使用一般窗体变量。 由于应用程序中只能有一个MDI窗体,因此不必使用一般的MDIForm类型。无论何时,一旦需要声明引用MDI窗体的窗体变量,就可用特定的MDIForm类型(或者是MDIForm1,或者是对MDI窗体的Name属性指定的任何名称),而不用一般的MDIForm类型。只是出于完整性的考虑才提供一般的MDIForm类型。
当作对象使用的窗体 窗体主要用来构造应用程序界面,但有时也用来作为应用程序中其他模块调用的对象。窗体与类模块关系密切。两者之间的主要区别在于,窗体是可视对象,而模块却没有可视界面。 可对窗体添加自定义方法和属性,并可从应用程序中的其他模块访问它们。为了创建窗体的新方法,可以在窗体级的代码中添加用Public声明的过程。 假设已经设计了一个叫做Form_object的窗体,于是,可以 用下面的语法为Form_object窗体添加自定义方法。 Public Sub 方法名() 代码块 End Sub 用上述语法自定义的方法可以用下面这个语句从其他模块调用: Form_object .方法名
创建窗体的新属性就象在窗体模块中声明一个公用变量那样简单,也可用Property过程向窗体添加自定义属性。例如,对于上述窗体Form_object,用下面的变量声明语句可以为其增加一个标示号属性。 Public IDNumber As Integer ‘在Form_object的通用代码中声明全局变量。 Form_object.IDNumber=8 ‘为Form_object的IDNumber属性赋值为8。 在引用窗体的方法和属性值时,不必加载窗体就可以调用窗体的变量、属性和自定义方法,还可设置窗体的自定义属性。于是,不必将窗体加载到内存就可运行有关窗体的代码。同样,引用控件而不引用其属性或方法时也不会加载窗体。
图6-4 选择菜单“工程”中的“添加类模块( C )” 6.3.2 用类模块创建对象 6.3.2.1 创建一个类模块 要在VB中创建一个新类,需要向VB工程中添加一个类模块。一个类模块只能包含一个类的定义,因此,必须为每个类添加一个类模块。添加类模块的方法是,选择菜单“工程”中的“添加类模块( C )”。 如图6-4所示。 图6-4 选择菜单“工程”中的“添加类模块( C )”
单击“添加类模块( C )”后,弹出添加类模块窗口,选则“新建”标签中的“类模块”图标后按“打开”按钮,即可在工程中添加一个类模块。如图6-5所示。 图6-5 在工程中添加一个类模块
下面,我们要创建一个职员类Class1。保存工程时将类模块的名称修改为“zhiyuan 下面,我们要创建一个职员类Class1。保存工程时将类模块的名称修改为“zhiyuan.cls”,下面就可以向类中添加属性和方法了。添加类模块后,工程资源管理器的项目如图6-6所示。 图6-6 工程资源管理器的项目
6.3.2.2 向类中添加属性和方法 类模块的代码如下: ‘首先向类中加入声明为私有(Private)的一个成员变量m_1EmployeeNumber,记录雇员的雇员号。 ‘其次声明一个私有的字符串数组m_Family()用于存放职员的家庭成员。 Private m_1EmployeeNumber As Long Private m_Family() As String ‘由于m_1EmployeeNumber这个成员的变量是私有的,因此在类外不能被访问。为了让类外的对象访问职员号,可以添加一个属性EmployeeNumber来存取它。定义属性必须有Get和Let两个属性过程。EmployeeNumber属性的两个属性过程如下:
‘Get属性过程代码: Public Property Get EmployeeNumber() As Long EmployeeNumber = m_1EmployeeNumber End Property ‘Let属性过程代码: Public Property Let EmployeeNumber(lNumber As Long) If lNumber > 1000 Then Err.Raise lInvalid_Emp_Number, "CEmployee:EmployeeNumber",_ & "Invalid Employee Number" Else m_lEmployeeNumber = lNumber End If
‘为职员类Class1加入一个Family属性记录该职员的家庭成员的姓名。 ‘Family属性的Get过程代码如下: Public Property Get Family() As String() Family = m_Family End Property ‘Family属性的Let过程代码如下: Public Property Let Family(arr() As String) m_Family = arr End Property 其实任何类型都可以作为属性的类型,只需把属性类型声明为Variant,因为,Variant型变量可以存储任何数据类型的值。
为了显示一个雇员的家庭成员的名字,为Class1类添加一个方法DisplayFamily。为了让外部对象能访问类的方法,必须把方法定义成公有(Public)的。DisplayFamily方法的具体实现如下: Public Function DisplayFamily() As String Dim X Dim sTemp As String sTemp = "雇员号:" & CStr(m_1EmployeeNumber) & vbCrLf For Each X In m_Family sTemp = sTemp & X & vbCrLf Next DisplayFamily = sTemp End Function
6.3.2.3 从类创建新的对象 要使用一个类,必须创建这个类的一个对象。下面通过使用刚才创建的Class1类来加深对对象的理解。 在窗体Form1的单击事件代码中,先创建一个Class1类的新对象,再设置EmployeeNumber属性和Family属性的值,最后在窗体上显示出此雇员的所有家庭成员的名字。 窗体Form1的单击事件代码如下:
Option Explicit Private Lee As Class1 Private Sub Form_Click() Set Lee = New Class1 Lee.EmployeeNumber = 100 ReDim arr(0 To 4) As String arr(0) = "李明" arr(1) = "王丽丽" arr(2) = "李大明" arr(3) = "李小明" arr(4) = "李小丽" Lee.Family = arr Print Lee.DisplayFamily End Sub 程序的运行结果如图6-7所示。
图6-7 程序的运行结果
6.3.2.4 多态性 用VB中的类也可以实现象C++中一样的多态性。使用关键字Implements给实现多态性提供了可能。 首先,定义一个公共接口(inteface),接口里包含了一些属性和方法的声明(注意,只是声明,没有具体实现)。例如,要定义一个Iperson的接口,在VB工程中加入一个类模块,声明一些属性和方法,代码如下所示: ‘Interface:Iperson Option Explicit Public Name As String Public Address As String 这里用Public声明代替了属性过程(Property Get和Property Let),因为在这里没有编写任何具体实现的代码,所以不需要属性过程。其实,VB中的这种接口和Java中的Interface类似,同时也和C++中的抽象类(Abstract)类似。
接下来必须在工程中添加另外一个模块来具体实现这个接口。先在类模块的开始处加上Implements关键字,再逐一实现接口中定义的属性和方法。假设这个类的类名为Ccustomer,在类模块中添加代码如下: Option Explict Implements Iperson ‘必须加入这行! Private Property Let Iperson_Address(By Val RHS As String) ‘在这里编写代码 End Property Private Property Get Iperson _ Address() As String Private Property Let Iperson _Name(By Val RHS As String) MsgBox “New value is;” & RHS Private Property Get Iperson _Name As String MsgBox “Got the value”
可以添加很多类模块,用不同的方法实现同一个接口,这样就实现了多态性(相同的界面,多种实现版本。)。 用类模块实现了公共接口之后,如何来使用Ccustomer类和接口呢?如果编写如下代码来使用它: Private m_Customer As Ccustomer Private Sub Form_Load() Set m_Customer = New Ccustomer M_Customer.Name = “李明” End Sub
那么就会发现产生了错误,因为在Ccustomer类定义中,属性都是私有的,不能在类外引用它们。但是,在Iperson接口中,属性都是公有的,因此,可以通过Iperson接口来访问Ccustomer类的属性,下面这段代码看起来是可行的: Option Explict Private m_Customer As Ccustomer Private m_Iperson as Iperson Private Sub Form_Load() Set m_Customer = New Ccustomer Set m_Iperson = m_Customer M_Iperson.Name = “李明” End Sub
但是这样不够直观,可以有一种更好的方法来访问Ccustomer类的私有属性: Option Explict Private m_Customer As Ccustomer Private Sub Form_Load() Set m_Customer = New Ccustomer Test m_Customer End Sub Sub Test(obj As Iperson) Obj. Name = “李明” Obj.Address = “建设大街11号”
6.3.2.5 使用Class Builder 可以使用图6-5中的“VB类生成器”来快速创建一个新类,单击图6-5中的“VB类生成器”图标,就可以使用“VB类生成器”向导来创建类了。如图6-8所示。 图6-8 VB类生成器向导
6.3.3 使用New关键字 用New关键字创建新对象,这个对象被视为它的类所定义的对象。可用New创建集合、窗体的实例以及类模块中定义的类。 在窗体上使用New关键字 在设计时创建的窗体是类,可用New关键字创建这个类的新实例。 要使窗体变量和已加载窗体的实例一直存在,需要用Static或Public声明变量,而不要用局部变量。 也可以将New关键字与Set语句并用,将New关键字和Set语句并用会加快运行速度,因此这种方法值得推荐。
下面的代码假设已经在设计状态设计好了窗体Form1,用命令按钮的Click事件过程中的代码创建一个窗体对象,并且设置其属性,然后显示该窗体对象,命令按钮的单击事件代码如下: Private Sub Command1_Click() Dim f As Form2 Set f = New Form2 f.Caption = "我是窗体Form2的实例" f.Show End Sub 程序的运行结果如图6-9所示。
图6-9 New关键字示例程序的运行结果
对其他对象使用New关键字 可用New关键字从类模块中定义的类创建集合和对象,下例说明了New关键字是如何创建类的实例的。从“工程”菜单中选择“添加类模块”命令,从而在工程中添加一个类模块。设置类模块的Name属性为ShowMe。 Form1中的下列代码创建了ShowMe的新实例,还调用了包含在类模块中的过程。 Public clsNew As ShowMe Private Sub Command1_Click() Set clsNew = New ShowMe ClsNew.ShowFrm End Sub Sub ShowFrm() Dim frmNew As Form1 Set frmNew = New Form1 FrmNew.Show FrmNew.WindowState = 1
New关键字的限制 表6.4说明了在使用New关键字时应该注意的一些限制。 表6.4 使用New关键字的限制
释放对对象的引用 每个对象都使用内存和系统资源。当不再使用对象时应该及时释放这些资源,这是良好的编程习惯。 用Unload从内存中卸载窗体或控件。 用Nothing释放对象变量占用的资源。用Set语句将Nothing赋予对象变量。 给过程传递对象 在VB中可以将对象作为调用参数传递给过程。在下面的示例程序中,有Form1和Form2两个窗体,在Form1上有两个命令按钮Command1(调用使窗体Form1水平居中的过程)、Command2(将Form2的图片框对象传给Form1)和一个图片框Picture1(它的Picture属性设置为空。)。设计状态的Form1如图6-10所示。
图6-10 设计状态的Form1
窗体Form1的代码包含命令按钮Command1的单击事件过程和一个名为“Demo”的子过程。 Private Sub Command1_Click() '调用Demo子过程,将Form1作为对象参数(实际参数)传给Demo子过程。 Demo Form1 End Sub “Demo”的子过程的调用需要一个“Form1类”形式参数x,代码如下: Private Sub Demo(x As Form1) '在屏幕中使窗体居中。 x.Left = (Screen.Width - x.Width) / 2
窗体Form1的代码还包含命令按钮Command2的单击事件过程。 Private Sub Command2_Click() ‘调用Form2的GetPicture过程,并且把Form1上的图片框控件对象Picture1(空框)作为实在参数传给 Form2中的GetPicture过程。 Form2.GetPicture Picture1 End Sub 第二个窗体Form2上包含一个图片框控件Picture2,设计时将它的Picture属性值设置为d:\Vb教程\给过程传对象\lion.wmf。可以通过引用把对象传递给参数,然后在GetPicture过程内将参数设置成新对象。设计状态的Form2如图6-11所示。
图6-11 设计状态的Form2
窗体Form2的代码如下: Private objX As PictureBox ‘声明一个对象变量objX,它是PictureBox类。 Public Sub GetPicture (x As PictureBox) ‘定义GetPicture 过程。 '将从Form1传来的空图片框对象赋值给对象变量x Set objX = x ‘赋值对象变量。 '将Form2上的Picture2控件对象的Picture属性赋值给Form1的图片框。 objX.Picture = Picture2.Picture End Sub 程序运行后,按第一个命令按钮使窗体水平居中,按第二个命令按钮将把第二个窗体上的图片加载到第一个窗体上。程序执行结果如图6-12所示。
6-12 按了下面的命令按钮后程序执行结果
6.4 引用其它窗体的对象 在一个窗体模块中引用其它窗体中定义的函数或过程时要加上窗体名称作为限定词,即使引用Public定义的全局函数也需要加窗体名。比如给出半径计算面积的Area()函数是在 窗体Form1中定义的,在Form2中引用时,要用如下语法: Text1 = Form1.Area(23.652)。 也可以在一个窗体中操纵另一个窗体中的对象。比如:在Form2中可以加上如下的代码: Form1.Command1.Value = True 这一行语句在执行时就象用鼠标单击Form1上的Command1按钮一样,尽管Form1是未加载的。 可以引用其它窗体上定义的全局变量,在变量之前也要加上窗体的名称作为限定词。
在标准模块中定义全局的变量、过程或函数,在各个模块中引用时可以直接使用其名称,而不用加上模块作为限定词。添加全局模块,可以在“工程”菜单中选择“添加模块”,这样就可以在编辑器中出现一个标准模块,标准模块的扩展名为 .BAS。如果程序需要全局变量、过程或函数,提倡在标准模块中定义,这样可以减少出错的机会,简化代码的书写。 6.5 本章小结 本章介绍了面向对象的程序设计方法在VB中的表现形式。本章是对第5章讲过的各种各样的控件感性知识的概括,是从理论的高度认识和使用对象的一般方法。本章的内容对于后续的有关数据库应用程序设计的知识也做了理论准备。 类是对象的模板,对象是类的实例。VB中提供了丰富的类模板,在VB环境中设计程序,就是利用这些模板创建对象,也可以由程序员自己定义类。VB中的对象不具有继承性。