第五章 过程和函数
对于复杂的程序,结构化程序设计就是对一个复杂的问题采用“分而治之”的策略——模块化,把一个较大的程序划分成若干个模块,每个模块只完成一个或者若干个功能。VB也是如此,Visual Basic把程序按功能分为多个模块。每个模块的代码中又分为相互独立的过程,每个过程完成一个具体特定的任务。使用“过程”不仅是实现结构化程序设计思想的重要方法,而且是避免代码重复,便于程序调试维护的一个重要手段。在Visual Basic中就是使用子过程或函数过程来构建应用程序。
5.1 VB应用程序结构
在建立VB应用程序时,应先设计代码的结构。VB应用程序的结构通常如图5-1所示。
图5-1 VB应用程序结构图
VB将代码存储在3类不同的模块中:窗体模块,标准模块和类模块,如图5-2所示。在这3类模块中都可以包含常量和变量的声明以及Sub、Function过程。它们形成了工程的一种模块层次结构,可以较好地组织工程,同时也便于代码的维护。通过VB环境的工程资源管理器窗口可以清楚地看到一个工程中的模块层次结构。详见1.3中图1-9。
图5-2 工程中的模块
5.1.1 窗体模块
每个窗体对应一个窗体模块,窗体模块包含窗体及其控件的属性设置、窗体变量的说明、事件过程、窗体内的通用过程、外部过程的窗体级声明。窗体模块保存在以.frm为扩展名的文件中。默认时应用程序中只有一个窗体,因此有一个以.frm为扩展名的窗体模块文件。如果应用程序有多个窗体,就会有多个.frm为扩展名的窗体模块文件。
5.1.2 标准模块
简单的应用程序通常只有一个窗体,这时所有的代码都放在该窗体模块中。而当应用程序庞大而复杂时,就需要多个窗体。在多窗体结构的应用程序中,有些程序员创建的通用过程需要在多个不同的窗体中共用,为了不在每个需要调用该通用过程地窗体重复键入代码,就需要创建标准模块,标准模块包含公共代码的过程。
标准模块保存在扩展名为.bas的文件中,缺省时应用程序不包含标准模块。标准模块可以包含公有或模块级的变量、常量、类型、外部过程和全局过程的全局声明或模块级声明。缺省时,标准模块中的代码时公有的,任何窗体或模块的事件过程或通用过程都可以调用它。在许多不同的应用程序中可以重用标准模块,在标准模块中可以定义通用过程,但不可以定义事件过程。
5.1.3 类模块
在VB中,类模块是面向对象编程的基础,文件以.Cls为扩展名。程序员在类模块中编写代码建立新对象,这些新对象可以包含自定义的属性和方法,可以在应用程序中使用。类模块与标准模块的不同之处在于标准模块仅仅含有代码,而模块既含有代码又含有数据。
5.1.4 VB过程分类 1. 子过程
1) 事件过程
事件过程由VB自行声明,附加在窗体和控件上,用户不能增加或删除。当用户对某个对象发出一个动作时,Windows会通知VB产生了一个事件,VB会自动地调用与该事件相关的事件过程。事件过程只能放在窗体模块中。
事件过程的常用格式如下:
Private Sub <对象名>_<事件名( [<形参表>] )> <语句系列> End Sub
2) 通用过程
通用过程由用户定义或删除修改,可以放在标准模块中,也可以放在窗体模块中,其格式如下:
[Private|Public] Sub <过程名>(<参数表>) <语句系列> End Sub
2. 函数过程
1) 系统函数
VB为了简化程序设计,提供了许多内部函数供设计者调用,如Abs( ),Int( ),ASC( ),MID( )等。常用系统函数的使用在本书的第二章有详细介绍。
2) 用户自定义函数
除了有固定功能的系统函数之外,还允许用户编写自己的函数过程,被称为用户自定义函数,格式如下:
[Private|Public] Function <自定义函数过程名>(<参数表>) [As <类型>] <语句> End Function
5.2子过程SUB的定义和调用
5.2.1创建子过程
建立通用过程有两种方法:直接在“代码”编辑窗口中输入过程代码或使用“添加过程”对话框。
1.在“代码”编辑窗口中输入
在“代码”编辑窗口中,把光标定位在已有过程的外面(即通用声明段),然后按如下格式输入通用过程:
[Private|Public] [Static] Sub <过程名>([<形参表>])
<语句系列>
[Exit Sub] [<语句系列>] End Sub 说明:
1)Public|Private
可以将子过程放入标准模块、类模块和窗体模块中。按照缺省规定,所有模块中的子过程为Public(公有的),这样在应用程序中可随处调用它们。如果选用Private,则只有该过程所在模块中的程序才能调用该过程。
2) Static
若使用Static关键字,则该过程中的所有局部变量的存储空间只分配一次,切这些变量的值在整个程序运行期间都存在,即在每次调用该过程时,各局部变量的值一直存在;若省略Static,过程每次被调用时重新为其变量分配存储空间,当该过程结束时释放其变量的存储空间。
3) 过程名
过程名的命名规则与变量名相同,长度不超过40个字符。一个过程名只能有唯一的名字,在同一模块中,同一名称不能既作Sub过程名又作Function函数过程名。
4) 语句系列
是过程的过程体,语句系列中可以用一个或多个Exit Sub语句从过程中退出。 5) 形参表
形参表中的语法为:
[ByVal] 参数名1 [As 类型名],[ByVal] 参数名2 [As 类型名],…,
其中ByVal表明该参数是值传递方式。
形参表中出现的参数称为形式参数,简称形参。它并不代表一个实际的存在变量,在调用此过程时,存储对应实参传递过来的确定的值。类似于变量声明,它指明了从调用过程传递给被调过程变量的个数和类型。各变量名之间用逗号分隔,其中的形式参数被缺省为具有Variant数据类型,但建议将形参声明一个指定的数据类型。
2.使用“添加过程”对话框
使用“添加过程”对话框建立过程的步骤为: (1) 打开要添加过程的代码编辑窗口。
(2) 执行“工具”菜单中的“添加过程”命令,打开“添加过程”对话框,如图5-3所示。
图5-3 过程添加对话框
(3) 在“名称”文本框中输入过程名。从“类型”中选择“子程序”类型。从“范围”组中选择范围,相当于使用Public或Private关键字。 (4) 单击“确定”按钮。
使用这个方法建立了一个过程模板,可以在模板上添加过程体代码。
5.2.2调用子过程
SUB过程可以被其它过程(包括事件过程和通用过程)调用。每次调用过程都会执行Sub和End Sub之间的语句系列。Sub过程以Sub开始,以End Sub结束。当程序遇到End Sub时,将退出过程,并立即返回到调用语句的后续语句中。
1.调用方法
调用Sub过程有两种方法:
(1) 使用Call语句:Call <过程名> ([<实参表>]) (2) 直接使用过程名:<过程名> ([<实参表>])
2.使用说明
(1) <实参表>是实际参数表,实参必须用圆括号括起,参数与参数之间用逗号分隔。
(2) 当用Call语句调用执行过程时,若无实参,其过程名后圆括号不能省略,若有参数,则参数必须放在括号之内。
(3) 若省略Call关键字,则过程名后不能加括号,若有参数,则参数直接跟在过程名之后,参数与过程名之间用空格分隔,参数与参数之间用逗号分隔。 例如,以下两个语句都调用Recarea过程: Call Recarea(6,7) Recarea 6,7
3.实例应用
【例5.1】编写一个计算矩形面积的Sub过程,然后调用该过程计算矩形面积。 Private Sub Form_Click() Dim A As Single, B As Single