VB基础

  VB入门

1知识要点

1VB的特点、安装和启动

了解VB面向对象、可视化、事件驱动的特点。

2VB集成开发环境

初学者主要掌握菜单栏、工具栏、工具箱窗口、属性窗口、代码窗口、工程资源管理器窗口的使用。

3VB对象的概念,对象的属性、方法和事件三要素

4.创建VB应用程序的过程

5.掌握窗体、标签、文本框、命令按钮控件的常用属性、方法和事件的使用

6VB应用程序的构成和管理

VB应用程序的组成:一个.vbp工程文件、一个(或多个)frm窗体文件、自动产生的.frx二进制文件、还可以有.bas.cis文件(见下图)

掌握在完成一个应用程序的创建、编辑、调试后,保存时不要遗漏了某个文件;掌握在工程中添加或删除窗体的方法;区分窗体名称和窗体文件名。

7.制作安装盘

打包和展开的作用和操作过程,查看打包和展开的结果文件。

8VB帮助系统的安装和使用

VB帮助系统盘MSDN的安装;使用VB帮助最方便的方法是选中需帮助的对象,按F1键,即可显示该对象的帮助信息。

1常见错误和难点分析

1.标点符号错误

VB中只允许使用西文标点,任何中文标点符号在程序编译时产生"无效字符"错误,统在该行以红色字显示。用户在进入VB后不要使用中文标点符号。中、西文状态下标点号对照见下表所示。

中、西状态下标点符号对照

西文状态

,

.

'

"

;

_

  <

中文状态

'

"

—— 

2.字母和数字形状相似

L的小写字母"1"和数字"l"形式几乎相同、O的小写字母""与数字"0"也难以区,这在输入代码时要十分注意,避免单独作为变量名使用。

3.对象名称(Name)属性写错

在窗体上创建的每个控件都有默认的名称,用于在程序中唯一地标识该控件对象。系统为每个创建的对象提供了默认的对象名,例如,Text1Text2Command1Label1等。用户可以将属性窗口的(名称)属性改为自己所指定的可读性好的名称,如txtInputtxtOutput cmdOk等。对初学者,由于程序较简单、控件对象使用较少,还是用默认的控件名较方便。

当程序中的对象名写错时,系统显示"要求对象"的信息,并对出错的语句以黄色背景云。用户可以在代码窗口的"对象列表"框检查该窗体所使用的对象。

4Name属性和Caption属性混淆

Name属性的值用于在程序中唯一地标识该控件对象,在窗体上不可见;而Caption属性的值是在窗体上显示的内容。

5.对象的属性名、方法名写错

当程序中对象的属性名、方法名写错时,VB系统会显示"方法或数据成员未找到"的信息。在编写程序代码时,尽量使用自动列出成员功能,即当用户在输入控件对象名和句点后,系统自动列出该控件对象在运行模式下可用的属性和方法,用户按空格键或双击鼠标即可,这样既可减少输入也可防止此类错误出现。

6.变量名写错

Dim声明的变量名,在后面的使用中表示同一变量而写错了变量名,VB编译时就认为是两个不同的变量。例如,下面程序段求1~100的和,结果放在Sum变量中:

       Dim sum As  Integeri As Integer

       Sum=0

       For  i  =1  to 100

              Sum=Sun+i

       Next i

       Print Sum

显示的结果为100。原因是累加和表达式Sum=Sun+i中的右边的变量名Sum写成SunVB对变量声明有两种方式,可以用变量声明语句显式声明,也可以用隐式声明,即不声明直接使用。上述变量名的写错,系统为两个不同的变量各自分配内存单元,造成计算结果不正确。因此,为防止此类错误产生,必须对变量声明采用限制其为显式声明方式,也就是在通用声明段加Option Explicit语句。

7.语句书写位置错

VB中,除了在"通用声明"段利用Dim等对变量声明语句外,其他任何语句都应在事件过程中,否则运行时会显示"无效外部过程"的信息。若要对模块级变量进行初始化工作,则一般放在Form Load()事件过程中。

8.无意形成控件数组

若要在窗体上创建多个命令按钮,有些读者会先创建一个命令按钮控件,然后利用对该控件进行复制、粘贴,这时系统显示:

已经有一个控件为"Command1"。创建一个控件数组吗?的信息,若单击""按钮,则系统创建了名称为Command1的控件数组。若要对该控件的 Click事件过程编程,系统显示的框架是:

       Private Sub Command1_Click(Index As Integer)

       End Sub

Index表示控件数组的下标。

若非控件数组,Click事件过程的框架是:

Private Sub Command1_Click()

End Sub

请注意直到学习第四章数组前,一律不使用控件数组。

9Print方法中定位问题

定位通过TabSpc函数和最后的逗号、分号和无符号来控制。VB中通过Print方法中各参数的综合使用达到所需的结果,但初学者往往难以掌握。

(1)  Tab(n)Spc(n)的区别

Tab(n)从最左第1列开始算起定位于第n列,若当前打印位置已超过n列,则定位于下一行的第n列,这是常常定位不好出现的问题。在格式定位中,Tab用得最多。

Spc(n)从前一打印位置起空n个空格。例如,下面程序段显示了TabSpc的区别,效果如图所示。

       Private Sub Commandl_Click()

              Print "1234567890”

              Print Tab(1)"**"'Tab(2)"%%%"spc(2)"$$$$"

  End Sub

      

 

 

 (2) 紧凑格式""分号的使用

紧凑格式"",即输出项之间无间隔。但对于数值型,输出项之间系统自动空一列,而由于数值系统自动加符号位,因此,大于零的数值,实际空两列。对于字符型之间无空格。

例如,下面程序段,效果如图所示。

      

 

 

Private Sub Command1_Click()

              Print 1;-2;3

              Print"1234";"5678"

              Print"A";"B";"C";"D","E","F"

       End Sub

从该例应区分数值和字符在紧凑格式输出的差异。

10.打开工程时找不到对应的文件

一般,一个再简单的应用程序也应由一个工程.vbp文件和一个窗体.frm文件组成。工程文件记录该工程内的所有文件(窗体.frm文件、标准模块.bas文件、类模块.cls文件等)的名称和所存放在磁盘上的路径。

若在上机结束后,把文件复制到软盘上保存,但又少复制了某个文件,下次打开工程时就会显示"文件未找到"。也有在VB环境外,利用Windows资源管理器或DOS命令将窗体文件等改名,而工程文件内记录的还是原来的文件名,这样也会造成打开工程时显示"文件未找到"

解决此问题的方法:一是修改.vbp工程文件中的有关文件名:二是通过"工程"菜单的"添加窗体"中的"现存"选项,将改名后的窗体加入工程。

第二章  VB语言基础和顺序结构

2.1  知识要点

1VB程序的书写规则

(1)   VB代码书写规则

1)程序中不区分字母的大小写,Ab AB等效;

2)系统对用户程序代码进行自动转换:

l         对于VB中的关键字,首字母被转换成大写,其余转换成小写

l         若关键字由多个英文单词组成,则将每个单词的首字母转换成大写

l         对于用户定义的变量、过程名,以第一次定义的为准,以后输入的自动转换成首次定义的形式

(2)   语句书写规则

1)       在同一行上可以书写多行语句,语句间用冒号()分隔

2)       单行语句可以分多行书写,在本行后加续行符:空格和下划线  _

3)       一行允许多达255个字符

(3)   程序的注释方式

1)       整行注释一般以 Rem开头,也可以用撇号 '

2)       用撇号 ' 引导的注释,既可以是整行的,也可以直接放在语句的后面,最方便;

3 可以利用“编辑”工具栏的 “设置注释块”、“解除注释块”来将设置多行注释。

2VB提供的数据类型

VB提供了丰富的数据类型(见教程表1.3.1),每种数据类型有关键字或类型符表示,不同的数据类型占用不同的存储空间,用户可根据实际问题的需要使用合适的类型。除此数据类型外,VB还提供了构造类型,即数组和用户自定义类型(相当于记录类型)

3.变量和常量

(1) 变量

l       变量的命名规则

☆ 必须以字母或汉字开头,由字母、汉字、数字或下划线组成,长度≤255个字符;

不能使用VB中的关键字,并尽量不与VB中标准函数名同名;如:Dim Sin

VB中不区分变量的大小写,一般变量首字母用大写,其余用小写;常量全部用大写字母表示

为了增加程序的可读性,可在变量名前加一个缩写的前缀来表明该变量的数据类型。

l       变量的声明:有利用Dim等声明语句或类型符声明各种类型的变量,也可以不声明直接使用具有Variant变体类型的变量。为使程序运行安全、可靠,对使用的变量还是利用显式声明为好。

l       变量的初值:系统默认数值型变量为零、字符型变量为空(Q),对象变量为Nothing

(2) 常量

VB中,常量有三类,分别为:

·直接常量,例如,11.23&Hab0.123El"1234asd"#2000/5/5#TrueFalse

·用户自定义常量,例如,Const PI=3.14159

·VB系统提供的常量,例如,vbEmptyvbIntegervbNormal

4.运算符及优先级

       算术运算符  - ^ * / / Mod + -     由高到低

       字符运算符  +&      同级

       关系运算符  =>>=<<=<>IsLike     同级

       逻辑运算符  NotAndOrXorEqvImp       高到低

5.表达式书写及值的类型

书写规则:从左到右在-行上书写,无高低区分:表达式中的运算符可以用圆括号括起,以改变运算的优先级或增加表达式的消蜥度。不能使用方括号或花括号,圆括号可以出现多个,但要配对。

值的类型:在算术表达式中,出现不同的数据类型,向精度高的数据类型转换。

6.常用函数

VB中提供了丰富的函数,教程中按算术、字符串、日期和时间、转换,格式等分类列出了一些常用的函数,对函数完整的形式和使用举例参阅VB帮助。查阅的方法一般有两种:对已知函数名,选中函数名,按F1键:未知函数名,进入VB帮助后,通过"目录"选项卡,选择"Visual Basic文档"目录,再选择"参考"下的"语言参考"中的"函数"

7.赋值语句

赋值号"="左边只能是变量;一次只能对一个变量赋值。

8.与用户交互函数和过程

InputBox函数和MsgBox函数或过程。

 2.3  常见错误和难点分析

1.逻辑表达式书写错,在VB没有造成语法错而形成逻辑错

例如,要将数学上表示变量x在一定数值范围内如3x10,以VB的逻辑表达式表示,有的读者写成的VB表达式为:

3<=x<10

此时在其他语言中将产生语法错,而在VB中不产生语法错,程序能运行,但不管x的值为多少,表达式的值永远为True,这造成程序能正常运行的假象,其结果是不正确的。

因为在VB中,当两个不同类型的变量或常量参加运算时,有自动向精度高的类型转换的功能。例如,逻辑常量Tme转换为数值型的值为-1False0;反之数值型非0转换为逻辑型的值为True0False。同样数字字符与数值运算,转换为数值型。

例如,语句    PrintTrue+3    '显示的结果是2

       Print"123"+100      '显示的结果是223

       Print#5/1/2000#+3  '显示的结果是00-5-4

根据此原因,表达式:

       3<=x   <10

       (1)

       (2)

值的计算过程是:首先根据x的值计算3<=x,结果总为TrueFalse;然后该值(-10)10比较永远为True。正确的VB表达式书写为:

3<=x And x<10

2.同时给多个变量赋值,在VB没有造成语法错而形成逻辑错

例如,要同时给x,y,z三个整型变量赋初值1,有的读者写成如下赋值语句:

x=y=z=1

 C语言中,上述语句是可以实现同时对多个变量赋值,而在VB中规定一句赋值语句内只能给一个变量赋值,但上述语句并没有产生语法错,运行后x,y,z中的结果均为0

原因是VBy=z=1作为一个表达式,再将表达式的结果赋值给x。在VB中默认数值型变量的初值为0,根据上面错误1的分析类推,因此表达式y=z=l的结果为0,所以x赋得的值为0yz变量的值为默认值o

3.标准函数名写错

VB提供了很多标准函数,如IsNumeric()Date()LeR()等。当函数名写错时,如将 IsNumeric写成IsNummeric,系统显示"子程序或函数未定义",并将该写错的函数名选中提醒用户修改。

[提示]

如何判断函数名、控件名、属性、方法等是否写错,最方便的方法是当该语句写完后,按 Enter键,系统把被识别的上述名称自动转换成规定的首字母大写形式,否则为错误的名称。

4.数据合法性检查中引起程序的死循环

在数据输入时,经常需要对输入的数据作合法性检查,以确保程序运行的正确性。如在实验::第1题中,对输入的温度要求是数字,否则删除原输入的内容,焦点仍定位于文本柜。有关属性设置见下表,界面如图2.2.2所示,程序段如下。

2.2.1  控件有关属性

       有关控件名    TabIndex

       Text1      2

       Text2      3

       Command1     4

       Command1     5

       Private Sub Text1_LostFocus()

              If Not IsNumeric(Text1)Then

                     Text1=""

                     Text1.SetFocus

              End If

       EndSub

       Private Sub Text2_LostFocus()

              If Not IsNumeric(Text2)Then

                     Text2=""

                     Text2.SetFocus

              End If

       End Sub

当华氏温度(Text1)输入错时,焦点在Text2处不停地闪动,程序产生死循环。

原因是当Textl输入结束按Tab键,激发Textl LostFocus事件,焦点已到Text2;但当判断Textl文本框输入数据错时,执行Textl.SetFocus,使焦点从Text2拉回到Textl;而又激发Text2_LostFocus事件,此时并没有判断Text2文本框输入数据错,又执行 Text2.SetFocus,使焦点从Text1拉回到Text2,如此交错造成死循环。

而当摄氏温度(Text2)输入错时,程序正常运行。因为当Text2输入结束按Tab键,焦点已到Commanl,因此不会产生死循环。

解决Text1输入错时死循环的问题,只要把Private Sub Text2_LostFocus()事件的If表达式If Not IsNumeric(Text2)Then改为:IfText2<>""And Not isNumeric(Text2)Then即可。

5.如何终止死循环

当编写程序时考虑不周到,产生死循环(尤其使用第四章介绍的循环结构)时,只要同时按Ctrl+Break键就町终止死循环,找出死循环的原因,修改程序。

6.声明局部变量和窗体级变量的问题

VB程序中,除了大量的控件对象外,还要使用一些变量,暂时存放一些中间结果。这些变量的声明可以放在过程外的"通用声明"(称为窗体级变量,在教程的3.7.4节介绍),也可以放在过程中(称为局部变量),怎样安置这些变量,初学者觉得有点头疼。两者区别:窗体级变量在本窗体的所有过程中均可使用:而局部变量仅在变量所在的过程中可使用,也即随着本过程的执行而分配存储空间,当执行到EndSub语句,分配的内存空间回收,变量的值也丢失。

具体对实验二第2题来说,在方法一中窗体内有四个过程,共同要用到三个变量a,b,c,因此这些变量的声明应在"通用声明"段,否则Click事件过程中a,b,c变量的值为零。在方法二中只有一个事件过程,变量a,b,c作为过程级变量声明,当然声明与窗体级变量效果相同。

       方法一:       方法二:

       Dimagb#c#     Pfiv~eSubForm-Click()

       Private Sub Textl_LostFocus()             Dima#b#c#

                  '对变量a赋值                     '用到变量a,b,c

       EndSub   EndSub

       Private Sub Text2_LostFocus()

                  '对变量b赋值

       EndSub

       Private Sub Text3_LostFocus()

                  '对变量c赋值

       EndSub

       Private Sub Command1_Click()

                  '用到变量a,b,c

       EndSub

7.在Form Load事件中,SetFocus方法不起作用

原因同Print方法,因为系统在窗体装入内存时无法同步地用SetFocus方法定位控件的焦点。解决的方法在属性窗口对要定位焦点的控件将其Tablndex值设置为。就可。

8.程序运行时对多个文本框间焦点移动的问题

方法-:按"Tab"键。这时可不必编程,直接利用系统提供的功能方便地在各控件之间移动。若要确定离开或进入了哪个控件,则利用"控件LostFocus''"控件_GotFocus''事件进行判断。

方法二:按"回车"键。这时必须通过KeyPress事件编程宋实现,有关程序段如下:

Private Sub某文本框_KeyPress(KeyAscii As Integer)

       If KeyAscii=13 Then

              另一控件.SetFocus

             End If

                     …

       End Sub

第三章  选择结构

3.1  知识要点

1.单边IF语句的两种格式和使用

(1)If<表达式>Then              (2)If<表达式>Then<语句>

       <语句块>

End If

其中,表达式可以是任何表达式,即算术、字符、关系和逻辑表达式,按表达式的值非。为True0False来判断。

多行的IF必须与EndlF配对;单行格式没有End If关键字。

2.双边IF语句的两种格式和使用

(1)If<表达式>Then       (2)If<表达式>Then<语句1>Else<语句2>

       <语句块1>

Else

       <语句块2>

End If

3.多边IF语句的格式和使用

       If<表达式1>Then

       <语句块1>

ElseIf<表达式2>Then

       <语句块2>

[Else

       <语句块n+1>]

       End If

Else If之间不能有空格。

4IF语句的嵌套和使用

       If<表达式1>Then

                …

       If <表达式11>Then

         …

End If

         …

End If

区分嵌套的层次方法,每个Endlf与它上面最接近的If配对。书写为锯齿形,便于区分和配对。

5.情况语句Select Case的格式和使用

格式:

       Select Case<变量或表达式,

              Case<表达式列表1>

                     <语句块1>

       Case<表达式列表2>

              <语句块>

              …

       [Case Else

              <语句块n+1>]

       End Select

其中,<变量或表达式>只能是对一个变量进行多种情况的判断;<表达式列表i>中不能山现"变量或表达式"中出现的变量。

6.条件测试函数的形式和使用

IIf(<条件表达式>,当条件为True时的值,当条件为False时的值)

Choose(<数字类型变量>,值为1的返回值,值为2的返回值…)

Switch(<条件表达式1>,条件表达式1True时的值

       [<条件表达式2>,条件表达式2True时的值…])

3.3  常见错误和难点分析

1.在选择结构中缺少配对的结束语句

对多行式的If块语句中,应有配对的End If语句结束。否则,在运行时系统会显示" If没有End If"的编译错误。

同样对Select Case语句也应有与其相对应的EndSelect语句。

2.多边选择Else If关键字的书写和条件表达式的表示

多边选择Else If子句的关键字Else If之间不能写有空格,即不能写成Else If

在多个条件表达式的表示时,应从最小或最大的条件依次表示,以避免条件的过滤。例如,已知输入某课程的百分制成绩mark,要求显示对应五级制的讦定,评定条件如下:

有以下几种表示方式,语法上都没有错,但执行后结果有所不同,请读者分析哪些正确?哪些错误?

下面给出的答案中,方法一、二、五正确,其余错误,请读者分析各自的原因。

方法一:       方法二:       方法三:

If mark>=90Then   If mark<60Then     If mark>=60Then

       Print"" Print"不及格" Print"及格"

ElseIf mark>=80Then    ElseIf mark<70Then      ElseIf mark>=70Then

       Print""        Print"及格"     Print""

ElseIf mark>=70Then    ElseIf mark<80Then      Elselfmark>=80Then

       Print""        Print""        Print""

ElseIfmark>-60Then      ElseIf mark<90Then      Elselfmark>=90Then

       Print"及格"            Print""        Print""

Else Else Else

       Print"及格"     Print"" Print"不及格"

End If     End If     End If

方法四:       方法五:

If mark>=90Then   If mark>=90Then

       Print""        Print""

ElseIf80<=mark<90Then      ElseIf80<=mark And mark<90 Then

       Print"" Print""

ElseIf70<=mark<80Then      ElseIf70<=mark And mark<80Then

       Print"" Print""

ElseIf60<=mark<70Then      ElseIf60<=mark And mark<70Then

       Print"及格"            Print"及格"

Else Else

       Print"不及格"        Print"不及格"

End If     End If

3Select Case语句的使用

(1)"表达式列表i"中不能使用"变量或表达式"中出现的变量。例如,上述多边选择的例子改为Select Case语句实现,方法一Case子句中出现变量mark,运行时不管mark的值多少,始终执行Case Else子句,运行结果不正确;方法二、方法三正确。

方法一:       方法二:       方法三:

Select Case mark    Select Case mark    Select Case mark

       Case mark>=90             Case Is>=90          Case Is>=90

              Print"" Print"" Print""

       Case mark>=80      Casels>=80     Case 80To 89

              Print""        Print""        Print""

       Casemark>=70       Case Is>=70   Case 70To 79

              Print""        Print""        Print""

       Case mark>=60      Case Is>=60   Case 60TO 69

              Print"及格"            Prim"及格"            Print"及格"

       Case Else Case Else Case Else

              Print"不及格"        Print"不及格"        Print"不及格"

End Select      End Select      End Select

(2)"变量或表达式"中不能出现多个变量。实验三第5题对三门课程奖学金的判断,只能用If语句的多边选择,而不能用SelectCase语句实现。例如,有些读者用如下语句表示:

       Select Case marklmark2mark3

              Case(markl+mark2+mark3)/3>=95

                     Print"一等奖"

       End Select

这样就会在"Select Case markl,mark2,mark3"语句行出现编辑错误:同时Case(markl+mark2 +mark3)/3>=95书写也错误。

第四章  循环结构

4.1  知识要点

1For Next循环结构形式和使用

       For<循环变量>=<初值>To<终值>[Step<步长>]

              <循环体>

       Next<循环变量>

常用于已知循环次数的场合。步长可正可负,可为整数,也可为实数。掌握循环次数的计算: ,当循环变量(步长为正)大于终值,循环终止。

例如,程序段都是以每100显示sin的值:

(1)Fori=0 To 360 Stepl0 (2)For x=0To 6.28 Step 6.28/36

       Print sin(i*3.14/180)             Print sin(x)

       NextiNextx

(3)For j=360 To 0 Step-10

              Print sin((360-j)*3.14/180)

       Next j

2DoLoop循环结构形式和使用

根据不同组合,有5种形式:

1)无条件循环 2)当条件为真循环 3)当条件为真不循环    4)先循环再判断    5)先循环再判断

       Do   Do While<条件>           Do Until<条件>            Do          Do

              <循环体>              <循环体>                     <循环体>                     <循环体>                     <循环体>

       Loop       Loop              Loop              Loop While<条件> LoopUntil<条件>

3.循环的嵌套及注意事项

循环体内又出现循环结构称循环的嵌套或多重循环。计算多重循环的循环次数由每一重循环次数的乘积。

外循体内要完整地包含内循环结构,不能交叉。

4.其他辅助语句

Eixt For退出For循环语句、Exit Do退出Do循环、GoTo五条件转向语句、End程序运行结束语句、With语句。

4.3  常见错误和难点分析

1.不循环或死循环的问题主要是循环条件、循环初值、循环终值、循环步长的设置有问题。例如,以下循环语句不执行循环体:

For i=10 To 20 Step-1   ' 步长为负,初值必须大于等于终值,才能循环

For i=20 To10 ' 步长为正,初值必须小于等于终值,才能循环

Do While False       ' 循环条件永远不满足,不循环

例如,以下循环语句死循环:

For i=10 To 20 Step 0    ' 步长为零,死循环

Do While 1     ' 循环条件永远满足,死循环

2.循环结构中缺少配对的结束语句

ForNext语句没有配对的Next语句;Do语句没有一个终结的Loop语句等。

3.循环嵌套时,内外循环交叉:

       For I=1 to 4

              For j=1 to 5

              …

              Next i

       Next j

上述循环的交叉运行时显示"无效的Next控制变量引用"

4.累加、连乘时,存放累加、连乘结果的变量赋初值问题

(1)一重循环

在一重循环中,存放累加、连乘结果的变量初值设置应在循环语句前。

例如,求11003的倍数和,结果放入Sum变量中,如下程序段,输出结果如何?

       Private SubForm_Click()

              Fori=3 To 100 Step 3

                     Sum=0

                     Sum=Sum+i

              Next i

              Print Sum

       End Sub

要得到正确的结果,应作如何改进?

(2)多重循环

在多重循环中,存放累加、连乘结果的变量初值设置放在外循环语句前,还是内循环语句前,这要视具体问题分别对待。

例如,期末30位学生参加三门课程的考试,求每个学生的三门课程的平均成绩如下程序能否实现,应如何改进?

       aver=0

       For i=1 To 30

              For j=1 To 3

                     m=InputBox("输入第"&j&"门课的成绩")

                     aver=aver+m

              Next j

              aver=aver/3

              Print aver

       Nexti

第五章     

5.1  知识要点

1.数组的概念

数组:存放具有相同性质的一组数据,也就是数组中的数据必须是同一个类型和性质。

数组元素:数组中的某一个数据项。数组元素的使用同简单变量的使用。

2.静态数组的声明

静态数组:在声明时已确定了数组元素个数。

声明形式:Dim数组名([下界To]上界[[下界To]上界[,…]])As  类型

此语句声明了数组名、数组维数、数组大小、数组类型。

[注意]

下界、上界必须为常数,不能为表达式或变量:省略下界,默认为0,也可用Option Base语句重新设置下界的值。

3.动态数组的声明

声明形式:    Dim数组名 ()

       ReDim  [Preserve]数组名([下界To]上界[[下界To]上界[,…]])

[注意]

此时的上界、下界可以是赋了值的变量或表达式。若有Preserve关键字,表示当改变原有数组最末尾的大小时,使用此关键字可以保持数组中原来的数据。

4.控件数组

相同类型的控件组成的数组。

控件数组的建立:在设计时的窗体上,通过对某控件的复制和粘贴操作:在程序运行时通过Load方法实现。

控件数组元素:由控件的Index属性值表示数组的F标。

5.数组的操作

应掌握的基本操作有:数组初始化、数组输入、数组输出、求数组中的最大(最小)元素及下标、求和、平均值、排序和查找等。

5.3  常见错误和难点分析

1Dim数组声明

有时用户为了程序的通用性,声明数组的上界用变量来表示,如下程序段:

       n=InputBox("输入数组的上界")

       Dim a(1 To n)As Integer

程序运行时将在Dim语句处显示"要求常数表达式"的出错信息。即Dim语句中声明的数组上,下界必须是常数,不能是变量。

解决程序通用的问题,一是将数组声明的很大,这样浪费一些存储空间;二是利用动态数组,将上例改变如下:

       Dima()As Integer

       n=InputBox ("输入数组的上界")

       ReDim a(1 To n)As Integer

2.数组下标越界

引用了不存在的数组元素,即下标比数组声明时的下标范围大或小。例如,要形成有如下30项的斐波那契数列:

1,1,2,3,5,8,13,21,34,,317811514229832040

正确的程序段如下:

       Dim a(1 To 30) As Long, i%

若将For i=3To 30改为For i=1 To 30,程序运行时会显示"下标越界"的出错信息,因为开始循环时i=l,执行到循环体语句a(i)=a(i-2)+a(i-1),数组下标i-2i-1均小于下界1

同样若将上例:a(i)+a(i-2)+a(i-1)语句改为:a(i+2)=a(i)+a(i+1)

程序运行时也会显示"下标越界"的出错信息,这时是数组下标大于上界30

3.数组维数错

数组声明时的维数与引用数组元素时的维数不一致。例如,下程序段为形成和显示3×5的矩阵:

       Dim a(3,5) As Long

              For i=1 To 3

                     For j=1 To 5

                            a(i)=i*j

                            Print a(i);"";

                     Next j

              Print

       Next i

程序运行到a(i)=i*j语句时出现"维数错误"的信息,因为在Dim声明时是二维数组,引用时的一个下标。

4Aarry函数使用问题

Aarry函数可方便地对数组整体赋值,但此时只能声明Variant的变量或仅由括号括起的动态数组。赋值后的数组大小由赋值的个数决定。

例如,要将1234567这些值赋值给数组a,表2.5.1列出了三种错误及相应正确的赋值方法。

2.5.1  Aarry函数表示方法

错误的Aarry函数赋值 改正的Aarry函数赋值

Dim a(1 To 8)a=Array(1,2,3,4,5,6,7,8) Dim a( )a=Array(1,2,3,4,5,6,7)

Dim a As Integera=Array(1,2,3,4,5,6,7)       Dim aa=Array(1,2,3,4,5,6,7)

Dim aa()=Array(1,2,3,4,5,6,7)      Dim aa=Array(1,2,3,4,5,6,7)

5.如何获得数组的上界、下界

 Aarry函数可方便地对数组整体赋值,但在程序中如何获得数组的-上界、下界,以保证访问的数组元素在合法的范围内,可使用UBoundLBound函数来决定数组访问。

在上例中,若要打印a数组的各个值,可通过下面程序段实现:

For i=Lbound(A) To Ubound(A)

              Print a(i)

       Next l

6.给数组赋值

VB6.0提供了可对数组整体赋值的新功能,方便了数组对数组的赋值操作。但真正使用不那么方便,有不少限制。数组赋值形式如下:

数组名2=数组名1

我们就此形式作讨论:这里的数组名2,实际上在前面的数组声明时,只能声明为Varian的变量,赋值后的数组2的大小、维数、类型同数组名1;否则,若声明成动态或静态的数组,例如:

Dim数组名2()Dim数组名2 (下标)

程序在运行到上述赋值语句时显示"不能给数组赋值"的出错信息。

所以,为了程序的安全、可靠,建议读者还是忍痛割爱,少用VB60的这一新功能,使用传统的循环结构来给数组赋值。基于此原因,我们也就在教程中不作展开。

第六章     

6.1  知识要点

1.过程的概念

VB的程序是由一个个过程构成的,除了VB系统提供了大量使用的内部函数过程和事件过程外,VB系统还允许用户根据各自需要自定义过程。使用过程的好处:使程序简练、高效、便于程序的调试和维护。本节涉及的过程主要指的是用户自定义的子过程和函数过程。

2.两类过程定义与调用

(1)子过程

定义形式:Sub<子过程名>[(形参表)]

        …

       End Sub

特点:子过程名无值,无类型。

调用形式:Call<子过程名>[(实参表)]

       或:<子过程名>[(实参表)]

特点:是一句独立的语句。

(2)函数过程

形式:Function<函数过程名>([形参表])

       …

       <函数过程名>=<表达式>

       …

       End Sub

特点:函数过程名有值、有类型,在过程体内至少赋值一次。

调用形式:<函数过程名> ([实参表])

特点:不能独立存在,必须参加表达式的运算。

3.参数传递

(1)传值方式是将实参的具体值传递给形参。

传值方式是形参前加ByVal关键字,表示值传递。这种传递方式是一种单向的数据传递,即调用时只能由实参将值传递给形参;调用结束不能由形参将操作结果返回给实参。实参可以是常数或表达式。

(2)传地址

传地址方式(ByRet)是将实参在内存的地址传递给形参,也就是实参、形参共用内存内的"地址"

 这种传递方式是一种双向的数据传递,即调用时实参将值传递给形参:调用结束由形参将操作结果返回给实参。当实参要得到返回的结果时,实参只能是变量,不能是常数或表达式。

在过程中具体用传值还是传地址,主要考虑的因素是:若要从过程调用中通过形参返回结果,则要用传地址方式;否则应使用传值方式,减少过程间的相互关联,便于程序的调试。数组、记录类型变量、对象变量只能用地址传递方式。

VB中,默认是传地址方式。

4.变量的作用域

全局变量:Public关键字开头的变量为全局变量,在整个工程中都有效。

窗体、模块级变量:在通用声明段用DimPrivate关键字声明的变量,在该窗体或模块内有效。

局部变量:在过程中声明的变量,在该过程调用时分配内存空间并初始化,过程调用结束,回收分配的空间。

使用规则见表2.6.1所示。

2.6.1  变量的作用域

使用范围       局部变量       窗体/模块级变量   全局变量

                     窗体       标准模块

声时方式       Dim, tatic       Dim,Private          

声明位置       在过程中       窗体/模块的通用声明段      窗体/模块的通用声明段

能被本模块的其他过程存取       不能          

能被其他模块存取       不能       不能       能,但在变量名前加窗体名      

静态变量:局部变量声明前加Static关键字,在程序运行的过程中始终保值。

5.过程的递归调用

在调用一个子过程或函数过程中又调用自己,称为递归调用,这样的子过程或函数过程称为递归子过程或递归函数,简化称为递归过程。

构成递归过程的条件:递归结束条件及结束时的值:能用递归形式表示,并且递归向终止条件发展。

6.常用算法

对数值计算方面要求掌握:求最大值(最小值)及下标位置、求和、平均值、最大公约数、最小公倍数、素数、数制转换、高次方程求根(迭代法、二分法)、定积分(矩形法、梯形法、辛卜生法、蒙特卡洛法)

非数值计算:常用字符串处理函数、排序(选择法、冒泡法、插入法、合并排序)、查找(顺序、二分法)

6.3  常见错误和难点分析

1.程序设计算法问题

该章程序编写难度较大,主要是算法的构思有困难,这也是程序设计中最难学习的阶段。经验告诉每一位程序设计的初学者,没有捷径可走,多看、多练、知难而进。上机前一定要先编写好程序,仔细分析、检查,才能提高上机调试的效率。每当一个程序通过艰苦的努力调试通过时,那苦尽甘来的喜悦令你一言难尽。

2.确定自定义的过程是子过程还是函数过程

实际上过程是一个具有某种功能的独立程序单位,供多次调用。子过程与函数过程的区别是前者子过程名无值:后者函数过程名有值。若过程有一个返回值,则习惯使用函数过程;若过程无返回值,则使用子过程:若过程返回多个值,一般使用子过程,通过实参与形参的结合带回结果,当然也可通过函数过程名带回一个,其余结果通过实参与形参的结合带回。

3。过程中形参的个数和传递方式的确定

对初学者,在定义过程时不能确定形参的个数和传递方式。

过程中参数的作用是实现过程与调用者的数据通信。一方面,调用者为子过程或函数过程提供初值,这是通过实参传递给形参实现的:另一方面,子过程或函数过程将结果传递给调用者,这是通过地址传递方式实现的。因此,决定形参的个数就是由上述两方面决定的。对初学者,往往喜欢把过程体中用到的所有变量命作为形参,这样就增加了调用者的负担和出错概率:也有的初学者全部省略了形参,则无法实现数据的传递,既不能从调用者得到初值,也无法将计算结果传递给调用者。

VB中形参与实参的结合有传值和传地址两种方式。区别如下:

(1)在定义形式上前者在形参前加即Val关键字。

(2)在作用上值传递只能从外界向过程传入初值,但不能将结果传出:而地址传递既可传入又可传出。

 (3)如果实参是数组、自定义类型、对象变量等,形参只能是地址传递。

4.实参与形参类型对应问题

在地址传递方式时,调用过程实参与形参类型要一致。例如:

函数过程定义如下:

       Public Function f!(x!)

              f=x+x

       End Function

主调程序如下:

       Privme Sub Commandl_Click()

              Dim y%

              y=3

              Print f(y)

       End Sub

上例形参x是单精度型、实参y是整型,程序运行时会显示"ByRef参数类型不符"的编译出错信息。

在值传递时,若是数值型,则实参按形参的类型将值传递给形参。例如:

函数过程定义如下:

       Public Function f!(ByVal x%)

              f=x+x

       End Function

主调程序如下:

       Priva~SubCommandI_Click()

              Dim y!

              Y=3.4

              Print f(y)

       End Sub

程序运行后显示的结果是6

5.变量的作用域问题

局部变量,在对该过程调用,分配该变量的存储空间,当过程调用结束,回收分配的存储空间,也就是调用一次,初始化一次,变量不保值:窗体级变量,当窗体装入,分配该变量的存储空间,直到该窗体从内存卸掉,才回收该变量分配的存储空间。

例如,要通过文本框输入若于个值,每输入一个按Eenter键,直到输入的值为9999,箱入结束,求输入的数的平均值。

       Private Sub Textl_Key Press(Key Ascii As Integer)

              Dim sum!,n%

              If KeyAscii=13 Then

                     If Val(Text1)=9999 Then

                            sum=sum/n

                            Print sum

                     Else

                            Sum=sum+Text1

                                   n=n+1

                            Text1=""

                     End If

              End If

       End Sub

该过程没有语法错,运行程序可输入若干个数,但当输入9999时,程序显示"溢出"的错误。原因sumn是局部变量,每按一个键,局部变量初始化为o,所以会有上述错误产生。

改进方法:将要保值的局部变量声明为Static静态变量或声明为窗体级变量。也可将要保值的变量在通用声明段进行声明为窗体级变量。

6.递归调用出现"栈溢出"

如下求阶乘的递归函数过程:

PublicFunctionfac(nAsInteger)Asinteger

       If n=1 Then

                     fac=1

              Else

                     fac=n*fac(n-1)

              End If

       End Function

       Private Sub Commandl_Click()     '调用递归函数,显示出fac(5)=120

                     Print "fac(5)"fac(5)

       End Sub

当主调程序调用时,n的值为5时,显示120结果:当n的值为-5时,显示"溢出堆栈空间"的出错信息。

实际上每递归调用一次,系统将当前状态信息(形参、局部变量、调用结束时的返回地址)压栈,直到到达递归结束条件。上例当n=5时,每递归调用一次,参数n-l,直到n=l递归调用结束,然后不断从栈中弹出当前参数,直到栈空。而当n'-5时,参数n-1-6、压栈,再递归调用、n-1永远到不了n=l的终止条件,直到栈满,产生栈益出的出错信息。

所以设计递归过程时,一定要考虑过程中有终止的条件和终止时的值或某种操作,而且每递归调用一次,其中的参数要向终止方向收敛,否则就会产生栈溢出。

第七章  常用控件()

7.1  知识要点

1.单选按钮和复选框

单选按钮和复选框的常用属性是Value,它的主要作用是用宋检查单选按钮或复选框是否被选定。

单选按钮和复选框能够响应Click事件,但通常不需要编写事件过程。

2.框架

框架的主要作用是将其他控件组合在一起,对一个窗体中的各种功能进行分类,以便于用户识别。当用框架将同一个字体上的单选按钮分组后,每一组单选按钮都是独立的,也就是说,在一组单选按钮中进行操作不会影响其他组单选按钮的选择。

框架的重要属性是Caption

一般不需要编写事件过程。

3.列表框

列表框的主要属性有:TextListListlndexListCountSo~ed。当MultiSelect属性为 12时允许多项选择,此时往往需要Selected属性判定哪些项目被选定。

列表框的常用方法是:AddltemRemoveltemClear

在通常情况下,列表框不需要编写事件过程,其中的项目也不需要更改。

4.组合框

组合框是组合了文本框和列表框的特性而形成的一种控件。组合框的类型由其Style属性决定。下拉式组合框(Style0)和简单组合框(Style1)允许用户在文本框中输入不属于列表内的选项。

5.滚动条

滚动条特有的常用属性有:MaxMinValueSmallChangeLargeChange

滚动条的重要事件是:ChangeScroll

6.时钟控件

时钟控件特有的常用属性是Interval,它的值以0.  001秒为单位。

时钟控件的Enabled属性与其他控件是不同的,当时钟控件的Enabled属性为True时, Timer事件以Interval属性值的毫秒间隔发生。如果将时钟控件的Enabled属性设为False Interval属性设为0时计时器停止运行,则Timer事件不会发生。

Timer是时钟控件的唯一事件。

可以利用时钟连续播放图片达到动画效果。

7.3  常见错误和难点分析

1.遗漏对象名称

VB程序设计时,初学者常犯的一个错误是遗漏对象名称,特别是在使用列表框时。例如,如果要引用列表框(List1)中当前选定的项目,Listl.list(Listlndex)是错误的。即使当前焦点在Listl上,VB也不是认为ListlndexList l的属性,而是一个变量。所以正确的引用方式是:Listl. 1ist(Listl.Listlndex)

2.列表框的Columns属性

列表框的Columns属性决定列表框是水平还是垂直滚动、以及如何显示列中的项目。如果水平滚动,则Columns属性决定显示多少列,如表2.7.2所示。图2.7.1是一个水平滚动两列显示的列表框。

在程序运行期间,该属性是只读的,也就是说,不能在运行时,将多列列表框变为单列列表框或将单列列表框变为多列列表框。

2.7.2  列表框的Columns属性

列数          

0(默认值)1n       项目安排在一列中,且列表框竖直滚动项目安排在多个列中,先填第一列,再填第二列……列表框水平滚动并显示指定数目的列

3.域级验证

域级验证是指输入到某独立域的数据的验证,在域级验证的过程中一般不考虑窗体-般其他域的内容。进行域级验证的合适时间是:

(1)当往某域中输入某个键时,此时涉及键盘事件(KeyDownKeyUpKeyPress)。有关这方面的内容请参阅教程第4.7节。

(2)当用户企图离开某域时,此时涉及CansesValidate属性和Validate事件。

(3)当某域的内容发生变化时,此时涉及Change事件。

CausesValidation属性和Validate事件通常是协同工作的。

CausesValidate属性决定Validate事件是否发生。如果控件的CausesValidate属性为False,该控件的Validate事件永远不会发生。如果控件的CausesValidate属性为Tree,当焦点企图移到(还没有离开,也可以说离开之前)另一个CausesValidate属性为True的控件时,原控件的Validate事件发生:当焦点企图移到另一个CausesValidate属性为False的控件时,原控件的Validate事件暂时不发生,什么时候发生?直到焦点移到一个CausesValidate属性为True的控件上时才发生。

例如,假定有如图2.7.2所示的程序。当焦点企图从Textl移到Text2时,TextlValidate事件发生:同样当焦点企图从Text2移到Textl时,Text2Validate事件发生。当焦点企图从Textl移到Text3时,TextIValidate事件暂时没有发生,因为Text3CausesValidateFalse,然后如果焦点企图继续移动到Text2时,TextlValidate事件才发生。

2.7.2  CausesValidate属性和Validate事件

CausesValidate属性和Validate事件的这一特性常常应用在如图273所示的程序中。当在文本框中输入了无效数据时而又不知道如何输入有效数据时,用户往往选择Help命令寻求帮助或选择Cancel命令结束数据输入,此时不希望执行验证程序。因为如果执行验证程序且发现了无效数据,则无法选择HelpCancel了,用户就这样被套住了。现在只要将文本框的CausesValidate属性设为True,命令按钮的CausesValidate属性为False,验证程序放在 Validate过程中,问题就解决了。在默认情况下,所有控件的CausesValidation属性都为Tree

2.7.3  命令按钮的CausesValidate属性和Validate事件

并不是所有的控件都有Validate事件。只有那些能用于输入数据的控件(如文本框、复选框、滚动条等)才有这个事件。Validate事件过程如下:

       Privme Sub object_Validate(Cancel As Boolean)

              …

       EndSub

其中,当参数Cancel被设为Tree后,焦点将不会离开对象。

如果要将实验七第1题改用Validate事件和CausesValidation属性实现数据验证,则应有如下的程序。

       Sub txtMath_Validate(Cancel As Boolean)

              If Val(txtMath.Text)<0 Or Val(txtMath.Text)>100 Then

                     Cancel=True

              End If

       End Sub

常用控件()

8.1  知识要点

1.菜单

每一个菜单项都是一个控件,有Click事件。在程序运行期间,如果用户单击菜单项,则运行该菜单项的Click事件过程。

利用菜单编辑器可以设计弹出菜单,在程序中使用PopupMenu方法显示。

利用控件数组可以实现实时菜单,即由应用程序根据需要动态创建的菜单。菜单项用 Load语句创建,用UnLoad清除。

2.对话框

VB应用程序中,对话框有三种:预定义的对话框、通用对话框和用户自定义对话框。

预定义对话框是系统定义的对话框,可以调用如InputBoxMsgBox等函数直接显示。

通用对话框向用户提供了打开、另存为、颜色、字体,打印和帮助六种类型的对话框。使用它们可以减少设计程序的工作量。

自定义对话框是具有特殊的属性设置的窗体。作为对话框的窗体的BorderStyle ControlBoxMaxBu~onMinButton应分别为1FalseFalseFalse

对话框分成模式的和无模式的。

3.多重窗体

窗体的常用方法和语句有:LoadUnloadShowHide

在窗体的加载和卸载过程中涉及到多种事件,这些事件发生的时机和次序请参阅教程第 4.5节。

4.高级控件

VB中,用户可以加载和使用VB提供的以及第三方开发的许多扩展的高级控件。它们的属性可以简单地在属性页中设置。

(1)SSTab控件可以用来制作选项卡。

(2)ProgressBar用来指示事务处理的进程。

(3)Slider控件是包含滑块和可选择性刻度标记的窗口,以一种可视的方式向用户提供刻度设置的功能。

(4)UpDown可以用来设置程序的某些参数,一般与文本框"捆绑"在一起。

(5)Animation用来描放AVI视频文件。Animation的四个重要方法是:OpenPlayStopClose方法,常用属性有CenterAutoPlay。如果CenterTme,则动画在控件的中央播放;如果AutoPlayTrue,则用Open打开文件时自动播放,否则需要用Play播放。

5.鼠标器

除了ClickDblClick之外,鼠标事件还有MouseDownMouseUpMouseMove

这三个鼠标事件过程具有相同的参数。

(1)Button:可以使用vbLefiBu~onvbRightButtonvbMiddleButton方便地检测是哪个鼠标按钮被按下了。

(2)Shift:可以使用vbAltMaskvbCtrlMaskvbShiftMask以及它们的逻辑组合来检测 AltCtrlShift键的状态。如果要检测CtrlShift键是否同时被按下,则应用表达式(Shift AndvbCtrlMask)And(ShifiAndvbShifiMask)

(3)XY:表示当前鼠标指针的位置。

MouseDownMouseUpbutton'参数的意义与MouseMove是不同的。对于MouseDownMouseUp来说,button参数指出哪个鼠标按钮触发了事件,而对于MouseMove来说,它指示当前所有的状态。

6.键盘

键盘事件有KeyPressKeyUpKeyDown

KeyUpKeyDown所接收到的信息与KeyPress接收到的不完全相同。

("KeyUpKeyDown能检测到KeyPress不能检测到的功能键、编辑键和箭头键。

(2)KeyPress接收到的是用户通过键盘输入的ASCII码字符。例如,当键盘处于小写状态,用户在键盘按"A"健,则KeyAscii参数值为97:当键盘处于大写状态,用户在键盘按"A"健,则KeyAscii参数值为65KeyUpKeyDown接收到的是用户在键盘所按键的键盘扫描码。例如,不管键盘处于小写状态还是大写状态,KeyCode参数值都是65

总之,如果需要检测用户在键盘输入的是什么字符,则应选用KeyPress事件:如果需要检测用户所按的物理键时,则选用KeyUpKeyDown事件。

在默认情况下,单击窗体上的控件时窗体的KeyPressKeyUpKeyDown是不会发生的。为了启用这三个事件,心须将窗体的KeyPreview属性设为True,而默认值为False

一旦将窗体的KeyPreview属性设为True,键盘信息要经过两个平台(窗体级键盘事件过程和控件的键盘事件过程)才能到达控件。例如,假定有下列两个过程:

       SubForm_KeyPress(KeyAsciiAsInteger)

              KeyAscii=KeyAscii+1

       End Sub

       Private Subtxt Test KeyPress(KeyAscii As Integer)

              Key Ascii=KeyAscii+1

       End Sub

则当用户在键盘上输入小写字符"a"时,文本框txtTest接收到的字符是"c"

利用这个特性可以对输入的数据进行验证。例如,如果在窗体的KeyPress事件过程中将所有的字符都改成大写,则窗体上的所有控件都不能接收到小写字符。

用户应该根据需要决定数据验证放在窗体级还是放在控件级。

7.普通拖放

手工拖放与自动拖放的区别如表2.8.1所示。

在运行时拖动源对象并不能自动改变源对象位置,必须进行编程来重新放置控件。

拖动时的图标由源对象的Draglcon属性决定。

2.8.1  手工拖放与自动拖放的区别

对象       手工拖放       自动拖放

源对象    DragMode置为0Drag方法启动""操作     DragMode置为1没有MouseDows事件

中间对象       发生DragOver事件      发生DragOver事件

目标对象       发生DragOverDragDrop事件       发生DragOverDragDrop事件

8OLE拖放

当源对象的OLEDragMode属性为](Automatic)时,自动支持OLE""操作;当目标对象的OLEDropMode属性设为2(Automatic),自动支持OLE""操作。

完全支持OLE拖放的控件有:TextBoxPictureBoxImage等控件。

支持自动""操作,但不支持自动""操作的控件有:ListBoxComboBoxDirListBoxFileListBox等控件。

只支持OLE拖放事件的控件有:LabelCommandButtonOptionButtonCheckBoxFrameDriveListBox等控件。

 8.3  常见错误和难点分析

1.窗体顶部菜单栏中的菜单项与子菜单中的菜单项的区别

窗体顶部菜单栏中的菜单项与子菜单中的菜单项都是在菜单编辑器中定义的,但是它们是有区别的。

(1)窗体顶部菜单栏中的菜单项不能定义快捷键,而子菜单中的菜单项可以有快捷键。

(2)当有热键字母(菜单标题中"&"后的字母)时,按Alt+热键字母选择窗体顶部菜单栏中的菜单项,按热键字母选择子菜单中的菜单项(当子菜单打开时)。子菜单没有打开时,按热键字母无法选择其中的菜单项。

(3)尽管所有的菜单项都能响应Click事件,但是窗体顶部菜单栏中的菜单项不需要编写事件过程。

2.在程序中对通用对话框的属性设置不起作用

在程序中对通用对话框的属性设置不起作用,多数情况是因为在弹出对话框后才进行属性设置。例如,下面的程序代码就存在这样的问题,改正方法是将弹出对话框语句放到最后,即把CommonDialogl.Action=l放在所有属性设置语句的后面。

       CommonDialog1.Action=1

       ConmaonDialog1.FileName="*.Bmp"

       CommonDialogl.InitDir="C:/Windows"

       CommonDialog1.Filter="Pictures(*.Bmp)|*.Bmp|All Files(*.*)|*.*"

       CommonDialog1.FilterIndex=1

3.在工程中添加现有窗体时发生加载错误

在使用"工程"菜单中的"添加窗体"命令添加一个现存的窗体时经常发生加载错误,绝大多数是因为窗体名称冲突的缘故。例如,假定当前打开了一个含有名称为Forml的工程,如果想把属于另一个工程的Forml窗体装入则肯定会出错。

[注意]

窗体名与窗体文件名的区别。在一个工程中,可以有两个窗体文件名相同的窗体(分布在不同的文件夹中),但是绝对不能同时出现两个窗体名相同的窗体。

4.实时菜单的创建'

实时菜单是由应用程序根据需要动态创建的。在VB中,常见的实时菜单是"文件"菜单,该菜单显示了最近所使用的工程。

创建实时菜单必须结合控件数组,用Load语句创建菜单项,用UnLoad清除菜单项。

创建实时菜单的步骤;

(1)在菜单编辑器中建立样本菜单项。

样本菜单项的属性设置见表284所示。设置Indexo,表明样本菜单项是控件数组的一个元素,其下标为o。样本菜单项的Name属性是必须的,它将作为控件数组的名称。在-F面假定数组名为NameA~ayVisible可以设为True,设为False表示初始时该菜单项不可见。

2.8.4  实时菜单样本菜单项

属性       Name      Caption   Index      Visible

设置值    必需的    可以没有       0     False

(2)在程序中用Load语句创建菜单项。

例如,Load NameArray(1)创建一个新的菜单项(在控件数组中的F标为1),然后将其 Visible属性设置True,同时设置Caption属性。

动态创建的菜单项继承了除了Index之外的绝大部分属性,所以要对CaptionVisible属性进行设置。另外,样本菜单项在菜单系统中的位置决定了新菜单项出现的位置。

(3)为实时菜单项编写代码。

每个实时菜单项都是控件数组的一个成员,具有相同的名称,并且共享事件过程。

下面是一个实时菜单项代码示例:

       SubNameArray_Click(Index As Integer)

              Select Case Index

                     Case  0

                            MsgBox("NameArmy(0)(样本菜单项) is clicked!")

                     Case  1

                            MsgBox("NameArray(1)(第一个实购菜单项)isclicked!")

                     Case  2

                            MsgBox("NameArray(2)(第二个实时菜单项)is clicked!")

              End Select

       End Sub

(4)删除实时菜单项。

尽管把Visible设为False,程序运行时实时菜单项不会显示,然而有时还是需要把实时菜单项从内存中销毁。删除实时菜卑顾使用UnLoad语句。例如,LoadNameArray(1)

有关建立实时菜单的详细内容请参阅教程第4.3节。

5.通用对话框的CancelError属性和Err对象

当通用对话框的CancelError属性为Tme时,无论何时选择"取消"按钮,均产生 32755(cdlCancel)号错误,即将ErrNumber属性设置为32755

ErrVB的一个系统对象,它记录了程序运行期间所发生的错误。

Err对象的重要属性有Number(默认属性)Description。当错误发生后,错误的生成者把错误号和有关错误的说明分别存放在NumberDescription属性中。例如,当在 CancelError属性为True的通用对话框中选择"取消"按钮时,产生一个错误,Err对象的NumberDescription属性将被设置为32755"选择'取消'"

在程序运行期间,经常会发生各种各样的错误。有关错误处理的详细内容请参阅教程第 9.6节。

下面是当程序产生cdlCancel错误时结束程序的运行。

       SubForm_ClickO

              CommonDialogl.CancelError=True

              On Error GoTo ErrorHandler

              CommonDialogl.Action=l

              ' 处理文件的语句

              ErrorHandler

              If Err.Number=cdlCancel Then

                     End

              Endlf

       End Sub

6.与窗体有关的事件

在首次用Load语句将窗体(假定该窗体在内存中还没有创建)调入内存之时依次发生 InitializeLoad事件。在用UnLoad将窗体从内存中卸载时依次发生QueryUnLoadUnload事件,再使用Set窗体名=Nothing语句解除初始化时发生Terminate事件。

Initialize是在窗体创建时发生的事件。在窗体的整个生命周期中,Initialize事件只触发一次。用户可以将一个窗体装入内存或从内存中删除很多次,但窗体的建立只有一次。也就是说,在用Load语句将窗体装入内存时会触发Load事件,但并不一定触发Initialize事件。

在用UnLoad语句卸载窗体后,如果没有使用Set窗体名=Nothing解除初始化,则在下次使用Load语句时不会触发Initialize事件,否则会引起Initialize事件。

假定有FormlForm2两个窗体,并且有下列事件过程:

       ' Forml窗体事件过程

       Sub Form_Click()

              Debug.Print"窗体首次装入内存时发生的事件:"

              Load Form2

              Debug.Print"Unload卸载窗体时发生的事件:"

              UnloadForm2

              Debug.Print "窗体第二次装入内存时发生的事件:"

              Load Form2

              Debug.Print "Unload卸载窗体时发生的事件:"

              Unload Form2

              Debug.Print "Set窗体名=Nothing语句解除初始化时发生的事件:"

              Set Form2=Nothing

              Debug.Print "窗体第三次(解除初始化后)装入内存时发生的事件:"

              Load Form2

       End Sub

       'Form2窗体事件过程

       Sub Form_Initialize()

                                   Debug.Print"Initialize事件"

       End Sub

       Sub Form_Lond()

                     Debug.Pnnt"Load事件"

       End Sub

       Sub Form_QueryUnload(Cancel As hteger, UnloadMode As Integer)

                                   Debug.Print"QueryUnload"

       End Sub

       Sub Form_Unlond(Cancel As Integer)

                     Debug.Print"Unload"

       End Sub

       Sub Form_Terminate()

                                   Debug.Print"Terminate"

       End Sub

当用户在Form1上单击时,在Debug窗口显示下列信息:

       窗体首次转入内存时发生的事件:

       Initialize事件

       Load事件

       Unload卸载窗体时发生的事件:

       Query Unload

       Unload

       窗体第二次装入内存时发生的事件:

       Load事件

       Unload卸载窗体时发生的事件:

       QueryUnload

       Unload

       Set窗体名=Nothing语句解除初始化时发生的事件:

       Terminate

       窗体第三次(解除初始化后)装入内存时发生的事件:

       Initialize事件

       Load事件

7MouseDownMOUSeUpC1ick事件发生的次序

当用户在窗体或控件上按下鼠标按钮时MouseDown事件被触发,MouseDown事件肯定发生在MouseUpC1ick事件之前。但是,MOUSeUpCk事件发生的次序与单击的对象有关。

当用户在标签、文本框或窗体上作单击时,其顺序为:

(1)MouseDown

(2)MouseUp

(3)Click

当用户在命令按钮上作单击时,其顺序为:

(1)MouseDown

(2)Click

(3)MouseUp

当用户在标签或文本框上作双击时,其顺序为:

(1)MouseDown

(2)MOuseUp

(3)Click

(4)DblCUck

(5)MouseUp

第八章     

8.1  知识要点

1.文件系统控件

VB提供的文件系统控件主要属性和事件见表2.9.1所示。

2.9.1  文件系统控件主要属性和事件

控件       主要属性       主要事件

DriveListBox(驱动器)    Drive      Change

DirListBox(目录)   Path Change

FileLiseBox(文件)  Path FileName Pattern    Click  DblClick

要使三个控件有机地联系起来,必须用到两个事件过程Drivel Change()Dirl Change() (假定控件使用默认名称)

要使显示的是某种类型的文件,必须还要增加组合框控件,然后要通过对文件列表框控件的Pattern属性进行设置实现。

2.处理文件与目录(文件夹)语句和函数

VB提供的文件与目录(文件夹)语句和函数见表2.9.2所示。在VB6.0中提供了功能更强的文件系统对象,参阅教程第七章。

2.9.2  文件与目录语句和函数

VB语句和函数形式      等效的DOS命令     

FileCopy source, destination  Copy       文件复制

Kill pathname  DELERASE 文件删除,可出现统配符

Name oldpathname As newpathname    REN       文件重命名

ChDrive drive 键盘符    改变当前驱动器

MkDir path     MD  创建新目录

ChDir path      CD  改变当前目录

RmDir path     RD  删除目录

CurDir((drive))             函数返回当前路径

[注意]

用上述语句作用于文件操作时,此时文件必须是关闭的。

3.文件的概念

文件:是指存放在外部介质上的以文件名标识的数据的集合。文件由若干条记录组成,一个记录又可包括若干个数据项。当前操作的文件有一个指针,指向当前读写位置。

 文件分类:根据存放的内容可分程序文件和数据文件;根据存储数据的形式可分ASCII码文件和二进制文件;根据存放的介质可分磁盘文件、打印文件等:根据组织、存取形式可分为顺序文件、随机文件和二进制文件(因使用不多,本章不作介绍)

文件的读写:计算机内存向外存文件中传送数据,为写文件,使用规定的"写语句";将外存文件中的数据向内存传送,为读文件,使用规定的"读语句"

文件缓冲区:对文件进行读写操作时,VB在内存开辟一个"文件缓冲区",从文件中读取的内容到内存数据区、从内存数据区向文件中写入的内容都必须先送到缓冲区。使用"文件缓冲区"的好处可提高文件对文件读写的速度。一个打开的文件对应一个缓冲区,每个缓冲区有一个缓冲区号,即后面涉及到的文件号。

4.顺序文件及操作

顺序文件:是文件中记录的写入,存放与读出三者的顺序是一致的,即记录的逻辑顺序与物理顺序相同。顺序文件以ASCII码方式存放数据,可用文本编辑软件显示和编辑。

顺序文件结构简单,记录可不等长,读出某一条记录速度慢,不能直接对文件进行修改,适宜于对文件顺序批量处理。

打开语句形式:Open文件名For读写方式As[#]文件号(Len=记录长度]

文件名可以是用双引号引括起的字符串常量,也可是字符变量(此时无"");读写方式有:OUTPUTINPUTAPPEND;文件号1-511;记录长度表示缓冲区的字符数。

[注意]

当对一个己存在的文件进行OUTPUT方式打开,则原有数据全部删除。

写语句:Print#文件号,[输出列表  Write#文件号,[输出列表]

两种语句区别:后者输出在数据项之间自动插入"",并给字符串加上双引号,以区分数据项和字符串类型;而前者无。对多个数据项,也可用记录变量名表示。

读语句:       INPUT#文件号,变量列表

       LINEINPUT#文件号,字符串变量     (注意:回车换行符不读入;

       INPUT$(读取的字符数,#文件号)     包括回车换行符时读入)

关闭文件:    Close[[#]文件号]

常用函数:    LOFEOFLOC

5.随机文件及操作

随机文件:文件中所有记录等长、各数据项长度固定,每个记录有唯一的记录号,读写文件按记录号对该记录读写,文件以二进制代码形式存放数据。随机文件适宜对某条记录进行读写操作。

记录:一般用TYPE ENDTYPE记录类型定义,然后再声明记录变量。

打开语句形式:Open文件名For Random As #文件号[Len=记录长度)

记录长度:通过Len(hE录类型)自动获得。

写语句:Put[#]文件号,[记录号],变量列表或记录变量名

读语句:Get[#]文件号,[记录号],变量列表或记录变量名

省略记录号,则表示在当前记录后插入或读出一条记录。

 9.3  常见错误和难点分析

1.文件系统的三个控件不能产生关联

也就是当驱动器改变时,目录列表框不能跟着相应改变;或者当目录列表框改变时,文件列表框不能跟着相应改变。要三个控件产生关联,使用下面两个事件过程:

       Private Sub Drivel_Change()

              Dirl.Path=Drivel.Drive

       End Sub

       Private Sub Dirl_Change()

              Filel.Path=Dirl.Path

       End Sub

2.如何在目录列表框表示当前选定的目录

在程序运行时双击目录列表框的某目录项,则将该目录项改变为当前目录,其Diirl.  Path的值作相应的改变。而当单击选定该目录项时,Diirl.  Path的值并没有改变。有时为了对选定的目录项进行有关的操作,与ListBox控件中某列表项的选定相对应,表示如下:

Dirl.List(Dirl.Listlndex)

3.当使用文件系统控件对文件进行打开操作时,显示"文件未找到"出错信息

例如,如下语句:

Open Filel.Path+Filel.File Name For Input As#1

当选定的目录是根目录,上述语句执行正确;而当选定的目录为子目录,上述语句执行时显示"文件末找到"出错信息。

其中:Filel.Path表示当前选定的路径,Filel.File Name表示当前选定的文件,合起来表示文件的标识符。

当选定的文件在根目录下(假定驱动器为C)Filel.Path的值为"C:/1",假定选定的文件名为"t1.txt",则Filel.Path+Filel.FileName的值为"C:/t1.txt",为合法的文件标识符。

当选定的文件在子目录下(假定驱动器为C,子目录为my)Filel.Path的值为"C:/my" Filel.Path+Filel.FileName的值为"C:/my tl.txt",子目录与文件名之间少了一个"/"分隔符。

为了保证程序正常运行,OpenFilel.Path+Filel.FileNameForlnput As#1改为:

       Dun F$

       If Right(Filel.Path1)"/" Then      ' 表示选定的足根目录

              F=Filel.Path+Filel.FileName

       Else                      ' 表示选定的是子目录,子目录与文件名之间加"/"

              F=Filel.Path+"/"+Filel.FileName

       End If

              Open F For Input As # 1

4Open语句中欲打开的名是常量也可以是字符串变量,但使用者概念不清,导致出现"文件未找到"出错信息

如在从盘上读入文件名为"C:/my/t1.txt"

正确的常量书写如下:

       Oven  "C:/my/t1.txt"For Input As#1    ' 错误的书写常量两边少双引号

或正确的变量书写如下:

       Dim F$

       F="C:/my/t1.txt"

       Open F For Input As #1 ' 错误的书写变量F两边多了双引号

5.文件没有关闭又被打开,显示"文件已打开"的出错信息

如下语句:

       Open"C:/my/t1.txt"  For Input As #1

       Print F

       Open "C:/my/t1.txt"  For Input As #1

       Print"2"F

执行到第二句Open语句时显示"文件已打开"的出错信息。

6.如何读出随机文件中的所有记录,但又不知道记录号

不知道记录号而又要全部读出记录,则只要同顺序文件的读取相似,采用循环结构加无记录号的Get语句即町,程序段如下:

              Do While Not EOF(1)

                     Get #1, , j

                     Print j

              Loop

       EndSub

随机文件读写时可不写记录号,表示读时自动读下一条记录,写时插入到当前记录后。

 
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值