End Sub
上述程序把整个数组传送到通用过程中。数组在事件过程(主程序)中定义,名为Values 在实参表中写作Values();在通用过程的形参表中,数组名写作P().当调用过程时,就把 主程序中的数组Values()作为实参传送给通用过程中的数组P().程序的输出结果为: 1 8 27 64 125
(2)如果不需要把整个数组传送给通用过程,可以只传送指定的单个元素,这需要在数 组名后面的括号中写上指定元素的下标。例如: Dim test_array() As Integer
Static Sub Sqval(a) a = Sqr(Abs(a)) End Sub
Sub Form_Click()
ReDim test_array(1 To 5, 1 To 3) test_array(5, 3) = -36 Print test_array(5, 3)
Call Sqval(test_array(5, 3)) Print test_array(5, 3) End Sub
该例中“Call Sqval(test array(5, 3))”语句把数组test array第五行第三列的元素送到过程Sqval .在调用过程Sqval之后,改变了test array(5,3)的值。程序的输出结果为: -36 6
(3)前一章介绍的LBound和UBound函数常用来确定传送给过程的数组的大小。用 LBound函数可以求出数组的最小下标值,而用UBound函数可以求出数组的最大下标值, 这样就能确定传送给过程的数组中各维的上下界。例如: Static Sub Printout (a())
For row=LBound(a, 1)To UBound(a, 1) For cot=LBound(a, 2) To UBound(a, 2) Print a(row, cot) Next cot Next row End Sub
上述过程用LBound函数把row和col初始化为数组a中各维的下界,同时用UBound函数 把For循环执行的次数限制为数组元素的个数。
例9.9编写一个Function过程,求数组的最大值。 求数组最大值的通用过程如下:
Private Function FindMax (a() As Integer)
Dim Start As Integer, Finish As Integer, i As Integer Start=LBound(a)
Finish=UBound(a) Max=a(Start)
For i=Start To Finish
If a(i)>Max Then Max=a(i) Next i FindMax=Max End Function
该过程先求出数组的上界和下界,然后从整个数组中找出最大值。过程中的数组是一个形式 参数,可以在下面的事件过程中调用该过程: Sub Form Click()
ReDim b(4) As Integer b(1)=30 b(2)=80 b(3)=234 b(4)=874
c=FindMax(b()) Print c End Sub
程序执行后,单击窗体,输出结果为874.
以上介绍了Visual Basic过程的参数传送,现补充说明以下几点:
(1)当把常数和表达式作为实参传送给形参时,应注意类型匹配。通常有以下3种情况: ①字符串常数和数值常数分别传送给字符串类型的形参和数值类型的形参。
②当传送数值常数时,如果实参表中的某个数值常数的类型与Function或Sub过程形 参表中相应的形参类型不一致,则这个常数被强制变为相应形参的类型。
③当作为实参的数值表达式与形参类型不一致时,通常也强制变为相应的形参的类型。 (2)记录是用户定义的类型,传送记录实际上是传送记录类型的变量,一般步骤如下: ①定义记录类型。例如: Type Stockltem
PartNumber As String*8 Description As String*20 UnitPrice As Single Quantity As Integer End Type
②定义记录类型变量。例如:
Dim StockRecord As StockItem
③调用过程,并把定义的记录变量传送到过程。例如: Call FindRecord(StockRecord)
④在定义过程时,要注意形参类型匹配。例如: Sub FindRecord(RecordVar As StockItem)
(3)单个记录元素的传送。传送单个记录元素时,必须把记录元素放在实参表中,写成 “记录名.元素名”的形式。例如:
Sub PrintPriceTeg(Desc As String, Price As Single) End Sub
Dim StockRecord As StockItem
Call PrintPriceTeg(StockRecord.Description,StockRecord.UnitPrice) 9.4可选参数与可变参数 Visual Basic 6.0提供了十分灵活和安全的参数传送方式,允许使用可选参数和可变参数。在调用一个过程时,可以向过程传送可选的参数或者任意数量的参数。
9.4.1可选参数
在前面的例子中,一个过程中的形式参数是固定的,调用时提供的实参也是固定的。也 就是说,如果一个过程有3个形参,则调用时必须按相同的顺序和类型提供3个实参。在VisualBasic 6.0中,可以指定一个或多个参数作为可选参数。例如,假定建立了一个计算两个数的乘积的过程,它能可选择地乘以第三个数。在调用时,既可以给它传送两个参数,也可以给它传送3个参数。
为了定义带可选参数的过程,必须在参数表中使用Optional关键字,并在过程体中通 过IsMissing函数测试调用时是否传送可选参数。例如:
Sub Multi (fir As Integer, sec As Integer, Optional third) N=fir*sec
If Not IsMissing(third) Then N=n*third End If Print n End Sub
上述过程有3个参数,其中前两个参数与普通过程中的书写格式相同,最后一个参数没有指 定类型(使用默认类型Variant)而是在前面加上了\”,表明该参数是一个可选参数。在过程体中,首先计算前两个参数的乘积,并把结果赋给变量n,然后测试第三个参数是否存在,如果存在,则把第三个参数与前两个参数的乘积相乘,最后输出乘积。
在调用上面的过程时,可以提供两个参数,也可以提供3个参数,都能得到正确的结果。 例如,如果用下面的事件过程调用: Private Sub Form_Click() Multi 10,20 End Sub
则结果为200;而如果用下面的过程调用: Private Sub Form_Click() Multi 10,20,30 End Sub 则结果为6000。
上面的过程只有一个可选参数,也可以有两个或多个。但应注意,可选参数必须放在参 数表的最后,而且必须是Variant类型。
可选参数过程通过Optional指定可选的参数,其类型必须是Variant;通过Ismissing函数测试是否向可选参数传送实参值。IsMissing函数有一个参数,它就是由Optional指定的形参的名字,其返回值为Boolean类型。在调用过程时,如果没有向可选参数传送实参,则Ismissing函数的返回值为True,否则返回值为False。 9.4.2可变参数
在C语言中,通常用预定义函数printf输出数据。用该函数可以输出一个数据,也可以输出任意多个数据。输出的数据就是函数的参数,因此printf是一个可变参数函数。在VisualBasic 6.0中,可以建立与printf类似的过程。
可变参数过程通过ParamArray命令来定义,一般格式为:
Sub过程名(ParamArray数组名)
这里的“数组名”是一个形式参数,只有名字和括号,没有上下界。由于省略了变量类型, “数组”的类型默认为Variant。
前面建立的Multi过程可以求两个或3个数的乘积。下面定义的是一个可变参数过程, 用这个过程可以求任意多个数的乘积。
Sub Multi (ParamArray Numbers()) n=1
For Each x In Numbers n=n*x Next x Print n End Sub
在该过程中使用了For Each \语句,具体用法见第8章。 可以用任意个参数调用上述过程。例如: Private Sub Form_Click() Multi 2,3,4,5,6 End Sub 输出结果为720。
由于可变参数过程中的参数是Variant类型,因此可以把任何类型的实参传送给该过程。例如:
Private Sub Form Click()
Dim a As Integer,b As Long,c As Variant,d As Integer a=6:b=8 c=12:d=2 Multi a,b,c,d End Sub 9.5对象参数
和传统的程序设计语言一样,通用过程一般用变量作为形式参数。但是,和传统的程序 设计语言不同,Visual Basic还允许用对象,即窗体或控件作为通用过程的参数。在有些情况下,这可以简化程序设计,提高效率。这一节将介绍用窗体和控件作为通用过程参数的 操作。
前面已经介绍了用数值、字符串、数组作为过程的参数,以及如何把这些类型的实参传 送给过程。实际上,在Visual Basic中,还可以向过程传送对象,包括窗体和控件。 用对象作为参数与用其他数据类型作为参数的过程没有什么区别,其格式为: Sub过程名(形参表) 语句块 [Exit Sub] End Sub
“形参表”中形参的类型通常为Control或Form.注意,在调用含有对象的过程时,对象只 能通过传地址方式传送。因此在定义过程时,不能在其参数前加关键字ByVal a 9.5.1窗体参数
下面通过一个例子来说明窗体参数的使用。
假定要设计一个含有多个窗体的程序(在第13章将介绍多窗体程序设计),该程序有4 个窗体,要求这4个窗体的位置、大小都相同。
窗体的大小和位置通过Left, Top, Width及Height属性来设置。可以这样编写程序: Form1.Left = 2000 Form1.Top = 3000 Form1.Width = 5000 Form1.Height = 3000 Form2.Left = 2000 Form2.Top = 3000 Form2.Width = 5000 Form2.Height = 3000 Form3.Left = 2000 Form3.Top = 3000 Form3.Width = 5000 Form3.Height = 3000 Form4.Left = 2000 Form4.Top = 3000 Form4.Width = 5000
Form4.Height = 3000每个窗体通过4个语句确定其大小和位置,除窗体名称不同外,其他都一样。因此,可以用
窗体作为参数,编写一个通用过程:
Sub FormSet(FormNum As Form) FormNum.Left=2000 FormNum.Top=3000
FormNum. Width=5000 FormNum.Height=3000 End Sub
上述通用过程有一个形式参数,该参数的类型为窗体(Form)。在调用时,可以用窗体作为实 参。例如:
FormSet Form l
将按过程中给出的数值设置窗体Forml的大小和位置。
为了调用上面的通用过程,可以用“工程”菜单中的“添加窗体”命令建立4个窗体, 即Form l、Form2、Forma和Form4。在默认情况下,第一个建立的窗体(这里是Forml)是启动窗体。
对Forml编写如下事件过程: Private Sub Form Load() FormSet Forml FormSet Form2 FormSet Forma FormSet Form4 End Sub
对4个窗体分别编写如下的事件过程: Private Sub Form Click()
Forml.Hide’隐藏窗体Forml Form2.Show’显示窗体Form2 End Sub