VB第九章.txt铁饭碗的真实含义不是在一个地方吃一辈子饭,而是一辈子到哪儿都有饭吃。就算是一坨屎,也有遇见屎壳郎的那天。所以你大可不必为今天的自己有太多担忧。第9章过程
Visual Basic应用程序是由过程组成(如前面的各种事件过程)的。在用Visual Basic设计应用程序时,除了定义常量和变量外,全部工作就是编写过程。Visual Basic中的过程可以看作是编写程序的功能模块。
在前面的各章中,已多次见过事件过程,这样的过程是当发生某个事件(如Click, Load, Change)时,对该事件作出响应的程序段,这种事件过程构成了Visual Basic应用程序的主体。
有时候,多个不同的事件过程可能需要使用一段相同的程序代码,因此可以把这一段代码独立出来,作为一个过程,这样的过程叫做“通用过程”(general procedure)它可以单独建立,供事件过程或其他通用过程调用。 在Visual Basic中,通用过程分为两类,即子程序过程和函数过程,前者叫做Sub过程,后者叫做Function过程。 9.1 Sub过程
Visual Basic提供了与Pascal, C, Ada等语言类似的子程序调用机制,即子程序过程和函数过程(C语言全由函数组成)。为了便于区分,在今后的叙述中,我们把由Sub ...End Sub定义的子程序叫做子程序过程或Sub过程,而把由Function ... End Function定义的函数叫做函数过程或Function过程。 9.1.1建立Sub过程 1.定义Sub过程
通用Sub过程的结构与前面多次见过的事件过程的结构类似。一般格式如下: [Static][Private][Public]Sub过程名[(参数表列)] 语句块 [Exit Sub] [语句块] End Sub
用上面的格式可以定义一个Sub过程,例如: Private Sub Subtest()
Print \这是一个sub过程\End Sub
Private Sub Form_click()
Print \这是窗体的单击鼠标事件\ Subtest '调用sub子过程 End Sub 说明:
(1) Sub过程以Sub开头,以End Sub结束,在Sub和End Sub之间是描述过程操作的 语句块,称为“过程体”或“子程序体”。格式中各参量的含义如下:
①Static指定过程中的局部变量在内存中的默认存储方式。如果使用了Static则 过程中的局部变量就是\型的,即在每次调用过程时,局部变量的值保持不变; 如果省略\则局部变量就默认为“自动”的,即在每次调用过程时,局部变量被 初始化为0或空字符串。Static对在过程之外定义的变量没有影响,即使这些变量在过程 中使用。
②Private:表示Sub过程是私有过程,只能被本模块中的其他过程访问,不能被其他 模块中的过程访问。
③Public表示Sub过程是公有过程,可以在程序的任何地方调用它。各窗体通用的 过程一般在标准模块中用Public定义,在窗体层定义的通用过程通常在本窗体模块中使用, 如果在其他窗体模块中使用,则应加上窗体名作为前缀。
④过程名:是一个长度不超过255个字符的变量名,在同一个模块中,同一个变量名 不能既用作Sub过程名又用作Function过程名。
⑤参数表列:含有在调用时传送给该过程的简单变量名或数组名,各名字之间用逗号 隔开。“参数表列”指明了调用时传送给过程的参数的类型和个数,每个参数的格式为: [ByVal]变量名[()][As数据类型] 这里的“变量名”是一个合法的Visual Basic变量名或数组名,如果是数组,则要在数组名后加上一对括号。“数据类型”指的是变量的类型,可以是Integer, Long, Single, Double, String, Currency, Variant或用户定义的类型。如果省略\数据类型”,则默认为Variant. “变量名”前面的\是可选的,如果加上\则表明该参数是“传值”(Passed by Value)参数,没有加\(或者加ByRef)的参数称为“引用”(Passed by Reference)参数。有关参数的传送问题将在9.3节介绍。 在定义Sub过程时,“参数表列”中的参数称为“形式参数”,简称“形参”,不能用 定长字符串变量或定长字符串数组作为形式参数。不过,可以在调用语句中用简单定长字 符串变量作为“实际参数”,在调用Sub过程之前,Visual Basic把它转换为变长字符串 变量。 (2) End Sub标志着Sub过程的结束。为了能正确运行,每个Sub过程必须有一个End Sub 子句。当程序执行到End Sub时,将退出该过程,并立即返回到调用语句下面的语句。此外, 在过程体内可以用一个或多个Exit Sub语句从过程中退出。 (3) Sub过程不能嵌套。也就是说,在Sub过程内,不能定义Sub过程或Function过程;不能用GoTo语句进入或转出一个Sub过程,只能通过调用执行Sub过程,而且可以嵌套调用。 下面是一个Sub过程的例子:
Sub Tryout(x As Integer, ByVal y As Integer) x=x+100 y=y*6 Print x,y End Sub
上面的过程有两个形式参数,其中第二个形参的前面有ByVal,表明该参数是一个传值参数。 过程可以有参数,也可以不带任何参数。没有参数的过程称为无参过程。例如上面的例子。对于无参过程,调用时只写过程名即可。 2.建立Sub过程
前面几章已见过如何建立事件过程。通用过程不属于任何一个事件过程,因此不能放在 事件过程中。通用过程可以在标准模块中建立,也可以在窗体模块中建立。如果在标准模块 中建立通用过程,可以使用以下两种方法: 第一种方法,操作步骤如下: (1)执行“工程/添加模块”,打开“添加模块”对话框,在该对话框中选择“新建”选项卡,然后双击“模块”图标,打开模块代码窗口。
(2)执行“工具”菜单中的“添加过程”命令,打开“添加过程”对话框,如下图 所示。
(3)在“名称”框内输入要建立的过程的名字(例如Tryout).
(4)在“类型”栏内选择要建立的过程的类型,如果建立子程序过程,则应选择“子程 序”;如果要建立函数过程,则应选择“函数”。
(5)在“范围”栏内选择过程的适用范围,可以选择“公有的”或“私有的”。如果选 择“公有的”,则所建立的过程可用于本工程内的所有窗体模块;如果选择“私有的”,则所 建立的过程只能用于本标准模块。
(6)单击“确定”按钮,回到模块代码窗口,如下图。
此时可以在Sub和End Sub之间键入程序代码(与事件过程的代码输入相同)。
第二种方法:执行“工程”菜单中的“添加模块”命令,打开模块代码窗口,然后键入 过程的名字。例如,键入“Sub Tryout() \按回车键后显示: Sub Tryout()
End Sub
即可在Sub和End Sub之间键入程序代码。
在模块代码窗口中,通用过程出现在“对象”框的“通用”项目下,其名字可以在“过 程”框中找到。
如果在窗体模块中建立通用过程,则可双击窗体进入代码窗口,在“对象”框中选择“通 用”,在“过程”框中选择“声明”,直接在窗口内键入“Sub Tryout()”,然后按回车键,窗口内显示:
Sub Tryout() End Sub
此时即可键入代码。 9.1.2调用Sub过程
调用引起过程的执行。也就是说,要执行一个过程,必须调用该过程。
Sub过程的调用有两种方式,一种是把过程的名字放在一个Call语句中,一种是把过程名作为一个语句来使用。
1.用Call语句调用Sub过程 格式:Call过程名[(实际参数)]
Call语句把程序控制传送到一个Visual Basic的Sub过程。用Call语句调用一个过程时,如果过程本身没有参数,则“实际参数”和括号可以省略;否则应给出相应的实际参数,并把参数放在括号中。“实际参数”是传送给Sub过程的变量或常数。例如: Call Tryout(a,b)
2.把过程名作为一个语句来使用
在调用Sub过程时,如果省略关键字Call,就成为调用Sub过程的第二种方式。与第 一种方式相比,它有两点不同: (1)去掉关键字Call;
(2)去掉“实际参数”的括号。 例如:
Tryout a,b 下面举两个例子。
例9.1编写一个计算矩形面积的Sub过程,然后调用该过程计算矩形面积。
程序如下:
Sub RecArea (Rlen, Rwid) Dim Area
Area=Rlen*Rwid
MsgBox \”& Area End Sub
Sub Form Click() Dim A, B
A=val(InputBox(\ B=val(InputBox(\ RecArea A, B End Sub
通用过程RecArea用来计算并输出矩形的面积,它有两个形参,分别为矩形的长和宽。在 Form Click事件过程中,从键盘上输入矩形的长和宽,并用它们作为实参调用RecArea过 程。在该例中,使用的是第二种方式调用Sub过程。
例9.2编写一个用来延迟指定时间(秒)的Sub过程。调用这个过程,按指定的时间间 隔显示若干行信息。
用For---Next循环可以实现时间延迟,但很不精确。这里用Visual Basic的内部函数Timer来编写较为精确的时间延迟过程。
Timer函数返回系统时钟从午夜开始计算的秒数,把Timer加上需要延迟的时间(秒)作为循环结束的时间,当Timer超过这个时间时结束循环,即停止时间延迟。用这种方法可以得到精确的时间延迟。 程序如下:
Static Sub DelsyLoop(DelsyTime)
Const SecondsInDay=24&*60&*60& LoopFinish=Timer+DelsyTime If LoopFinish>SecondsInDay Then
LoopFinish=LoopFinish一SecondsInDay Do While Timer>LoopFinish Loop End If
Do While Timer<LoopFinish Loop End Sub
Sub Form_Click()
Fontsize=12
Print”现在输出第一行., Print’.等待5秒钟??” DelsyLoop 5 Print
Print”输出第二行”
Print”等待10秒钟??” Call DelsyLoop(10) Print
Print”输出第三行.” End Sub
用上面的DelayLoop过程可以延迟指定的时间,调用时用需要延迟的时间(秒)作为实参。 例如:
DelayLoop 5
可以延迟5秒。在一般情况下,Timer比LoopFinish要小,因此可以用 Do While Timer<LoopFinish Loop
来控制时间延迟。但是,如果时间延迟从午夜前开始, 到午夜后才结束,则Timer从0开始起算,在这种情况 下,必须用
Do While Timer>LoopFinish Loop
来控制时间延迟。过程中对这两种情况都考虑到了。 程序运行后,单击窗体,显示第一行信息,5秒钟后 显示第二行信息,再过10秒钟显示第三行信息。 9.1.3通用过程与事件过程
事件过程也是Sub过程,但它是一种特殊的Sub过程,它附加在窗体和控件上。一个 控件的事件过程由控件的实际名字(Name属性)、下划线和事件名组成;而窗体事件过程由 \”、下划线和事件名组成。也就是说,窗体的事件过程不能由用户任意定义,而是由 系统指定。控件事件过程的一般格式为:
[Private | Public] Sub控件名_事件名(参数表) 语句组 End Sub
窗体事件过程的一般格式为:
[Private | Public]Sub Form_事件名(参数表) 语句组 End Sub
可以看出,除了名字外,控件事件过程与窗体事件过程的格式基本上是一样的。在大多数情 况下,通常是在事件过程中调用通用过程。实际上,由于事件过程也是过程(Sub过程),因 此也可以被其他过程调用(包括事件过程和通用过程)。
通用过程可以放在标准模块中,也可以放在窗体模块中,而事件过程只能放在窗体模块 中,不同模块中的过程(包括事件过程和通用过程)可以互相调用。当过程名惟一时,可以直接通过过程名调用;如果两个或两个以上的标准模块中含有相同的过程名,则在调用时必须用模块名限定,其一般格式为: 模块名.过程名(参数表)
一般来说,通用过程(包括Sub过程、Function过程)之间、事件过程之间、通用过程与事件过程之间,都可以互相调用。为了说明这一点,举一个例子。 按以下步骤操作:
(1)启动Visual Basic在窗体(Forml)上画两个命令按钮,把Caption属性分别设置为 \”和“Forml-Command2”。在该窗体模块中编写如下通用过程和事件过程: Public Sub ProceQ MsgBox’.这是第一个窗体模块中的通用过程” End Sub