第九章子函数与函数过程过程概述在VB5.0/6.0中,除了系统提供的内部函数过程和事件过程外,用户可自定义过程下列四种过程:▲“Sub”保留字开始的为子过程▲“Function”保留字开始的为函数过程“Property”保留字开始的为属性过程“Event”保留字开始的事件过程9.1子函数过程(sub过程)在VB中,的Sub子过程分为:事件过程和通用过程9.1.1事件过程(1)窗体事件的语法PrivateSubForm_事件名(参数列表)<语句组>EndSub(2)控件事件的语法PrivateSub控件名_事件名(参数列表)<语句组>EndSub9.1子函数过程(sub过程)9.1.2通用过程(Sub过程)的定义子过程的定义形式如下:[Public|Private][Static]Sub子过程名([形参表])局部变量或常数定义<语句组>[ExitSub]<语句组>EndSub说明:(1)子过程名:命名规则与变量名规则相同。子过程名不返回值,而是通过形参与实参的传递得到结果,调用时可返回多个值。(2)形式参数列表:形式参数通常简称“形参”,仅表示形参的类型、个数、位置,定义时是无值的,只有在过程被调用时,虚实参结合后才获得相应的值。(3)过程可以无形式参数,但括号不能省。(4)参数的定义形式:[ByVal|ByRef]变量名[()][As类型][,…],ByVal表示当该过程被调用时,参数是按值传递的;缺省或ByRef表示当该过程被调用时,参数是按地址传递的。9.1子函数过程(sub过程)9.1子函数过程(sub过程)例编一个交换两个整型变量值的子过程。PrivateSubSwap(XAsInteger,YAsInteger)DimtempAsIntegerTemp=X:X=Y:Y=TempEndSubPrivateSubcommand1_click()Dima%,b%a=val(inputbox(“a=“))b=val(inputbox(“b=“))print“a=“;a,”b=“,bcallswap(a,b)print“a=“;a,”b=“,bEndSub9.1子函数过程(sub过程)9.1.3子过程的建立通过“工具”菜单中的“添加过程”命令,出现“添加过程”对话框(见图6.1),选择过程类型(子过程、函数、属性、事件)及作用范围(公有的Public、私有的Private),单击确定后得到一个过程或函数定义的结构框架(模板),如:PublicSubSort()……EndSub9.1子函数过程(sub过程)9.1.4过程的调用1子过程的调用子过程名[参数列表]或Call子过程名(参数列表)说明:(1)参数列表称为实参或实元,它必须与形参保持个数相同,位置与类型一一对应。(2)调用时把实参值传递给对应的形参。其中值传递(形参前有ByVal说明)时实参的值不随形参的值变化而改变。而地址传递时实参的值随形参值的改变而改变。(3)当参数是数组时,形参与实参在参数声明时应省略其维数,但括号不能省。(4)调用子过程的形式有两种,用Call关键字时,实参必须加圆括号括起。例:调用上面定义的Swap子过程的形式:Swapa,b(省略关键字call和括号)CallSwap(a,b)9.1子函数过程(sub过程)过程调用的执行过程:PrivateSubCmdOK()……CallSwap(a,b)……Swapa,bEndSubPrivateSubSwap(x%,y%)Dimtemp%Temp=XX=YY=TempEndSub实例9.3窗体中有1个图片框和3个命令按钮(控件数组),如图。程序运行时,单击命令按钮,在图片框中画出指定数目的同心圆。9.2函数过程(Function过程)VisualBasic函数分为内部函数(sin(),sqr()等)和外部函数,外部函数是用户根据需要用Function关键字定义的函数过程,与子过程不同的是函数过程将返回一个值。9.2.1函数过程(Function过程)的定义[Public|Private][Static]Function函数名([参数列表])[As类型]局部变量或常数定义语句块[函数名=返回值][ExitFunction]语句块函数名=返回值EndFunction函数体9.2函数过程(Function过程)说明:(1)函数名:命名规则与变量名规则相同。(2)在函数体内,函数名可以当变量使用,函数的返回值就是通过对函数名的赋值语句来实现的,在函数过程中至少要对函数名赋值一次。(3)AS类型:是指函数返回值的类型,若省略,则函数返回变体类型值(Variant)。(4)ExitFunction:表示退出函数过程,常常是与选择结构(If或SelectCase语句)联用,即当满足一定条件时,退出函数过程。(5)形参数列表:形参的定义与子过程完全相同。实例9.5定义一个函数过程,用来计算1~n的和。PrivateFunctionsum(nAsInteger)AsLongfori=1tons=s+inextisum=sEndFunction调用函数过程可以由函数名带回一个值给调用程序,被调用的函数必须作为表达式或表达式中的一部分,再与其它的语法成分一起配合使用。因此,与子过程的调用方式不同,函数不能作为单独的语句加以调用。最简单的情况就是在赋值语句中调用函数过程,其形式为:变量名=函数过程名(实参列表)9.2函数过程(Function过程)9.2.2函数的调用实例9.6通过函数过程实现实例9.4的功能。9.3参数传递在调用过程时,一般主调过程与被调过程之间有数据传递,即将主调过程的实参传递给被调过程的形参,完成实参与形参的结合,然后执行被调过程体。在VB中,实参与形参的结合有两种方法:传址和传值。传址是默认的方法。两种结合方法的区分标志是“ByVal”,形参前加“ByVal”关键字时是传值,否则为传址。9.3.1传值传值的参数传递过程是:当调用一个过程时,系统将实参的值复制给形参,之后实参与形参便断开了联系。被调过程对形参的操作是在形参自己的存储单元中进行,当过程调用结束时,这些形参所占用的存储单元也同时被释放。因此在过程中对形参的任何操作都不会影响到实参。9.3.2传址传址的参数传递过程是:当调用一个过程时,它将实参的地址传递给形参。因此在被调过程体中对形参的任何操作都变成了对相应实参的操作,因此实参的值就会随形参的改变而改变。当参数是字符串或数组时,使用传址传递直接将实参的地址传递给过程,会使程序的效率提高。9.3.3数组参数的传递数组可以作为过程的参数。过程定义时,形参列表中的数组用数组名后的一对空的圆括号表示。在过程调用时,实际参数表中的数组可以只用数组名表示,省略圆括号。当用数组作为过程的参数时,进行的不是“值”的传递,而是“址”的传递。9.4过程与变量的作用域前面我们介绍了VB应用程序(通常称为工程)的组织结构,它由窗体模块、标准模块和类模块组成。VB程序代码就保存在窗体模块文件(*.Frm)、标准模块文件(*.Bas)或类模块文件(*.Cls)中。它们形成了工程的一种模块层次结构,如下图所示。9.4过程与变量的作用域9.4.1窗体模块(文件扩展名为.FRM)窗体模块。窗体模块可以包含处理事件的过程、通用过程以及变量、常数、类型和外部过程的窗体级声明。如果要在文本编辑器中观察窗体模块,则还会看到窗体及其控件的描述,包括它们的属性设置值。写入窗体模块的代码是该窗体所属的具体应用程序专用的;它也可以引用该应用程序内的其它窗体或对象。9.4.2标准模块(文件扩展名为.BAS)它们可以包含变量、常数、类型、外部过程和全局过程的全局(在整个应用程序范围内有效的)声明或模块级声明。写入标准模块的代码不必绑在特定的应用程序上,则在许多不同的应用程序中可以重用标准模块。9.4过程与变量的作用域9.4过程与变量的作用域9.4.3类模块(文件扩展名为.CLS)在VisualBasic中类模块是面向对象编程的基础。可在类模块中编写代码建立新对象。这些新对象可以包含自定义的属性和方法。实际上,窗体正是这样一种类模块,在其上可安放控件,可显示窗体窗口。9.4过程与变量的作用域概念[Public|Private]Sub子过程名([形式参数列表])…..EndSub通用子过程和函数过程既可写在窗体模块中也可写在标准模块中,在定义时可选用关键字Private(局部)和Public(全局),来决定它们能被调用的范围。9.4过程与变量的作用域按过程的作用范围来划分,过程可分为:模块级过程全局级过程1、窗体/模块级过程:加Private关键字的过程,只能被定义的窗体或模块中的过程调用。2、全局级过程:加Public关键字(或缺省)的过程,可供该应用程序的所有窗体和所有标准模块中的过程调用。9.4过程与变量的作用域总结归纳过程的定义及作用域如下表9.4过程与变量的作用域概述:在VB中,由于可以在过程中和模块中声明变量,根据定义变量的位置和定义变量的语句不同,变量可以分为:局部变量(过程级变量)窗体/模块级变量(私有的模块级变量,能被本模块的所有过程和函数使用)全局级变量(公有的模块级变量)。9.4过程与变量的作用域9.4.4过程级变量——局部变量局部变量:在过程内用声明的变量,只能在本过程中使用。在过程内部使用Dim或者Static关键字来声明的变量,只在声明它们的过程中才能被访问或改变该变量的值,别的过程不可访问。所以可以在不同的过程中声明相同名字的局部变量而互不影响。9.4过程与变量的作用域例:PrivateSubForm_Load()Dimn%n=10EndSubPrivateSubFrom_Click()Dimn%Print“n=“;nEndSub程序运行后单击窗体,其输出结果是什么?9.4过程与变量的作用域9.4.5窗体/模块级变量窗体/模块级变量:在“通用声明”段中用Dim语句或用Private语句声明的变量,可被本窗体/模块的任何过程访问。但其他模块却不能访问该变量。例如:在“通用声明”段声明如下变量:PrivatesAsStringDimaAsInteger例:Dimn%PrivateSubForm_Load()n=10EndSubPrivateSubFrom_Click()Print“n=“;nEndSub9.4过程与变量的作用域9.4.6全局变量全局变量也称公有的模块级变量,在窗体模块或标准模块的顶部的“通用”声明段用Public关键字声明,它的作用范围是整个应用程序,即可被本应用程序的任何过程或函数访问。例如:PublicaAsInteger,bAssingle9.4过程与变量的作用域3种变量声明及使用规则如下表:9.4过程与变量的作用域9.4.7静态变量(static)概念除作用域之外,变量还有存活期,在这一期间变量能够保持它们的值。在应用程序的存活期内一直保持模块级变量和全局变量的值。但是,对于Dim声明的局部变量仅当过程执行期间存在,当一个过程执行完毕,它的局部变量的值就已经不存在,而且变量所占据的内存也被释放。当下一次执行该过程时,它的所有局部变量将重新初始化。局部变量的存活期由其定义的关键词来决定。9.4过程与变量的作用域局部变量声明:Dim声明:随过程的调用而分配存贮单元,变量的初始化;过程体结束,变量的内容自动消失,存贮单元释放。Static声明,每次调用过程,变量保持上次调用结束时的值。声明形式:Static变量名[AS类型]StaticFunction函数过程名([参数列表])[As类型]StaticSub子过程名[(参数列表)]注意:过程名前加Static,表示该过程内的局部变量都是静态变量。