1、过程,第6章,前面介绍的当发生某些事件(如Click,KeyPress)时所驱动的程序段落称为“事件过程”。实际应用中,有些事件过程的代码是相同的,或一个事件过程中有许多重复而不连续的程序段落,可 将这些段落独立出来,定义成“通用过程”。“通用过程” 可以在标准模块或窗体模块中定义,供任一事件过程或通用过程随时调用。,本章要点,Sub过程,Function 过程,参数传递,变量和过程的作用域,过程的应用,Visual Basic程序的模块结构,键盘和鼠标事件过程,6.1.1 窗体模块和标准模块,VB应用程序由三种模块组成,即窗体模块(Form)、标准模块(Module)和类模块(Class),
2、这些模块分别保存在类型名为.frm、.bas和.cls的文件中。,6.1 Visual Basic程序的模块结构,6.1.1 窗体模块和标准模块,1窗体模块 窗体模块(简称窗体)是Visual Basic应用程序的基本组成部分,用于建立应用程序的用户界面。窗体模块可以包含事件过程、通用过程以及变量、常量、类型和外部过程的窗体级声明。 2标准模块 当一个应用程序含有多个窗体,且这些窗体都需要调用某一个通用过程时,就需要建立一个标准模块,在该标准模块中建立通用过程。标准模块可以包含变量、常量、自定义类型和过程的全局级(在整个应用程序范围内有效的)声明或模块级声明。 3类模块(略),6.1 Visu
3、al Basic程序的模块结构,6.1.2 事件过程和通用过程,1事件过程定义格式: Private Sub _ ()End Sub使用说明: (1)_为事件过程的过程名格式,其中为控件的Name属性值,为该控件要触发的事件名称。控件名可更改,但事件名是VB预定义好的关键字,不可更改。,6.1 Visual Basic程序的模块结构,6.1.2 事件过程和通用过程,(2)窗体是一个特殊的控件,其事件过程名为Form_,与窗体的Name属性值无关。 (3)一个事件过程与用户界面中的某个对象(一个窗体或一个控件)相联系,即事件过程是附加在所联系的对象上的,只有当一定的事件发生在特定的对象上时,事件
4、过程才会运行,因此,事件过程绝对是“私有的”(Private)。 (4)事件过程可以是有参过程,也可以是无参过程。若是有参过程,参数列在中,各参数之间用逗号隔开;若是无参过程,空括号要写。 (5)事件过程保存在窗体模块文件(.frm)中。,6.1 Visual Basic程序的模块结构,6.1.2 事件过程和通用过程,2通用过程在程序中使用通用过程是结构化程序设计的一个重要思想。对于那些与事件没有直接关系而且又要在多个过程中引用的程序段,最好的方式是将其定义为通用过程,供其它过程在需要时调用。通用过程有助于将复杂的应用程序分解成多个易于管理的功能模块,使应用程序更简洁、结构更清晰。通用过程有子
5、过程(Sub过程)和函数过程(Function过程)之分,子过程也称为子程序,函数过程常简称为函数。通用过程可以在窗体模块中定义,也可以在标准模块中定义。定义之后,便可供调用。,6.1 Visual Basic程序的模块结构,定义Sub过程的语句格式: Public|PrivateStaticSub () 语句序列 Exit Sub 语句序列 End Sub功能:定义一个以为名的Sub过程,Sub过程名不返回值,而是通过形式参数(形参)与实际参数(实参)的传递得到结果,调用时可得到多个参数值。,6.2 Sub过程,6.2.1 Sub过程的创建,注意: (1)的命名规则与变量名相同;(2)给出了
6、形参的类型、个数、位置。形参定义时是无值的,只有在过程被调用时,实参传送给形参后才获得相应的值。(3)中可以有多个形参,用逗号隔开,每一个参数按如下格式定义: ByValByRef变量名( )As 类型, 其中:ByVal表示当该过程被调用时,参数是按值传递的;缺省或ByRef表示当该过程被调用时,参数是按地址传递的。,6.2 Sub过程,6.2.1 Sub过程的创建,(4)若形参是数组:数组名( ) As 类型(5)Private定义的Sub过程为局部过程,只能在定义它的模块中被其它过程调用;Public(或缺省时)定义的Sub过程为公有过程,可被任何过程调用。(6)Static表示过程的局
7、部变量都是静态变量;(7)Exit Sub是退出Sub过程的语句,它常常是与选择结构(If或Select Case语句)联用,即当满足一定条件时,提前退出Sub过程。(8)过程可以无形式参数,但括号不能省略。,6.2 Sub过程,6.2.1 Sub过程的创建,Sub过程是一个通用过程,它不属于任何一个事件过程,因此它不能在事件过程中建立,通常Sub过程是在标准模块或窗体模块中建立的。,1.在窗体模块中建立方法一:打开代码窗口, 选择“工具”菜单的“添加过程”项,打开“添加过程”窗口,选择相关选项并“确定”。,6.2 Sub过程,6.2.1 Sub过程的创建,方法二:在窗体的代码窗口的其它过程之
8、外,输入过程的第一个语句,回车后系统自动写入End Sub;窗口中的“对象”框显示“通用”,“过程”框显示指定的过程名,接着输入代码。,6.2 Sub过程,6.2.1 Sub过程的创建,2.在标准模块中建立方法一: 在“工程”菜单选择“添加模块” ,在对话框的“新建”卡双击“模块”,添加一个新的模块文件并打开代码窗口;从“工具”菜单选择“添加过程”,打开“添加过程”窗口。选择相关选项并“确定”。,6.2 Sub过程,6.2.1 Sub过程的创建,方法二:在标准模块的代码窗口的其它过程之外,输入过程的第一个语句,回车后系统自动写入End Sub;窗口中的“对象”框显示“通用”,“过程”框显示指定
9、的过程名,接着输入代码。,6.2 Sub过程,6.2.1 Sub过程的创建,6.2.2 Sub过程的调用,语句格式: Call 子过程名() 或:子过程名 功能:调用一个已定义的Sub过程。,6.2 Sub过程,注意事项: (1) 中的参数必须与形参的个数、类型保持一致。(2)调用过程是把实参按出现的位置传递给对应的形参。其中,按值传递时实参的值不随形参的值变化而变化(单向传递);按地址传递时,实参的值将随形参值而改变(双向传递)。,例6-1 设计一个用于显示字符图形的窗体。显示的字符可以是“A”、“1”、“*”等不限,行数由用户输入决定,形状可以是正三角形或倒三角形。,6.2.2 Sub过程
10、的调用,6.2 Sub过程,应用程序在启动时,可以一启动就装载了窗体。如果工程中包含多个窗体,系统默认第一个建立的窗体为启动窗体。使用“工程”菜单的“工程1属性”命令打开“工程属性”对话框,可以选择其它窗体为启动窗体。,6.2.3 Sub Main过程,6.2 Sub过程,在实际应用中,启动窗体之前还需要进行一些初始化的工作,或者需要根据不同的情况,来决定装载哪一个窗体,此时,就要用到Visual Basic提供的一个特殊过程Sub Main过程,将装载窗体之前所要执行的一段代码放在Sub Main过程中,并将Sub Main过程设置为启动对象。,6.2.3 Sub Main过程,6.2 Su
11、b过程,例6-2 在例2-3的基础上添加一个标准模块,在标准模块中编写Sub Main过程,根据机器时间决定以Frml还是 Frm2作为启动窗体。,6.3.1 Function过程的定义,语句格式:Public|PrivateStaticFunction ()As Exit Function 函数名=返回值 End Function功能:定义一个以为名的Function过程,Function过程可通过形参与实参的传递得到结果,并返回一个函数值。,6.3 Function过程,注意事项: (1)的命名规则与变量名相同,但它不能与系统的内部函数或其它通用过程同名,也不能与已定义的全局变量和本模块中
12、同模块级变量同名。(2)在函数体内部,可以当变量使用,函数的返回值就是通过给赋值来实现的,在函数过程中至少要对函数名赋值一次。(3)As 是指函数返回值的类型,若省略,则函数返回变体类型值。,6.3.1 Function过程的定义,6.3 Function过程,(4)Exit Function是退出Function过程的语句,常与选择结构(If或Select Case语句)联用,即当满 足一定条件时,提前退出Function过程。(5)中的形参的定义与Sub过程完全相同。(6)Private定义的Function过程为局部过程,只 能在定义它的模块中被其它过程调用。Public定义的Funct
13、ion过程为公有过程,可被任何过程调用。(7)Static表示该函数的局部变量都是静态变量;(8)过程可以无形式参数,但括号不能省。,6.3.1 Function过程的定义,6.3 Function过程,Function过程的建立方法与Sub过程的建立方法相似:可以在窗体模块或标准模块的“代码窗口”中直接输入来建立Function过程,也可以选择“工具”菜单中的“添加过程”命令来建立Function过程,只是在选择类型时(图6-3),要选择“函数”。,6.3.1 Function过程的定义,6.3 Function过程,6.3.2 Function过程的调用,调用Function过程的语句格式
14、: 函数名() 功能:调用一个已定义的Function过程。注意: (1)中的实参与Function过程的对应形参进行参数传递,传递方法与Sub过程相同。 (2)函数调用只能出现在表达式中,其功能是求得函数的返回值。,6.3 Function过程,例6-3 设计一个窗体,输出P的值(P= ),程序的运行结果如图所示。,6.3.2 Function过程的调用,6.3 Function过程,6.4 参数传递,6.4.1 按值传递与按地址传递,1按值传递参数定义被调过程时,使用ByVal关键字指出参数是按值来传递的。按值传递参数时,主调过程的实参与被调过程的形参各有自己的存储单元,调用时主调过程的实
15、参值复制给被调过程的形参,实参与形参便断开了联系。如果在被调过程中改变了形参的值,则所做的变动不会影响实参的值。,在调用过程时,形参获得从实参传递过来的数据,此数据可能是一个具体的数值,也可能是一个变量的地址,关键取决于参数传递的方式是“传值”还是“传址”。,2按地址传递参数定义被调用过程时,参数默认按地址传递,也可使用ByRef关键字加以指定。按地址传递时,被调过程的形参得到的是主调过程的实参的地址,实参与形参共享同一存储单元。在被调过程体中对形参的任何操作都变成了对相应实参的操作,实参的值随着被调过程体内形参值的改变而改变。可见,可以利用按地址传递参数的方式,通过过程调用改变实参变量的值,
16、把所需的数据带回主调过程。当需要返回多个数据时,经常使用此方法。,6.4 参数传递,6.4.1 按值传递与按地址传递,3选用传值还是传址的基本规则(1)形参是数组,或变量是自定义类型的,只能使用传址方式。另外,若要将过程中的结果返回给主调程序,则对应的形参必须是传址方式。这时实参必须是同类型的变量名,不能是常量或表达式。(2)若形参不是以上的情况,一般应选用传值方式,这样可减少各过程之间的关联(因为在过程体内对形参的改变不会影响实参),有利于增加程序的可靠性,便于程序调试。,6.4 参数传递,6.4.1 按值传递与按地址传递,例6-4 编写两个过程,均用于实现两个数据的交换,但在参数的传递方式
17、上,一个采用传值,另一个采用传址,试比较其结果。,6.4 参数传递,6.4.1 按值传递与按地址传递,例6-5 设计一个窗体,输出A,B,C三个变量的值。,1数组作为参数 (1)形参是普通变量,实参可以是普通变量或数组元素。 (2)形参是带括号的数组名,实参也必须是带括号的数 组名。VB允许将整个数组的所有元素作为参数进行传递,在使用这种参数时,应注意:形参是数组名时,不指定数组的具体维数,但必须保留圆括号。形参是数组名时,只能采用按地址传递方式。在调用之前,被调过程的形参数组其下标的上下界是不确定的,在被调过程的代码中可用LBound和Ubound函数确定数组的下界和上界。,6.4 参数传递
18、,6.4.2 数组参数和对象参数,例6-6 定义一个函数求所有数组元素之积。调用该函数,分别求a和b两个数组中所有元素的乘积。运行界面如图所示。,6.4 参数传递,6.4.2 数组参数和对象参数,2对象作为参数以对象作为参数的过程其主要用法是,在一个通用过程中设置相同性质控件所需的属性,然后在主调过程中用不同的控件调用此过程,使得这些控件具有相同的属性设置(如,相同的大小、显示位置等)。用对象作为参数时应注意两点: (1)在定义过程时,“形参表”中形参的类型为Form或Control,其中Form表示参数是窗体对象,Control表示参数是其它控件对象。 (2)Form或Control类型的参
19、数只能使用按地址传递方式。,6.4 参数传递,6.4.2 数组参数和对象参数,例6-7 设计一个窗体,输出标签和文本框的内容,运行结果如右图所示。,6.4 参数传递,6.4.2 数组参数和对象参数,6.5.1 变量的作用域与生存期,1变量的作用域变量按其作用域可分为局部变量、窗体/模块级变量和全局变量。 (1)局部变量:在过程体内用Dim语句声明的变量,或不加声明直接使用的变量,只能在本过程中使用。 (2)窗体/模块级变量:在窗体或标准模块代码编辑窗口内的“通用声明”段使用关键字Dim或Private定义的变量。 (3)全局变量:窗体或标准模块的“通用声明”段中用Public语句声明的变量。全
20、局变量为所有窗体、模块中的所有过程所共享。,6.5 变量和过程的作用域,6.5.1 变量的作用域与生存期,6.5 变量和过程的作用域,变量的作用域及使用规则,6.5.1 变量的作用域与生存期,2变量的生存期变量的作用域是考虑变量可以在哪些过程中使用,而变量的生存期则考虑变量可以在哪段时间内使用。当一个过程被调用,系统将给该过程中的变量分配存储单元,当该过程调用结束时,是释放还是继续保留存储单元?这就是变量的生存期问题。根据生存期的不同,变量可分为 (1)动态变量:不是使用Static语句进行声明的变量。 (2)静态变量:在过程中使用Static语句声明的变量。,6.5 变量和过程的作用域,例6
21、-8 变量作用域示例。,例6-9 在窗体上依次输出1,1+2,1+2+3,1+2+3+10的值。,6.5.1 变量的作用域与生存期,6.5 变量和过程的作用域,6.5.2 过程的作用域,在VB系统中,过程的作用域是指该过程能被调用的范围,可以分为窗体/模块级和全局级。1.窗体/模块级 窗体/模块级过程是在定义Sub或Function过程时选用了关键字Private、Static,则该过程只能被定义它的窗体模块、标准模块中的语句、过程调用。2.全局级 全局级过程在定义Sub或Function过程时选用了关键字Public(或缺省),不管是定义还是未定义该过程的窗体模块、标准模块都能调用。,6.5
22、 变量和过程的作用域,调用规则:,6.5.2 过程的作用域,6.5 变量和过程的作用域,例6-10 数制转换问题。设计一个函数过程,将一个十进制整数m转换成r(2、8或16)进制数。程序运行结果如图所示。,6.5.2 过程的作用域,6.5 变量和过程的作用域,6.6.1顺序查找与折半查找,数据查找是数据处理中最基本的问题。所谓查找是在众多已有的数据中,提取一个指定的数据,或与已知数据相关的数据。数据查找最基本的方法是顺序查找和折半查找。 1顺序查找顺序查找的算法:将众多已有的数据先存放到数组中,然后将要查找的数据与已有的数据依次逐一比较,若相同则查找成功,将其显示或打印出来;若找不到,则给出查
23、找失败信息。,6.6 过程的应用,6.6.1顺序查找与折半查找,例6-11 设某班有10名学生,已知每个学生的学号和姓名,设计一个窗体,输入任一学生的姓名,查找对应的学号,程序的运行结果如图所示。,6.6 过程的应用,2折半查找顺序查找算法简单,但效率较低。如果数据较多,用二分法查找可提高效率。使用二分法查找的前提是数组必须有序。折半查找的算法:将众多已有的数据先存放到数组中,并对数组中数据进行排序,然后根据待查找的数据的大小,判断它是在数组的前半部分还是后半部分,取其一半;再将待查找的数据与剩余部分的数据比较,再取其一半;重复多次,直到找到为止。,6.6.1顺序查找与折半查找,6.6 过程的
24、应用,例6-12 某班有10名学生,已知每个学生的学号和姓名,设计一个窗体,输入任何一个学生的学号,用“二分法”找到该学生的姓名,程序的运行结果如图所示。,6.6.1顺序查找与折半查找,6.6 过程的应用,6.6.2 数据插入与删除,插入或删除操作一般是在众多已有的有序数据中,插入或删除一个指定的数据,数据插入或删除后仍保持其有序性。这先要涉及查找问题,找到要插入的位置或要删除的数据后,才能进行插入或删除操作。算法:将众多已有的数据先存放到数组中,并对数组中数据进行排序,然后根据待插入的数据的大小,确定插入位置;在插入数据之前,先将数组元素个数增1,再将要插入的位置及其之后的数据向后移动;最后
25、将待插入的数据插入到指定位置。删除找到的数据后,被删除数据之后的所有数据要向前移动一个元素位置。,6.6 过程的应用,6.6.2 数据插入与删除,例6-13 设某班级现有学生5人,本学期因为专业调整,有学生转出本专业,也有外专业转入,设计一个窗体,对人员调整进行处理,并列出调整后的名单。,6.6 过程的应用,1过程的嵌套调用在第四章我们了解到If语句、循环语句等都可以嵌套,形成一种多分支结构和多重循环结构,以解决较复杂的问题。对过程而言,Visual Basic规定,过程不能嵌套定义,但可以嵌套调用,即在一个过程中可以调用另一个过程,这个被调用过程又可以调用其它的过程,形成任意深度的调用层次。
26、,6.6 过程的应用,6.6.3嵌套与递归,例6-14 利用公式 近似计算自然对数e的值。结果如图所示。,6.6 过程的应用,6.6.3嵌套与递归,6.6 过程的应用,6.6.3嵌套与递归,2.过程的递归调用 如果一个过程中必有一个语句用于调用过程自身,从而实现自我的嵌套,这样的过程就称为递归过程。递归算法分为两个阶段:第一个阶段是“递推”,即把求“N”的解表示为求“N1”的解,而“N1”的解不知道,还要“递推” 到求“N2”的解, ,直到求出已知的解;第二个阶段是“回推”,即依靠“已知”的解推算出“上一个”解,再依靠“上一个”解推算出上“上一个”解, ,直到求出“N”的解。,例6-15 设计
27、一个窗体,用递归方法编写函数过程,求fact(n)= n! 分析:求n!可以用一个循环语句实现,但如果要用递归方法解决,就必须先给出递归公式:1 当n0fact(n)=n*fact(n-1) 当n0,6.6 过程的应用,6.6.3嵌套与递归,由上例可见,实现递归需要两个条件: (1)能够找到递归公式; (2)要有递归结束条件及结束时的值。递归过程的过程体一般由两个或两个以上的分支构成,其中至少有一个分支是非递归的(即有递归结束条件及结束时的值),并且递归分支的参数应朝非递归分支的方向发展。,6.6 过程的应用,6.6.3嵌套与递归,例6-16 用递归方法求解著名的汉诺塔(Tower of Ha
28、noi)问题。如图6-22所示,有n个圆盘,由A柱借助于B柱移到C柱。在圆盘移动时要遵守两个规则,一是每次只能移动一个圆盘,二是较小的圆盘一定在较大的圆盘之上。编写一个程序,输出将n个圆盘从A柱移到C柱的移动顺序。,A柱 B柱 C柱,6.6 过程的应用,6.6.3嵌套与递归,6.7.1 键盘事件,6.7 键盘和鼠标事件过程,1KeyPress事件在程序运行过程中,当用户按下并释放键盘上一个会产生ASCII码的按键时产生KeyPress事件。KeyPress事件的语法如下: Private Sub Form_KeyPress(KeyAscii As Integer) (窗体的事件过程代码) En
29、d Sub Private Sub Object_KeyPress(Index AsInteger, KeyAscii As Integer) (控件的事件过程代码) End Sub,6.7.1 键盘事件,6.7 键盘和鼠标事件过程,例6-17 设计一个窗体,控制窗体上的文本框Text1只能接收从键盘输入的英文字母,并且将输入的英文字母一律以大写的形式显示在Text1中,为了方便对照,把原按键字符显示在Text2中,结果如图所示。,6.7.1 键盘事件,6.7 键盘和鼠标事件过程,2KeyDown事件和KeyUp事件在程序运行过程中,当按下键盘上的任一个键时,则产生KeyDown事件,而当放开
30、该键时则产生KeyUp事件。对那些不能被KeyPress识别的按键(对于方向键、编辑键、功能键等不会产生ASCII码的按键,KeyPress事件不会发生),应当使用KeyDown和KeyUp事件过程来处理。,6.7.1 键盘事件,6.7 键盘和鼠标事件过程,KeyDown和KeyUp事件的语法雷同,以KeyDown为例: Private Sub Form_KeyDown(KeyCode As Integer,Shift As Integer) (窗体的KeyDown事件过程代码) End Sub Private Sub Object_KeyDown(Index As Integer, KeyC
31、ode As Integer,Shift AsInteger) (对象的KeyDown事件过程代码) End Sub,6.7.1 键盘事件,6.7 键盘和鼠标事件过程,注意: (1)KeyPress事件的KeyAscii参数返回与按键相对应的ASCII码。KeyDown和KeyUp事件的KeyCode参数返回键盘的物理状态,即该键的扫描码,其值只与按键在键盘上的物理位置有关。请对照:,6.7.1 键盘事件,6.7 键盘和鼠标事件过程,(2)Index是一个整数,用来唯一标识一个在控件数组中的控件。 (3)Shift参数是一个3位二进制整数,标明在该事件发生时是否还同时按了Shift、Ctrl和
32、Alt这3个控制键。3位二进制数的最低位对应Shift,中间位对应Ctrl,最高位对应Alt。对应位为1表示相应键被按下,为0表示该键未被按下。,6.7.1 键盘事件,6.7 键盘和鼠标事件过程,例6-18 设计一个窗体,显示按键的KeyAscii码与KeyCode码,程序的运行结果如左图所示。,例6-19 在窗体上用Image控件显示一幅图片,用键盘上的、方向键移动该图片。,6.7.2 鼠标事件,6.7 键盘和鼠标事件过程,1. 鼠标指针Visual Basic中处理鼠标指针主要是通过MousePointer和MouseIcon两个属性的设置完成的,大部分控件都具有这两个属性。 (1) Mo
33、usePointer属性该属性可以用来定义显示各种鼠标指针。格式:对象名称.MousePointer=设定值 MousePointer属性可以取17种预定义整数值。其中设定值为015时分别对应16种预定义的指针,如表6-4所示。,6.7.2 鼠标事件,6.7 键盘和鼠标事件过程,(2)MouseIcon属性当MousePointer属性值被设定成99时,还可以利用MouseIcon属性自定义鼠标指针。该属性可以把鼠标指针设置成一个自定义图标(来自某一个图标文件)。MouseIcon属性值的设定既可利用属性窗口在设计时指定,也可在运行时通过语句指定。用语句指定的语法格式有以下两种: 对象名.Mo
34、useIcon=LoadPicture(PathName) 对象名.MouseIcon=另一对象名.Picture,6.7.2 鼠标事件,6.7 键盘和鼠标事件过程,例6-20 窗体上有一个图像控件和一个定时器控件。设置图像的鼠标指针,使鼠标指针指向图像时成为下图所示的手形指针。当单击图像时窗体中的鼠标指针成为系统忙指针,然后每隔0.5秒激发一次定时器事件,当调用5次定时器事件过程后停止定时器事件,同时窗体的鼠标指针恢复为默认指针。,6.7.2 鼠标事件,6.7 键盘和鼠标事件过程,2. 鼠标事件 除了前面介绍的Click事件和DblClick事件外,还可通过MouseMove、MouseDo
35、wn和MouseUp事件使应用程序对鼠标位置及状态的变化做出响应。以MouseMove为例,其语法格式为: Private Sub Object_MouseMove(Index As Integer,Button As Integer, Shift As Integer,x As Single, y As Single) (对象上MouseMove事件过程代码) End Sub,6.7.2 鼠标事件,6.7 键盘和鼠标事件过程,各参数的含义如下: (1)Oblect是一个具有鼠标事件的对象(包括窗体)。 (2)Button为一个整数,它反映被按下的鼠标按键。Button=1,左键被按下;But
36、ton=2,右键被按下;Button=4,中间键被按下;Button=0,无按键被按下。 (3)Shift为一个整数,其含义和设置值同键盘事件。 (4)x和y指定鼠标当前位置,其值由对象的坐标系统 确定。,6.7.2 鼠标事件,6.7 键盘和鼠标事件过程,例6-21 利用MouseMove事件结合绘图方法,在鼠标移动时画图。,6.7.2 鼠标事件,6.7 键盘和鼠标事件过程,例6-22 结合MouseMove、MouseUp和MouseDown事件,设计一个直接用鼠标画图的简单画图程序,实现如下功能:鼠标任意按键被按下时启动绘图状态,当用户按下鼠标左键并移动时可以画出宽度为2的细点,按下鼠标右键并移动时可以画出宽度为6的粗点,当鼠标按键弹起时,禁止绘图功能。,本章习题,1.(2)(6)(10)2.3.4.(1)(7) (10),