Visual Basic 2008应用程序开发实例精讲
上QQ阅读APP看本书,新人免费读10天
设备和账号都新为新人

第1篇 VB2008基础知识

第1章 Visual Basic 2008.NET入门

Microsoft .NET是一个非常激动人心的、重大的技术变革。Visual Studio 2008(简称VS 2008)更是一个功能强大完善的开发平台。本章引导大家初步认识一下VB 2008。

1.1 .NET Framework概述

随着.NET Framework和Visual Studio.NET的引入,Microsoft使得Windows应用程序和Web应用程序的编写发生了重大的变革。这些新产品使Visual Basic程序开发产生了很大的变化。.NET不但为Visual Basic语言带来了真正的面向对象的编程,并且使跨平台兼容开发变得更容易。

.NET的两个主要组成部分是Microsoft .NET Framework SDK(软件开发工具包)和Visual Studio IDE(集成开发环境)。IDE用来开发程序,而Framework则是支持程序运行的运行库。注意,目前的Windows系列的操作系统都没有内置的.NET Framework SDK,所以要在Windows系列的操作系统上运行用Visual Studio IDE开发的程序,一定要先在计算机上装好.NET Framework。

.NET Framework为开发和运行在不同平台、不同语言编写的应用程序以及XML Web服务提供了一个平台。.NET Framework 由公共运行库(CLR)、类库(Class Library)和ASP.NET组成,ASP.NET是基于组件的动态服务器页面。

摘自太平洋电脑网http://www.pconline.com.cn/pcedu/softnews/cs/0707/1049507.html。微软在2007年11月底发布的Visual Studio 2008和.NET Framework 3.5更是受到开发者的青睐。Microsoft .NET Framework 3.5是一个新的Windows编程框架,它包含了.NET Framework version 2.0的所有技术,并融入了大量新技术,例如 Windows Workflow Foundation(WF)、Windows Communication Foundation(WCF)、Windows Presentation Foundation(WPF)和Windows CardSpace, .NET Framework 3.5在这些新增功能的基础上增量构建而成。此外,.NET Framework 3.5还包含若干技术领域中的大量新功能,它们以新程序集的形式添加,以避免重大更改。这些新功能包括:

(1)与语言集成查询(LINQ)和数据感知紧密集成。借助这个新功能,您可以使用相同的语法,在任何支持LINQ的语言中编写相关代码,以筛选和枚举多种类型的SQL数据、集合、XML和数据集,以及创建它们的投影。

(2)利用ASP.NET AJAX可以创建更有效、更具交互性、高度个性化的Web体验,这些体验在所有最流行的浏览器上都能实现。

(3)用于生成WCF服务的全新Web协议支持,包括AJAX、JSON、REST、POX、RSS、ATOM和若干新的WS-*标准。

(4)Visual Studio 2008中面向WF、WCF和WPF的完整工具支持,其中包括支持工作流的服务这一新技术。

(5).NET Framework 3.5基类库(BCL)中的新类可满足许多常见的客户请求。

注意 如果安装有.NET Framework 3.5的早期预发行版本(如:测试版),则运行此安装之前,必须使用“添加/删除程序”卸载那些预发行版本。

1.2 Visual Basic 2008.NET的新特性本节内容初学者看不太懂没关系,可以跳过此节或者查阅VS 2008的MSDN帮助。

1.Visual Basic语言中的新增功能

Visual Basic 2008引入了新的语言功能,其中包括局部类型推理、对象初始值设定项、匿名类型和扩展方法。这些功能是对一项很重要的新功能语言集成查询(LINQ)的支持,但是它们单独使用时也很有用。

(1)查询(Visual Basic)

使用 Visual Basic 可以在代码中创建语言集成查询(LINQ)表达式。语言集成查询(LINQ)为 Visual Basic 添加了查询功能,并且提供了用于处理各种数据的简单而强大的功能。LINQ引入查询作为Visual Basic语言的一部分,而不是向数据库发送要进行处理的查询,或者对要搜索的每种类型的数据使用不同的查询语法。它使用与数据类型无关的统一语法。

使用LINQ可以从SQL Server数据库、XML、内存中数组和集合、ADO.NET数据集或任何其他支持LINQ的远程或本地数据源查询数据。利用常见的Visual Basic语言元素即可执行上述所有操作。因为查询是用Visual Basic语言编写的,所以查询结果以强类型对象的形式返回。这些对象支持IntelliSense,后者使您可以更快地编写代码,并且在编译时而不是运行时捕捉查询中的错误。LINQ 查询可用作其他查询的源,以优化查询结果。还可以将这些查询绑定到控件,以便用户可以轻松地查看和修改查询结果。

(2)Visual Basic中的 XML

您可以在Visual Basic代码中包含XML作为一类数据类型,从而可以更加便捷地创建、转换、修改和查询XML。

(3)局部类型推理

使用局部类型推理(也称为“隐式类型转换”),编译器可根据初始化局部变量所用的值来确定局部变量的数据类型。

(4)对象初始值设定项:命名类型和匿名类型

使用对象初始值设定项,可以初始化表达式中的复杂数据对象,而不必显式调用构造函数。

(5)匿名类型

使用匿名类型功能可以不必先编写类定义即创建新数据类型的实例。编译器会根据声明该实例时所指定的属性来创建数据类型定义。

(6)扩展方法(Visual Basic)

使用扩展方法可以从某个数据类型外部向该类型添加方法。这些方法可以像该数据类型的普通实例方法那样调用。

(7)Lambda表达式

Lambda表达式是一种无名函数,可在委托类型有效的任何地方使用。

2.Visual Basic编译器的新增功能

(1)友元程序集

您可以通过将其他程序集标识为Friend程序集,来使标记为友元程序集的成员可用于其他程序集。使用 InternalsVisibleToAttribute 属性可为您的程序集标识一个或多个 Friend程序集。此操作对已签名的和未签名的程序集都适用。

(2)新命令行选项

Visual Basic 2008包括两个新的编译器选项:

· /optioninfer选项用于启用变量声明中的局部类型推理。

· /moduleassemblyname选项用于指定包含模块的程序集的名称。

1.3 安装VS 2008.NET

1.3.1 VS 2008.NET系统软硬件要求

(1)支持的操作系统:Windows Server 2003; Windows Vista; Windows XP

(2)硬件要求:

· 配备1.6 GHz或更快的处理器的计算机

· 384 MB或更大的内存(对于Windows Vista,需要768 MB或更大的内存)

· 2.2 GB的可用硬盘空间

· 5400 RPM硬盘

· 1024×768或更高分辨率的显示器

· DVD-ROM驱动器

1.3.2 VS 2008.NET安装步骤

首先准备好安装文件,建议读者到网上下载,下载的一般都是Iso格式的文件,那么读者可以安装一个虚拟光驱,把下载后的文件载入虚拟光驱,下面就可以开始安装了。

[1] 双击虚拟光驱(如果是用光盘安装,从光盘上自动运行即可),然后就会弹出如图1-1所示的Visual Studio 2008(简称VS 2008)安装程序界面(1)。

图1-1 VS 2008安装程序界面(1)

[2] 单击图1-1上的“安装Visual Basic 2008”,弹出VS 2008安装程序加载需安装的组件对话框,如图1-2所示。

图1-2 VS 2008安装程序加载需安装的组件

[3] 等待第2步加载完成后,单击“下一步”,弹出VS 2008安装程序起始页,如图1-3所示,在这个对话框中会告诉你已检测到计算机上安装了哪些组件,还需要安装哪些组件(注意,如果您是第一次安装VS 2008,那么可能检测到的已安装组件就没有,要安装的组件就会多些)。在该对话框中选中“我已阅读并接受许可条款”前的单选按钮。

图1-3 VS 2008安装程序起始页

[4] 单击“下一步”按钮,弹出如图1-4所示的VS 2008安装程序选项页。在该对话框中选择要安装的功能及安装的路径。

图1-4 VS 2008安装程序选项页

[5] 单击“安装”按钮,弹出如图1-5所示的VS 2008安装程序安装页,将逐个安装组件,此过程较长。

图1-5 VS 2008安装程序安装页

[6] 待图1-5中的所有组件安装完毕,弹出如图1-6所示的VS 2008安装程序完成页。

图1-6 VS 2008安装程序完成页

[7] 单击“完成”按钮,弹出如图1-7所示的VS 2008安装程序界面(2)。

图1-7 VS 2008安装程序界面(2)

至此,VS 2008就安装完毕,如果不想安装其他的可以单击“退出”按钮,完成安装。但建议读者再接着安装下一个 MSDN 帮助文档,方便以后查阅,这个对于学习来说非常重要。在此,继续安装“安装产品文档”。

[8] 单击“安装产品文档”,弹出如图1-8所示的MSDN安装程序加载安装组件页。

图1-8 MSDN安装程序加载安装组件页

[9] 待安装组件加载完成后,单击“下一步”按钮,弹出如图1-9所示的MSDN安装程序起始页。在该对话框中选中“我已阅读并接受许可条款”前的单选按钮。

图1-9 MSDN安装程序起始页

[10] 单击“下一步”按钮,弹出如图1-10所示的MSDN安装程序选项页,同样在该对话框中选择要安装的功能及安装的路径。在此选择“完全”安装。

图1-10 MSDN安装程序选项页

[11] 单击图1-10上的“安装”按钮,弹出如图1-11所示的MSDN安装程序安装页,此过程也较长。

图1-11 MSDN安装程序安装页

[12] 待上步的组件安装完成之后,弹出如图1-12所示的MSDN安装程序完成页,单击“完成”按钮。

图1-12 MSDN安装程序完成页

至此,整个VS2008就安装完成了。

1.4 VB 2008.NET集成开发环境

1.4.1 IDE启动界面

在上一节VS 2008安装完成之后,接下来我们可以启动VS 2008,并真正开始学习VB 2008了。单击“开始”|“程序”|“Microsoft Visual Studio 2008”,第一次启动时会弹出如图1-13所示的集成开发环境(IDE, Integrated Development Environment)默认环境设置对话框,在此我们选择“Visual Basic开发设置”。

图1-13 默认环境设置

然后单击“启动Visual Studio”按钮,弹出如图1-14所示的配置所选择的环境提示框。

图1-14 第一次使用配置环境提示

待环境配置完成后,进入如图1-15所示的IDE起始页。

图1-15 集成开发环境起始页

单击“创建”右边的“项目”,弹出如图1-16所示的新建项目对话框。在项目类型中选择“Visual Basic”,模板选择“Windows窗体应用程序”,单击“确定”按钮进入VB 2008环境。

图1-16 “新建项目”对话框

1.4.2 主体窗口界面介绍

VB 2008的主界面如图1-17所示。

图1-17 VB 2008开发环境主体界面

从主界面可以看出,VB 2008为多窗口工作环境。每一窗口在屏幕上的位置,都可以按开发者的需要进行调整,包括任意停靠、隐藏、拖放和切换等。各项功能说明如下。

1.标题栏

主界面最上面深蓝色的为标题栏,在标题栏左侧显示文件名,右侧提供窗口控制按钮。

2.菜单栏

标题栏下面即为菜单栏,横列着若干菜单,每个主菜单下面还有系列下拉菜单项,每个菜单项可能还有一些小菜单。每个主菜单项的功能参见下一节。

3.工具栏

菜单栏下面是若干工具栏,每个工具栏上都有系列的图标对应一些操作,通常都是最常用的图标在上面,为用户提供了图形化的快捷方式。默认的只有标准工具栏显示出来了,如果需要显示与关闭工具栏,可以通过菜单“视图”|“工具栏”选择相应的工具栏名称。如果在工具栏名称前有钩,表示当前此工具栏显示在IDE中,否则没有显示出来。

4.主工作区

工具栏下方中间最大的一块区域是整个IDE的主工作区,包括窗体界面设计工作区和编程过程中的代码输入区域。在图1-17看到的只是窗体界面设计窗口,可以将控件直接拖放到窗体上,提供所见即所得的设计界面。要进入代码输入窗口,通常有三种方法。

· 单击如图1-18所示的Form1.vb*,即可进入代码编辑窗口。实际上,主工作区是一个卡片式的窗体,通过卡片显示与隐藏不同的窗口。同理要进入窗体设计窗口,单击Form1.vb[设计]*。

图1-18 卡片式窗体

· 单击解决方案资源管理器窗口下的第四个“查看代码”按钮,如图1-19所示。要进入窗体设计窗口,可单击第五个按钮“查看设计器”。

图1-19 “查看代码”按钮

· 双击某个控件

5.工具箱

在主工作区左边的是工具箱,工具箱里有若干可上下弹开的按钮,每个里面都有设计窗体时或开发时常用的工具。

6.解决方案资源管理器

在主工作区的右边的上部分通常是解决方案资源管理器窗口,该窗口是用来管理当前解决方案内所包含的模块、组件、项目等。

7.属性窗口

在主工作区的右边的下部通常是属性窗口,该窗口是用来设置编程对象的属性,通过属性设置可以控制对象的状态及格式。

1.4.3 窗口菜单作用

在了解了主界面的各模块功能之后,现在再来了解一下各个菜单项的主要作用。

1.文件

提供与文件整体操作有关的命令,如新建项目、打开文件、打开项目、最近使用的文件、最近使用的项目等。

2.编辑

“编辑”菜单项是一般窗口应用程序最普遍的菜单之一。这个菜单项下的命名主要针对程序代码,如撤销、重复、剪切、复制、粘贴、快速查找、快速替换等。

3.视图

“视图”菜单项主要用来显示与隐藏某些窗口,例如属性窗口、工具箱、工具栏、其他窗口及全屏显示代码窗口等。

4.项目

“项目”在 VB.NET 开发的应用程序中,扮演着一个关键性的角色,可以通过它在项目中加入窗体与其他选项,例如模块、类、组件及设置当前应用程序的属性等。

5.生成

该菜单项主要用于对程序进行编译,生成可执行文件。但是,该生成文件不能被自动执行。

6.调试

提供程序调试所需的命令,例如启动调试、逐语句、逐过程、异常等,并可将调试成功的程序生成可执行文件。

7.数据

该菜单项用于配置数据适配器、生成数据集,并可用于查看数据集结构。

8.格式

“格式”菜单让用户对一群选择的控件进行位置、大小的设置与微调,或者是重叠控件垂直位置的调整,甚至可以将控件设置为“锁定”状态,以免无意间更动了控件的位置或大小。

9.工具

用于存放工具类命令组,包括连接到设备、连接到数据库、连接到服务器、自定义工具箱、ATL/MFC跟踪工具、Spy++、外部工具等。这些工具可以定制工具箱,定制整个主界面、调用外部控件、使用外部工具等。

10.窗口

用于控制窗口的操作命令均存放于此菜单下,如拆分窗口、把窗口设置为可停靠或浮动等、重置窗口布局、新建水平选项卡组、新建垂直选项卡组等。

11.帮助

用于提供一系列的帮助命令,包括搜索、目录、索引、动态帮助等。

1.4.4 主要开发类窗口

VB 2008开发环境中,包括了以下主要的子窗口。

1.工具箱

工具箱如图1-20所示,提供设计时各类型控件的选择,包括Windows窗体、菜单和工具栏、数据及组件等控件类型。在工具箱中的每个“控件”实际上都是一个“类”的“对象”,都有着自己的属性和方法。设计人员有两种方式选择控件:

图1-20 工具箱

· 双击自己需要的控件,根据控件的不同类型分别到窗体设计器不同位置,或者到窗体设计器的左上角或者到窗体设计器面板的下面。

· 点选工具箱中的控件,然后放到窗体适当的位置,并调整大小。

为了便于自己的控件与组件,可以创建自己的选项卡或者删除选项卡。

· 创建选项卡的方法是:在工具箱中右击,弹出如图1-21所示的快捷菜单,选择“添加选项卡”菜单项,然后在工具箱的底部就会出现要求输入工具箱的名称的文本框,输入一个名称后就创建完毕。

图1-21 快捷菜单

· 删除选项卡的方法是:在工具箱中选中需要删除的选项卡的名称右击,弹出如图1-21所示的快捷菜单,选择“删除选项卡”菜单项。

图1-22 快捷菜单

2.解决方案资源管理器

“解决方案资源管理器”窗口(如图1-23所示)用于管理当前解决方案内所包含的模块、组件、项目等。所谓“方案”,就是 VS.NET 中的工作基础包。一个方案能够保存很多不同类型的项目。在“解决方案资源管理器”中,以树形结构显示项目内容,包括项目名、文件夹、文件、资源和其他定义当前工作范围的杂项数据。

图1-23 解决方案资源管理器窗口

在“解决方案资源管理器”窗口中,单击“显示所有文件”按钮,则会显示所有项目及其包含的隐藏文件。单击“查看代码”按钮,则可进入代码编辑窗口。单击“查看设计器”按钮,则会进入窗体设计器窗口。

通过“解决方案资源管理器”窗口可以添加新项目,只要右击应用程序的名称,就会弹出一个快捷菜单,然后选择“新建项…”,如图1-24所示。之后会弹出如图1-25所示的“添加新项”对话框,先在左侧选择类别,然后在右边选择自己所需要的项目后单击“添加”即可。

图1-24 解决方案资源管理器快捷菜单

图1-25 “添加新项”对话框

3.属性窗口

属性窗口(如图1-26所示)提供程序设计人员在设计时,对窗体、控件等对象设置其相关的属性。程序设计人员可以在窗体设计窗口选择任何对象,然后到属性窗口修改属性,或是从图1-26中的下拉列表框中选择对象,然后设置其属性。默认的属性排列方式是按分类排序,也可以单击“按字母排序”按钮,把它改为按字母顺序排序。

图1-26 属性窗口

4.服务器资源管理器

“服务器资源管理器”的窗口如图1-27所示,可以管理网络环境的服务器以及连接到数据库。有了服务器资源管理器,程序开发人员再也不需要在机房与办公室之间疲于奔波,或者安装一大堆管理工具。通过服务器资源管理器,那些远程服务器都在你的开发工具内,只要有足够的权限,随时可以添加、启动或暂停服务、查看事件记录、获取性能计数器或是连接到数据库查询数据、维护数据库。

图1-27 服务器资源管理器窗口

1.4.5 动态帮助

VS.NET 提供了动态帮助系统,它会根据开发者当前的鼠标指针或输入光标所在位置在动态帮助窗口中提供相应的主题,供开发者查阅。单击“帮助”|“动态帮助”,然后“动态帮助”窗口就会显示出来,如图1-28所示。

图1-28 动态帮助窗口

提示 要想动态帮助窗口起作用,在安装.NET 时必须安装 MSDN。对于使用.NET的程序员来说,MSDN历来都是首选的开发帮助文档。有的用户在开发中遇到问题了,却舍近求远到处发文章求助,岂不知,最好的帮助就在身边。

1.5 我的第一个.NET应用程序

这一节我们来创建一个实例应用程序,以说明创建VB.NET应用程序的步骤。该实例的功能是求两个整数之和。在窗体上的文本框中输入两个整数,单击“求和”按钮,结果通过标签在窗体上显示出来。

1.创建VB.NET工程

[1] 启动VS 2008.NET,启动后的界面如图1-29所示。

图1-29 VS 2008.NET启动后的界面

[2] 单击“创建”右边的“项目”,弹出如图1-30所示的“新建项目”对话框。

图1-30 “新建项目”对话框

[3] 把名称改为“求两数之和”,模板选定“Windows窗体应用程序”,单击“确定”按钮。即可进入VB.NET的IDE环境,如图1-31所示。

图1-31 IDE主界面

2.设计应用程序界面同时修改对象的属性

[1] 把Form1窗体对象的Text属性修改为“我的第一个.NET应用程序”; MaximizeBox属性修改为False,使最大化按钮无效。

[2] 向窗体引入标签Label1,并修改其Text属性为“第一个数:”,调整到适当的位置;接着向窗体添加一个TextBox1控件,修改其Name属性为“TxtNum1”,并调整它的位置及大小。

[3] 向窗体再添加一个标签Label2,并修改其Text属性为“第二个数:”,调整到适当的位置;接着向窗体添加一个TextBox2控件,修改其Name属性为“TxtNum2”,并调整它的位置及大小。

[4] 向窗体添加一个显示结果的标签Label,修改其Name属性为LblResult, Text属性为空;最后添加一个用来触发事件的按钮 Button,修改其 Name 属性为 BtnAdd, Text属性为“求和”,并调整位置及大小。最终界面如图1-32所示。

图1-32 设置好界面的窗口

提示 调整对象大小,只要选定对象,用鼠标拖动周围的八个控制点。为了界面更美观或快速调整多个对象的大小及位置,可以利用“格式”菜单下的相应命令。

3.编写程序代码

双击求和“BtnAdd”按钮,即进入代码编写窗口,且首尾两行代码自动生成,如图1-33所示。我们只要在其中(Sub和End Sub之间)输入实现程序功能的代码即可。本实例的代码及解释如下:

图1-33 代码编辑窗口

Private  Sub  BtnAdd_Click(ByVal  sender  As  System.Object,  ByVal  e  As System.EventArgs) Handles BtnAdd.Click
      Dim FirstNum As Integer  ’定义第一个整型变量用于存放第一个数
      Dim SecondNum As Integer  ’定义第二个整型变量用于存放第二个数
      FirstNum = TxtNum1.Text  ’把第一个文本框输入的值赋给第一个变量
      SecondNum = TxtNum2.Text  ’把第二个文本框输入的值赋给第二个变量
      LblResult.Text = FirstNum + SecondNum  ’把两个变量的值相加后的结果赋给结果标签LblResult
End Sub

提示 也可以通过前面所讲的其他方法进入代码编辑窗口,在此就不赘述了。

4.保存及运行调试

[1] 单击工具栏上的“全部保存”按钮或单击菜单“文件”|“全部保存”,即会弹出如图1-34所示的“保存项目”对话框,一般选择好保存位置,单击“保存”按钮。

图1-34 “保存项目”对话框

[2] 单击工具栏上的“启动调试”按钮或单击菜单“调试”|“启动调试”或直接按F5键即可运行应用程序,如图1-35所示。然后输入数据进行验证程序的功能。如果在编译的过程中发生错误,就会出现警告对话框。单击“否”按钮,则会停止继续编译,并显示出错误的原因。修改错误,继续进行代码调试直至成功。

图1-35 程序运行窗口

5.创建可执行文件

与以往版本不同的是,VB.NET 并没有专门的生成应用程序(.exe)的选项,应用程序在工程建立的同时就已生成,保存在工程目录“Obj\Debug\Temp”中,但是这时的应用程序仅仅完成显示界面的功能,而不完成程序本身的功能。在经过至少一次的编译后,这个可执行文件就有了用户所要求的功能,同时在工程目录“Obj\Debug”中,生成了与工程同名的应用程序,且每次的编译都会随时更新最新的功能。

6.发布应用程序

发布应用程序就是要生成可以脱离编译环境的安装文件,使其能够方便地在其他机器上安装使用,具体步骤参见本书最后的附录。

1.6 本章小结

本章简单介绍了.NET Framework概念、.Visual Basic 2008的新特性、Visual Studio 2008的整个安装过程、VB 2008的IDE的各个组成部分及其应用功能,并通过一个实例详细介绍了运行 VB 2008开发应用程序的一般步骤。通过本章的学习,读者将初步了解.NET Framework,学会安装VS 2008,并掌握利用IDE开发应用程序的一般步骤。

第2章 Visual Basic.NET编程基础

本章详细介绍Visual Basic.NET的编程基础知识。主要内容包括:VB.NET的数据类型、常量与变量、自定义结构体、数组、运算符和表达式、结构化控制语句、面向对象编程的概念、对象和类的概念、控件的常用属性、API函数的运用。

2.1 基础编程知识

2.1.1 关键字及标识符

1.关键字

关键字又称为保留字,是由系统自定义的符号,不允许在编写程序中定义与关键字相同的标识符。关键字都有着特定的含义,并在程序中有着不同的作用。常见的关键字有如下一些。

如果想了解Visual Basic.NET“关键字”更详细的内容,可以参阅Visual Basic.NET的帮助系统,选择“帮助”|“搜索”命令,打开“搜索”窗口,在“查找”列表框中输入查找对象“Visual Basic.NET关键字”,然后在“查找结果”中双击“Visual Basic.NET关键字”,便可以显示所有关键字列表。

2.标识符

(1)语法元素编写程序时,将会使用到许多语法元素,这些语法元素都必须有正确的命名。标识符在程序中由程序员按照命名规则自行定义,用来标识常量、变量、数组、函数、过程、文件、窗体、控件等各种语法元素。

(2)Visual Basic.NET标识符的命名规则如下:

· 标识符第一个字符只能是字母或者下划线“-”。

· 从第二个字符开始可以使用字母、下划线、十进制数字作为标识符。

· 标识符以下划线开头,下划线后面至少要有一个字母或者十进制数字。

· 标识符不能与任何关键字同名。

· 不能在对象名、属性名、方法名、变量名、关键字的中间断开。

例如:I、J、k、sum、student_1、_Number 等是合法的标识符,但1abc、a-b、a' b、As、Dim等都不是合法的标识符。

(3)标识符命名的建议(非强制性规则)如下:

标识符命名最好能做到“见名知意”,这样便于记忆,同时也增强了程序的可读性。例如表示“总和”或者“平均值”这样的数据,取sum、average作为变量,程序阅读起来就更加容易。Visual Basic.NET 中标识符命名一般取英语的对应单词,不使用缩写。当然英文不好的使用中文拼音也可以。

Visual Basic.NET中标识符不区分大小写,例如“AverageScore”与“averagescore”表示同一个变量名,不过很显然,“AverageScore”的可读性更好。

在Visual Basic.NET中有两种标准的命名规范。

· 每个单词的首字母大写。

· 除第一个单词外,其余单词的首字母都大写。

标识符的长度没有特定的限制,但不同的编译系统可以区分的有效标识符长度是不同的。一般要求在“见名知意”的前提下,字符个数尽可能少。

3.其他符号

(1)注释符

为了便于阅读和理解程序,可以在某一条语句的前一行或者同一行尾部加上注释,解释程序段或语句的功能。Visual Basic.NET的注释符为单引号“' ”,即使输入中文的单引号,也会自动变成英文的单引号。

利用工具栏上的“注释选定行”和“取消对选定行的注释”按钮,可以给多行代码添加或取消注释。

在一个程序中,适当的注释不仅有助于编程者记忆各个模块的功能和标识符的意义,同时还可以帮助其他阅读者理解源程序,过了一段时间自己来阅读源程序也会觉得非常轻松。

注意 注释符及注释内容在程序编译执行过程中不被编译,只是辅助程序编写或者阅读的解释性文字。

(2)续行符

续行符的符号为空格+下划线“_”,其作用是把一条很长的语句写在多行中,这样可以在不使用水平滚动条的情况下阅读代码编辑器中的代码。

例如:

Private Sub HScrollBar1_Scroll(ByVal sender As Object, ByVal e _
   As System.Windows.Forms.ScrollEventArgs) Handles HScrollBar1.Scroll

(3)同行符

编写程序的时候,语句的常规书写习惯是一条语句占用一行,如果需要在一行中书写多条语句,就需要使用“同行符”。Visual Basic.NET中的“同行符”为冒号“:”。

例如:i=1:j=0表示两条语句。

注意 为了提高程序的可读性,减少出错,建议一行只写一条语句。

2.1.2 数据类型

数据可以说是程序的基础,决定着计算机如何存储变量。计算机在为变量分配空间时,首先就要根据变量的类型来决定内存的分配。下面将主要介绍Visual Basic.NET的基本数据类型。

1.Numeric数据类型

Visual Basic.NET支持多种类型的Numeric数据类型,这些类型包括:Integer(整型)、Long(长整型)、Single(单精度浮点型)、Double(双精度浮点型)以及新增的 Decimal (十进制型)和Short(短整型),但是少了Current(货币型)。

如果知道变量总是存放整数(如10),而不是小数(如10.01),最好将其声明为Integer类型、Long类型或Short类型。整数的运算速度较快,而且比其他数据类型占据的内存要少。在 For…Next 循环内作为计数器变量使用时,整数类型尤为有效。Decimal 数据类型不但取代了Visual Basic以前版本的Current类型,而且是Visual Basic.NET构架中的通用数据类型,浮点(Single和Double)数比Decimal类型的有效范围大得多。表2-1对数字数据类型进行了归纳。

表2-1 Visual Basic.NET的Numeric数据类型

2.Byte数据类型

如果变量包含二进制数据,则将它声明为 Byte 类型。除一元减法之外,所有可对整数进行的运算符均可操作Byte数据类型,因为Byte类型在Visual Basic.NET中占的存储位数是8位,表示的是从0~255之间的无符号整数类型,不能表示负数。因此,在进行一元减法运算时,Visual Basic.NET首先将Byte转换成符号整数。Byte数据类型可以转换成Integer、Long、Short、Single、Double或Decimal类型,不会出现溢出的错误。

3.String数据类型

如果要声明的变量为字符串,就把它声明为String类型,它是一个可变长的字符串数据类型,一个字符串最长可以包含大约2亿个Unicode字符。声明字符串变量的语法格式如下:

Dim s As String

然后可以对该变量s赋值,并用字符串函数对它进行操作,例如:s=“Visual Basic.NET”。

对String类型数据操作的基本函数有如下几个:

(1)Len函数

Len 函数返回字符串的长度,Len 函数的返回值是长整型,语法格式:Len(String Expression)。

说明:String Expression为有效的字符串表达式。例:

' 初始化字符串
Dim TestString As String = "Hello World"
' 返回结果11
Dim TestLen As Integer = Len(TestString)

(2)Trim、LTrim和RTrim

返回一个字符串,该字符串包含指定字符串不带前导空格(LTrim)、不带尾随空格(RTrim)或同时不带前导和尾随空格(Trim)的副本。例:

' 初始化字符串
Dim TestString As String = "  <-Trim->  "
Dim TrimString As String
TrimString = LTrim(TestString)   ' TrimString=" <-Trim->  "
TrimString = RTrim(TestString)   ' TrimString="  <-Trim-> "
TrimString = Trim(TestString)   ' TrimString=" <-Trim-> "

(3)Substring

Substring 返回从指定的字符位置开始且具有指定的长度的子字符串。它取代了以前VB版本的Right、Left、Mid函数。语法格式如下:

Str.Substring(StartPosition, Length)

例如:

'初始化变量
Dim TestString As String = "Hello World"
'结果为在TextBox1显示World
TextBox1.Text = TestString.Substring(6,5)

4.Boolean数据类型

Boolean数据类型的结果只有两个,即False或True。所以对于只有两个结果的变量通常声明为Boolean类型。不过Boolean类型数据仍占4个字节的存储空间。如果其他Numeric数据类型转换成Boolean数据类型,则0转换成False,非零均转换成True。Boolean数据类型的默认值为False。例如:

Timer1.Enabled=True

5.Date数据类型

Date(日期)和Time(时间)可包含在Date数据类型中,Date类型数据存储占用8个字节。数据范围从0001年1月1日凌晨0:00:00到9999年12月31日晚上11:59:59。Date变量必须以#开头和结束,格式为mm/dd/yyyy,如#2/4/2008#。

常用的时间日期函数比较多,例如:

· Today——设置或返回目前系统日期的函数。

· TimeOfDay——设置或返回目前系统时间的函数。

· Now——返回目前系统日期与时间的函数。

· Year(Datetime)——返回公元年的函数。

· Month(Datetime)——返回月(1~12)的函数。

· Day(Datetime)——返回日(1~31)的函数。

· WeekDay(Datetime)——返回星期(1~7)的函数。

· Hour(Datetime)——返回小时(0~23)的函数。

· Minute(Datetime)——返回分(0~59)的函数。

· Second(Datetime)——返回秒(0~59)的函数。

说明 以上参数Datetime表示一个Date类型的变量或常量。

6.Object对象数据类型

VB 6的Variant变体数据类型是一种特殊的“通用”数据类型,可以包括除定长字符串之外的各类数据。在VB.NET里,放弃了Variant这个类型,取而代之的是Object类型。Object 变量用作指向对象的指针,默认的数据类型相当于 Variant 变体数据类型。Object对象数据类型以32位(4个字节)的地址形式存储,此地址为对象引用。

7.枚举类型

当一个变量只有几种可能的值时,可以定义为枚举类型。所谓“枚举”,是指将变量的值一一列举出来,变量的取值仅限于列举出来的值的范围内。

枚举类型通过Enum语句来定义,格式如下:

[Public|Private] Enum类型名称
          成员名[=常数表达式]
          成员名[=常数表达式]
          ……
End Enum

对枚举类型的说明如下:

(1)Enum语句必须以Enum开头,以End Enum结束,各参数含义如下:

· Public:可选。表示所定义的Enum类型在整个项目中都可用,在默认情况下,Enum被定义为Public。

· Private:可选。表示所定义的Enum类型只在所声明的模块中可用。

· 类型名称:必需的。所定义的 Enum 类型的名称。“类型名称”必须给一个合法的Visual Basic.NET标识符,在定义Enum类型的变量或参数时用该名称来指定类型。

· 成员名:必需。是一个合法的Visual Basic.NET标识符,用来指定所定义的Enum类型组成元素的名称。

· 常数表达式:可选。元素的值可以是Byte、Short、Integer或Long类型,也可以是其他的Enum类型。如果不指定,则默认为Long类型。

(2)在 Enum 语句的格式中,“常数表达式”可以省略。在默认情况下,枚举中的第一个常数被初始化为0,其后的常数则被初始化为比其前面的常数大1的数值。例如:

Public Enum Days
    Sunday
    Monday
    Tuesday
    Wednesday
    Thursday
    Friday
    Saturday
End Enum

上面定义了一个枚举类型Days,它包括7个成员,都省略了“常数表达式”,因此常数Sunday的值为0,常数Monday的值为1,常数Tuesday的值为2,等等。

(3)可以用赋值语句显示给枚举中的常数赋值,所赋的值可以是任何长整数,包括负数。例如:

Public Enum MyColor
    Red=1
    Green=2
    Blue
End Enum

上面的枚举中,常数Red被赋值为1, Green被赋值为2,根据前面的规则,常数Blue的值为3。

(4)Visual Basic.NET 将枚举中的常数数值看作是整数。如果将一个浮点型的数值赋给一个枚举中的常数,Visual Basic.NET会将该数值取整为最接近的整数。

(5)定义了枚举变量之后,如何使用这种枚举变量呢?例如要使用上例中 MyColor的Red,就必须这样引用:MyColor.Red,而不能单独使用Red。

8.各种数据类型的转换

在实际应用中有时我们需要进行不同数据之间的操作运算,这时就必须转换数据类型。VB.NET提供了两种转换数据类型的方法:一是通过转换函数实现,二是通过对象化转换方法实现。

(1)转换函数

VB.NET提供了几种转换函数,可用来将值转换成特定数据类型。例如,用CStr函数将整型数据转换成字符串String:

Dim intData as Integer
Dim strData as string
intData=8
strData=CStr(intData)

在表2-2中列出了常见的转换函数,以供读者参考。

表2-2 数据类型转换函数

注意 对目标数据类型,传递到转换函数的值必须是有效的,否则会发生错误。例如,如果想把Long型数转换成Integer型数,那么,Long型数必须在Integer数据类型的有效范围内。

(2)对象化转换方法

VB.NET已经是完全对象化的语言了,声明过的变量、常量、数组,甚至一个数字都可以看作一个对象,同时可以使用对象所具有的一切方法,其中就有数据类型转换方法。上面的例子中可以用ToString方法将数据转换成String类型。

Dim intData as Integer
Dim strData as string
intData=8
strData= intData. ToString

在表2-3中列出了常见的转换方法,以供读者参考。

表2-3 数据类型对象化转换方法

2.1.3 变量与常量

1.变量

在VB.NET中,变量就是用来存储在应用程序执行时会发生变化的值。一个变量在内存中占据一定的存储单元,一个变量中可以存放一个数据。每个变量应有一个名字。

(1)变量命名规则

变量命名规则与标识符的命名规则相同,主要有几下几条。

· 变量必须以字母或下划线开头;

· 变量中不能出现空格和符号;

· 变量不能使用关键字。

(2)变量的声明

使用变量前,一般需要先声明变量名和其类型,以决定系统为它分配的存储单元。任何变量都属于一定的数据类型,包括基本数据类型和用户定义的数据类型。变量声明语句的一般格式如下:

Declare|Public|Protected|Friend|Private|Shared|Static|Dim<变量名>  As数据类型[=初值]

在进行变量类型的声明时,要注意以下几点:

· 用Dim语句声明的变量可用于包含该Dim语句所在程序的所有代码。如果变量是在模块、类或结构内但在过程外声明的,则可以从模块、类或结构内的任何地方访问;如果变量是在过程或模块内部声明的,则只能从过程或模块的内部访问。

· Dim语句不但可以用来声明变量的数据类型,而且可以对变量进行初始化。例如:

Dim i as Integer=0
Public flag as Boolean=False
Private Btn as New Button

声明了3个变量,其类型分别为Integer、Boolean和Object,初始值分别是0、False和Button类的新实例。

· 如果在声明时不指定变量的初始值,VB.NET将把它们初始化为相应的数据类型的默认值。

· 一个 Dim 中可以声明多个变量,但如果多个变量的类型相同,则不能对其进行初始化。

· 应当把声明语句放在变量出现的区域(模块或过程)的开头。如果一个声明语句要初始化变量的值,则应在其他语句引用该变量之前执行。

· Static用于在过程中定义静态变量或数组。与Dim不同,如果用Static定义了一个变量,则每次引用该变量时,其值会继续保留。而当引用 Dim 定义的变量时,变量的值会被重新设置。通常把有Dim定义的变量称为动态变量,而把由Static定义的变量称为静态变量。例如下面事件过程中连续单击Button1按钮3次,其TextBox1显示的值最终为3;而如果把声明语句中的Static改为Dim,则结果总是1。

Private  Sub  Button1_Click(ByVal  sender  As  System.Object,  ByVal  e  As System.EventArgs) Handles Button1.Click
      Static i As Integer
      i = i + 1
      TextBox1.Text = i
End Sub

· Public用来定义全局变量,即此类型的变量在整个应用程序中都有效。

(3)Option Explicit语句

当Option Explicit设为On时(这是缺省情况),必须在使用变量前显示声明该变量,否则将产生编译错误。(Option Explicit On ' 将Option Explicit设为On)

当Option Explicit设为Off时,可以在代码中直接使用变量,即隐式声明该变量。这时该变量作为对象类型创建。虽然隐式声明变量比较方便,但会增加命名冲突和隐藏拼写错误并且会抵消使用内存。(Option Explicit off ' 将Option Explicit设为off)

2.常量

所谓常量是指在整个应用程序执行过程中其值保持不变的量。其声明语法格式是:

[|Public|Protected|Friend| Protected Friend ] Const <常量名> [As数据类型]=表达式

对此说明以下几点:

· 参数常量名必须是有效的标识符,它的命名规则与标识符的命名规则一样。“As数据类型”用来说明常量的数据类型。表达式由数值常数或字符串常数以及运算符组成,但在表达式中不能使用函数调用。例如:

Const conpi=3.1415926535
Public Const conMax  As Integer=100
Const conDate=#8/8/2007#
Const conName="china"

· 可以在一行中放置多个常数声明,但需要用逗号进行分隔。例如:

Const conpi=3.1415926535, Const conMax=100, conDate=#8/8/2007#

· 当定义常数后,就可以将其放置在代码中,使代码具有更高的可读性和可维护性。例如:

Const conpi=3.1415926535
Area=conpi*R^2

· 声明常量时可以在常量名后面加上说明符,如:

Const conpi#=3.1415926535
Const Str$="Hello"

常用的数据类型说明符如表2-4所示。

表2-4 常用的数据类型说明符

2.1.4 自定义结构体

用户自定义类型(UDT:User-Defined Types)在VB.NET中叫做Structure(结构),包含一个或多个不同种类的数据类型。尽管结构中的数据可以单独被访问,但是这些数据仍被认作是一个集合。在VB.NET以前的版本中,用户自定义类型的关键字是Type,现在改成Structure。

一个结构的定义以Structure关键字开始,以End Structure结束,结构中的元素可以是任意的数据类型的组合,包括结构。结构一旦定义出来后就可以被用作变量声明、参数传递以及函数的返回值等用途。定义一个结构的语法格式是:

[|Public|Private| Protected] Structure
      {Dim|Public|Private|Friend} 成员1  As 数据类型1
        ……
      {Dim|Public|Private|Friend} 成员N  As 数据类型N
End Structure

例如,下面定义了一个记录玩家的相关信息和设置值:

    Public Structure thePlayerInfo
        Public Score As Integer ’记录得分
        Public HeadColor As Color  ’蛇头填充色
        Public BodyColor As Color  ’蛇身填充色
        Public Food As Integer ’记录吃进的食物数量
        Public Bomb As Integer ’记录吃进的炸弹数量
        Public blnGameOver As Boolean ’标记该玩家是否已经game over
        Public SnakeLength As Integer ’蛇身长度
        '蛇头移动方向(值为 -1,0,1)
        Public X_Way As Integer
        Public Y_Way As Integer
End Structure

用户自定义数据类型占用内存空间是其包含的所有数据类型所占内存空间的总和。

2.1.5 数组

1.数组

在程序设计中,为了处理方便,把具有相同类型的若干变量按有序的形式组织起来,这些按序排列的同类数据元素的集合就称为数组。一个数组可以分解为多个数组元素,这些数组元素可以是基本数据类型或是引用类型。因此按数组元素的类型不同,数组又可以分为数值数组、字符数组、引用数组等各种类别。可以用数字(索引或下标)来引用数组中的元素。在许多场合,使用数组可以缩短和简化程序,特别是把数组与循环语句结合在一起,可以高效的处理多种情况。数组有上界和下界,索引的最大值和最小值分别对应着上界和下界,数组的元素在上下界内是连续的。因为VB.NET对每一个索引值都分配空间,所以不要轻易声明一个大的数组。

在VB.NET里,数组下界总是从0开始,不能定义数组的下界,这点和VB 6.0完全不相同,VB 6.0可以通过Option Base语句强制定义数组的下界起始值。一个数组中的所有元素具有相同的数据类型。当然,当数据类型为Object时,各个元素能够包含不同种类的数据(对象、字符串、数值等)。可以声明任何基本数据类型的数组,包括用户定义的类型和对象变量。

和VB 6.0一样,VB.NET中的数组也可以分为固定数组(总是保持同样的大小)和动态数组(在运行时可以改变数组的大小)。

2.固定数组的声明与使用

(1)一维数组

声明固定一维数组的一般语法为:

[Dim|Private|Public]数组名(上界)As数据类型={初始值}

说明如下:

· Public 为声明公用数组,且需在模块的声明段中用。Private 或 Dim 在模块的声明段中用可声明模块级数组。在过程中用Dim可以声明局部数组。

· 初始值为对数组进行初始化,若干个数组用逗号(“, ”)分隔。

· 声明数组时,在数组名之后跟一个用圆括号括起来的上界。上界不得超过 Integer数据类型的范围(-2147483648到2147483647)。

例如:

Dim IntCount(10)As Integer
Public Sums(15)As Long

以上第一个声明建立了一个11个元素的数组,其索引号从0~10。第二个声明建立了一个16个元素的长整型数组,其索引号从0~15,且为公用数组。

数组声明完后,就可以引用数组元素的值。其一般格式为:

数组名(下标)

需要注意以下两点:

· 下标可以是数值类型的常量、变量或表达式,如果下标值不是整数,系统自动按四舍五入取整。

· 下标值必须在声明数组时所指定的小标范围内,否则会出现“下标越界”的错误。

(2)多维数组

多维数组中,二维数组是用得最多的。所以在此仅说明二维数组的声明及使用,其他多维数组类似。

二维数组声明的语法格式为:

[Dim|Private|Public]数组名(上界1,上界2)As数据类型={{初始值}, {初始值}}

语法格式的含义与一维数组的含义基本相同,需注意的是,二(多)维数组的元素总个数是所有维数大小的乘积。例如:

Dim GBoard(13,13)As Boolean

该语句声明的GBoard数组共有14*14=196个元素。(注意数组下标从0开始)

二维数组的引用语法格式为:

数组名(下标1,下标2)

例如:GBoard(2, 3)=True实际上表示把逻辑值True赋给数组GBoard(13, 13)中位于第3行第4列的元素。

数组经常与循环语句结合在一起使用,进行高效的处理数据。例如:

Dim i As Integer
Dim j As Integer
For i = 0 To 13
        For j = 0 To 13
              GBoard(i, j) = True
        Next j
    Next i

关于循环结构的具体使用,在后面的“结构化控制语句”中详细讲解。

3.动态数组

数组到底应该多大才合适,有时候可能开始时不知道。所以希望能够在运行时具有改变数组维数大小的能力。动态数组就可以在任何时候改变数组维数的大小。由前面知道声明固定数组时必须指明数组的上界,然而在声明动态数组时不能指明数组界限信息,只声明其类型,即数组名后的“()”为空,若为多维数组,中间用“, ”分隔开每个维。声明完之后还不能直接赋值。在使用动态数组之前,必须用 ReDim 语句重新确定动态数组的上界大小,然后才可以对该数组赋值或引用它参与运算。

注意 ReDim语句不能改变数组维数的数目,只能改变每一维的上界大小。

例如:

Private MapProperty(, ) As Integer ’记录地图各个网格的属性, 为二维数组
MAX_COL_INDEX=30
MAX_ROW_INDEX=18
ReDim MapProperty(MAX_COL_INDEX, MAX_ROW_INDEX)
ReDim  Preserve  MapProperty(32, 20)

在上例中首先声明了一个整型的二维动态数组MapProperty,即每维的大小都不知道。然后用ReDim语句重新定义了数组的每一维大小。在最后一句中不仅用到了ReDim关键字,还用了Preserve关键字。关键字Preserve的作用是让数组在改变维的上界大小时保留改变前数组元素的值。因为若不使用关键字 Preserve,当重新改变维的上界大小后,该维的数组元素将全部被清空,但有时需要保留改变前数组元素的值,这个时候Preserve关键字就很有作用了。通常关键字 Preserve 与函数 Ubound(数组名,维数)一起使用,函数Ubound(数组名,维数)的作用是取指定的数组名指定维数的上界。

例如:下面一语句的作用就是重新定义MapProperty数组,保留数组MapProperty原来的内容,且在第二维增加10个元素。

ReDim Preserve MapProperty(32, Ubound(MapProperty,2)+10)

注意 Preserve 关键字只能改变多维数组中最后一维的上界。如果改变了其他维或最后一维的下界,那么运行时就会出错。

2.1.6 运算符与表达式

运算是对数据的加工。最基本的运算形式可以用一些简洁的符号来描述,这些符号称为运算符或操作数,被运算的数据称为运算量或操作数。VB.NET提供了丰富的运算符,可以构成多种表达式。

1.算术运算

算术运算是最常用的运算符,用来执行简单的算术运算。常见的算术运算符见表2-5所示。

表2-5 算术运算符

在这9种运算符中,除取负运算是单目运算外,其他的都是双目运算(需要两个运算量)。加、减、乘、除运算与数学中的含义相同,下面介绍其他的几种运算符的操作。

(1)指数运算

指数运算用来计算乘方和方根,其运算符为“^”,例如2^3表示2的3次方,等于8,而8^(1/3)是计算8的3次方根,结果为2。

(2)浮点数除法与整数除法

浮点数除法运算符(/)执行标准的除法运算,其结果为浮点数。例如表达式3/2的结果是1.5,与数学中的除法一样。整数除法运算符(\)执行整除运算,要求操作数均为整数,需要先进行四舍五入,其结果也为整数。例如表达式3\2=1,而不是1.5。

(3)取模(求余)运算

求余运算符Mod,其结果为第一个操作数整除第二个操作数所得的余数,且要求两个操作数均为整数,也需要先进行四舍五入。例如7Mod3=1,13.3 Mod 2.9=1。

注意 算术运算符的优先级别。

表2-5的9种运算符优先级别从上到下逐渐降低,其中乘法运算与浮点除法运算同级,加法与减法同级,若有括号“()”,则先算“()”内的,多层“()”从最里层的往外算。

(4)连接运算

连接运算符有&或+,其作用就是将两个表达式连接在一起,如果两个操作数都是String 类型的,那么这两个连接运算符的功能完全一样。只要两个操作数中有一个为数值型数据则用+连接符将执行加法运算,而用&连接符任何时候都是执行连接运算。

例如:

Dim S1 As String
Dim S2 As String
Dim S3 As Integer
S1 = "123"
S2 = "abc"
S3 = "45"
Label1.Text = S1 + S2   ’结果显示abc
Label2.Text = S1 + S3   ’结果显示,执行加法
Label3.Text = S1 & S3   ’结果显示

2.比较运算符

比较运算符用来对两个表达式的值进行比较,比较的结果是一个逻辑值,即真(True)或假(False)。用比较运算符将算术表达式或逻辑量连接起来就是关系表达式。常见的比较运算符如表2-6所示。

表2-6 常用比较运算符

比较运算符既可以进行数值的比较,也可以进行字符串的比较。在比较字符串的大小时,是逐字符比较的。如果第一个字符不相同,则由第一个字符的大小决定字符串的大小,否则检查第二个字符;如果第二个字符不相同,就由第二个字符的大小决定;如果第二个字符也相同,则检查第三个字符……依次类推。

字符的大小是由字符的ASCII码值决定。数字字符小于大写字母,大写字母小于小写字母,小写字母小于汉字。例如,下列表达式的值都为True。

"abc"<"abcd"、"123" <"1A"、"ABC"<"abc"、"Z"<"啊"

上述比较运算符中的<、>、<=、>=优先级别相同,即谁在前先比较谁,但它们优先于=、<>(它们优先级别也相同)。

此外,VB.NET还有两种比较运算符:Is和Like。

(1)Is运算符

Is运算符的操作数要求是Object类型,如果两个操作数表示同一对象,那么返回True,否则返回False。此外,Is运算符还在Select Case语句中使用。

(2)Like运算符

Like 运算符用来比较字符串表达式的 SQL 表达式中的样式,主要用于数据库的模糊查询。使用时要注意以下几点:

· “? ”代表任意一个字符

· “*”代表任意多个字符

· “#”代表0至9中的1个数字

· [字符列表]代表任何在列表中的字符

· [!字符列表]代表任何不在列表中的字符

例如:

Dim  myCheck  As  Boolean
myCheck="x12345y" Like "x*y"     ’返回True
myCheck="x12345y" Like "x? y"    ’返回False
myCheck="x12345y" Like "x#y"     ’返回False
myCheck="x" Like "[xyz]"         ’返回True
myCheck="x" Like "[! x-z]"       ’返回False

3.逻辑运算

逻辑运算也称布尔运算,主要有如表2-7所示的几种。

表2-7 常用逻辑运算符

对表2-7中的几种运算符的含义分别说明如下:

(1)Not

非运算为取非运算,为单目运算,非真即假,也即是说Not True=False, Not False=True。

(2)And

与运算为双目运算,只有当两个参与运算的量均为 True 时,结果才为 True,否则为False。

(3)Or

或运算为双目运算,只要两个运算量中有一个为True,结果就为True,两个运算量都为False时,结果才为False。

(4)Xor

异或运算也为双目运算,当两个运算量相同时结果就为False,否则就为True。

表2-7中逻辑运算符的优先级别是从上到下逐次降低。

4.各类运算符的优先级别

在一个综合各类运算符的表达式中,运算的优先级别是:算术运算优先于比较运算优先于逻辑运算。另外注意,可以使用圆括号改变优先顺序,强令表达式的某些部分优先运算。

2.1.7 结构化控制语句

结构化控制语句通常有3类,即顺序结构、分支结构和循环结构,它们的执行流程图分别如图2-1、图2-2、图2-3和图2-4所示。

图2-1 顺序结构

图2-2 分支结构

图2-3 前置条件的循环结构

图2-4 后置条件的循环结构

顺序结构的程序执行过程比较简单,从上往下逐条语句执行。分支结构和循环结构较为复杂,下面分别介绍。

1.分支结构

实现分支结构的语句有条件语句(以关键字If开头)和选择语句(以关键字Select开头)两种。

(1)条件语句

以关键字If开头的条件语句通常有两种语法格式。

第一种形式:

If 条件 Then [语句块1] [Else 语句块2]

第二种形式:

If  条件  Then
    [语句块A]
ElseIf  条件N  Then
    [语句块N]
    …………
[Else
      [语句块B]]
    End If

在这两种形式的If语句中,条件和条件N等都是一个逻辑表达式;语句块A、语句块 N 和语句块 B 等都是一个或若干个可执行语句。如果语句块中有多个语句,则第一种形式的语句块中的语句只能用冒号(:)隔开写在同一行。

在第一种形式中,如果条件成立,则执行语句块1中的语句,否则如果不省略 Else和语句块2,则执行语句块2中的语句。

在第二种形式的If语句中的省略号表示ElseIf子句:

ElseIf  条件N  Then
    [语句块N]

可以重复多次,即这种形式的If语句可以用ElseIf子句连续地判断多个条件。先从If之后的第一个条件判断起,如果遇到一个成立的条件If,则执行下一行开头的语句块,语句块中的语句执行完后,将退出If语句执行End If之后的语句。如果End If之前的条件中任何一个都不成立,则执行Else后的语句块B。

因此每一种形式的If语句中不管有多少个语句块,都将至多执行其中的一个。

如果语句块中包含If语句,这将形成条件语句的嵌套,应该注意到嵌套时If语句的层次。如果是第二种形式的嵌套,要注意If与End If对应。例如:

If i=0 Then s=“+” ElseIf i<0 Then s=“-” Else s=“0”

If  i>0  Then
    S=“+”
Else
      If  i<0  Then
          s=“-”
          Else
              s=“0”
          End If
      End If

If  i>0  Then
      S=“+”
ElseIf  i<0  Then
        s=“-”
      Else
          s=“0”
      End If

的作用完全相同。

例1:设计一个子程序,根据输入的学习成绩分别显示优秀(90分以上)、良好(80分以上)、及格(60分以上)与不及格几个等级。

程序如下:

Private  Sub  Button1_Click(ByVal  sender  As  System.Object,  ByVal  e  As System.EventArgs) _Handles Button1.Click  ’单击按钮
      Dim n As Integer
      n = InputBox("请输入学生成绩")
      If  n>100 or i<0 Then
            MsgBox("成绩应该在0~100之间")
      ElseIf  n>=90  Then
            MsgBox("优秀")
      ElseIf  n>=80  Then
            MsgBox("良好")
      ElseIf  n>=60  Then
            MsgBox("及格")
      Else
            MsgBox("不及格")
        End If
    End Sub

注意 InputBox 为输入函数、MsgBox 为输出函数,具体语法格式可以参见本书后面的章节或者查看帮助。

例2:已知A、B、C是三个数值变量,用If语句来求这三个数中的最大数,并且把它存储在数值变量MaxNum中。

分析:所谓三个数中的最大数就是大于或等于另外两个数中的任一个数,因此可以用下面的语句实现题目的求解。

If  A>B And A>C  Then
      MaxNum=A      ’如果A既大于B又大于C,那么最大数就为A
ElseIf  B>C Then
      MaxNum=B      ’如果A不是最大数,则B和C中较大的一个为最大数
Else
      MaxNum=C      ’如果A和B都不是最大数,那么C就是最大数
End If

(2)选择语句

Select Case语句可以根据一个表达式的取值情况进行分支选择,也称为情况语句。它的语法格式是:

Select Case <测试表达式>
    Case <表达式列表1>
        <语句块1>
    Case <表达式列表2>
        <语句块2>
    ……
    [Case Else
        <语句块n+1>]
End Select

在这个语句中,语句块与If语句中的第二种形式中的语句块相同,也指若干可以执行的语句;测试表达式可以是任何数值表达式或字符串表达式。一个表达式列表指定一个测度表达式的范围,表达式列表可以是一个或多个用逗号隔开的表达式,或者用关键字 To或Is表示的范围。此处关键字To和Is的语法格式是:

下界To上界
Is比较运算符表达式

其中,下界、上界和表达式都是与语句中的被测表达式同类型的表达式,比较运算符指前面讲的6种。To表示的范围是:大于或等于下界并且小于或等于上界。关键字Is指定的范围由所使用的比较运算符和表达式决定。例如,如果被测表达式是一个数值表达式,则可以使用如下形式的Case子句:

Case 1 To 4,7 To 9,11, Is >20

这个子句指定的被测表达式的范围是从1到4,从7到9,11以及大于20的数。Case Else子句也可以省略。

在执行到Select Case语句时先计算被测表达式的值,然后按从上到下的顺序检测End Select前的使用表达式列表的Case子句,如果被测表达式的值不在任何一个Case子句指定的范围中,则执行Case Else子句(如果有的话)和End Select之间的语句块。如果被测表达式的值在某个Case子句指定的范围中,则执行这个Case子句与下一个Case子句(或End Select)之间的一个语句块。执行完一个语句块后不再检测下一个Case子句指定的范围,而是直接执行End Select后的语句。这样,当被测表达式的值同时在多个Case子句指定的范围中时,也只是执行这些Case字句中的第一个子句后的一个语句块。

Select Case语句也可以嵌套使用,仍需要注意Select与End Select的配对问题。Select Case 语句只适合于根据一个表达式的值进行分支选择,而 If…ElseIf…语句可以检测多个表达式。当 If…ElseIf…语句只是检测同一个表达式的不同取值时,就可以用 Select Case语句替换它。

例3:用Select Case语句替换例1的功能。

程序如下:

Private  Sub  Button1_Click(ByVal  sender  As  System.Object,  ByVal  e  As System.EventArgs) _Handles Button1.Click  ’单击按钮
      Dim n As Integer
      n = InputBox("请输入学生成绩")
      Select Case  n
      Case is>100, is<0
            MsgBox("成绩应该在0~100之间")
      Case 90 To 100
            MsgBox("优秀")
      Case 80 To 90
            MsgBox("良好")
      Case  is>=60
            MsgBox("及格")
      Case  Else
            MsgBox("不及格")
        End Select
    End Sub

2.循环结构

VB.NET 中实现循环结构的语句常有 For…Next 语句、Do…Loop 语句、While…End While语句等。这些语句都能使某些语句重复地执行多次。

(1)For…Next语句

For循环一般用于循环次数已知的情况。For循环含有一个循环计数变量,每执行一次循环,该变量就会增加或减少指定的值,直到循环结束。其语法格式如下:

For counter = start To end [Step step]
    [statements]
    [Exit For]
    [statements]
Next [counter]

该语句执行时,先将counter设为star(t 初值)。测试counter的值是否超过end(如step为正数是大于,否则是小于),若已经超过,则循环结束,否则执行循环体中的语句。step是每次循环时 counter 变化的数值,它可正可负,缺省时为1。本次循环结束后,counter将加上步长step的值返回到循环开始,再进行测试,直到counter的值超过终值,循环结束。可以在循环体内的任何位置加上任意个Exit For,那么当达到一定的条件就会提前退出For循环,而跳到执行Next后的语句。

例4:设计一个计算连续整数之和的程序。

程序如下:

Private  Sub  Button1_Click(ByVal  sender  As  System.Object,  ByVal  e  As System.EventArgs) Handles Button1.Click
      Dim i As Integer
      Dim N As Integer
      Dim Sum As Long
      N = InputBox("请输入一个整数:")
      Sum = 0
      For i = 1 To N
          Sum = Sum + i
      Next
      Label1.Text = Sum.ToString
End Sub

使用For…Next循环时,在For和Next两个语句之间可以放置任何可执行语句,当然也可以放入其他For…Next循环,这样就形成所谓的“嵌套循环”。在使用嵌套循环时,每个循环的循环变量要使用不同的变量名,同时要注意For和Next的匹配。例如,下面的循环嵌套是正确的。

For i = 1 To 10
      ……
For j= 1 To 10
    ……
          For k = 1 To 10
            ……
          Next  k
    ……
      Next  j
      ……
Next  i

例5:设计一个在窗体上显示如图2-5所示由“*”组成的图案。

图2-5 效果图

程序如下:

Sub main()
      Dim i As Integer
      Dim j As Integer
      Dim s As String = "*"
      For i = 1 To 5  ’控制输出行
          For j = 1 To i
              Console.Write(("*")) ’控制每行输出的*个数
          Next j
          Console.WriteLine()  ’换行输出
      Next i
      Console.Read()   ’等待用户输入信息后再关闭窗口(即不会一闪关闭窗口)
    End Sub

说明 本例的运行效果是在控制台应用程序下运行的,新建项目时选择控制台应用程序。

(2)Do…Loop语句

如果可以计算出循环体的执行次数则使用For … Next语句是很方便的,但若事先不知道循环次数的情况下用Do … Loop语句更方便。它有两种语法格式:

第一种语法格式:

Do  [{while|until} 条件]
    [循环体]
Loop

第二种语法格式:

Do
    [循环体]
Loop  [{while|until} 条件]

在这两种格式的Do…Loop语句中,条件是一个逻辑表达式。把逻辑表达式的值为True看作是条件成立,值为 False 看作是条件不成立。第一种形式可以实现前置条件的循环结构,第二种形式可以实现后置条件的循环结构。它们的区别主要在于第一种形式的循环体可能一次都不执行,即开始时条件就不成立;而第二种形式的循环体至少要执行一次。

这两种循环在使用关键字 While 时可以解释为当条件成立时循环,而用关键字 Until为当条件不成立时循环或者说循环直到条件成立。

在循环时,通常是改变条件中的某个变量的值,使得循环体结束,若条件的逻辑表达在循环过程中保持不变,则会导致死循环,除非在循环中用Exit Do跳出循环。

例6:用Do…Loop语句来写求连续整数之和的程序。

程序如下:

Private  Sub  Button1_Click(ByVal  sender  As  System.Object,  ByVal  e  As System.EventArgs) Handles Button1.Click
      Dim i As Integer
      Dim N As Integer
      Dim Sum As Long
      N = InputBox("请输入一个整数:")
      i = 1
      Sum = 0
      Do While i <= N  ’该语句可以换成Do Until i>N
          Sum = Sum + i
          i = i + 1  ’这条语句不能忘记,让循环变量加1,否则导致死循环
      Loop
      Label1.Text = Sum.ToString
    End Sub

或者如下:

Private  Sub  Button1_Click(ByVal  sender  As  System.Object,  ByVal  e  As System.EventArgs) Handles Button1.Click
      Dim i As Integer
      Dim N As Integer
      Dim Sum As Long
      N = InputBox("请输入一个整数:")
      i = 1
      Sum = 0
      Do
          Sum = Sum + i
          i = i + 1  ’这条语句不能忘记,让循环变量加1,否则导致死循环
      Loop While i <= N  ’该语句可以换成Do Until i>N
      Label1.Text = Sum.ToString
  End Sub

例7:计算1+2+3+…,直到累加的和超过30000。

程序如下:

Private  Sub  Button1_Click(ByVal  sender  As  System.Object,  ByVal  e  As System.EventArgs) Handles Button1.Click
      Dim i As Integer
      Dim Sum As Long
      i = 1
      Sum = 0
      Do
          Sum = Sum + i
          i = i + 1  ’这条语句不能忘记,让循环变量加1,否则导致死循环
      Loop Until Sum > 30000  ’该语句可以换成Loop While Not sum>30000
      Label1.Text = Sum.ToString
End Sub

(3)While…End While语句

语法格式如下:

While  条件
    循环体
End While

如果程序判断条件为真,则执行循环体,到达End While语句时,控制返回While语句,再次判断条件,如果条件还是真,则重复此过程,直到条件为假,则程序转入End While后面的语句。

该循环结构与 For 循环的区别是:For 循环对循环体执行指定的次数,该循环结构是在给定的条件为真时重复执行循环体。这就是说,While…End While循环结构可以指定一个循环终止的条件,而For循环只能进行指定次数的重复。因此,当需要以某个条件是否出现来控制循环时,就应选择While…End While循环结构来描述。实际上它与Do While…Loop没有区别。

例8:用While…End While语句来写求连续整数之和的程序。

程序如下:

Private  Sub  Button1_Click(ByVal  sender  As  System.Object,  ByVal  e  As System.EventArgs) Handles Button1.Click
      Dim i As Integer
      Dim N As Integer
      Dim Sum As Long
      N = InputBox("请输入一个整数:")
      i = 1
      Sum = 0
      While i <= N
          Sum = Sum + i
          i = i + 1  ’这条语句不能忘记,让循环变量加1,否则导致死循环
      End While
      Label1.Text = Sum.ToString
End Sub

(4)For Each…In…Next循环语句

For Each…In…Next循环语句与For…Next循环类似,但它对数组或对象集合中的每一个元素重复一组语句,而不是重复语句一定的次数。如果不知道一个集合有多少个元素, For Each…In…Next循环语句非常有用。For Each…In…Next循环语句语法格式如下:

For Each  变量名 In  集合名或数组名
    循环体
 Next 变量名

例9:输出数组中的每个元素的值。

程序如下:

Module Module1
    Sub Main()
      Dim Score() As Integer = {60, 75, 78, 80, 86}
      Dim element As Integer
      Dim i As Integer = 1
      For Each element In Score
          Console.WriteLine("第" & i & "个数组元素的值为:{0}", element)
          i = i + 1
      Next
      Console.Read()
    End Sub
End Module

例10:单击按钮Button1关闭窗体中的所有子窗体。

程序如下:

Private  Sub  Button1_Click(ByVal  sender  As  System.Object,  ByVal  e  As System.EventArgs) Handles Button1.Click
'声明一个Form的对象,用于循环迭代操作
      Dim child As System.Windows.Forms.Form
      For Each child In Me.MdiChildren
          child.Close()
      Next
 End Sub

2.2 面向对象编程

2.2.1 “面向对象编程”中的概念

与 VB6.0不一样,VB.NET 已是真正的面向对象的开发工具。“面向对象编程”使程序设计思想不再基于流程,而是基于“类”和“对象”。即在编程过程中,通过开发环境添加程序所需的对象;通过为对象配置属性的方法,并在此基础上处理程序中的有关事件、方法等操作性代码。从而大大提高了效率,使编程工作像搭积木一样,既快速又规范,同时也为后期调试程序奠定了基础。下面介绍面向对象编程中常涉及的概念。

1.对象和类

(1)类(Class)

类是指一组具有相同数据结构和相同“对象”的集合。如果将一个个独立的实体(如“一部电话机”、“一台电视机”)加以抽象,就可以形成“类”的概念。所以也可以理解为“类”是创建对象(如“电话机”、“电视机”)的“模板”或者“蓝图”。换句话说,我们可以理解为生产电话机、电视机的图纸为类。

(2)对象(Object)

对象是指编程过程中的一个具体实例(Instance)。如果要执行类的方法和使用类的属性,就需要创建类的实例。即对象是类的特定实例,它包含类中所定义的特征。就好比用电话机的图纸(类)生产出来的具体的电话机(对象)一样,产生出来的电话机一定具有图纸所设定的特征。针对面向对象编程而言,对象可以理解为一个一系列不同类型的实例的总称。例如,应用程序的窗口、对话框、按钮等。

总之,类是对象的定义,用类说明的变量称为对象,对象是类的一个实例。用一个类可以建立多个对象,如同一张电话机图纸可以生产一批电话机。

(3)类的三个特性

· 封装性。封装性是指将对象的内部实现细节(属性、方法、事件)封闭起来,通过接口实现对象与外界代码间的交互。封装性包括两个方面的含义:一是把描述对象的属性与实现对象功能的方法结合在一起,将两者封装在一个独立的单位中;二是指“信息隐蔽”,把不需要让类的外部知道的信息隐蔽起来,有些属性及方法允许类的外部使用,但不允许更改,对外部隐蔽具体的实现方法,有些属性或方法则不允许外部访问。例如,用图纸生产出来的电话机把没有必要让用户知道的内部结构、工作机制等进行了封装,通过电话机表面的显示屏及按键让用户操作电话机实现其功能。

· 继承性。继承性是指类之间抽象层的自上而下的层次关系。它的特点是“子类”可以继承“父类”的属性和方法,还可以添加自己的属性和方法。同时如果修改了“父类”中的一部分内容,“继承性”同时改变所有的“子类”继承的相应部分(包括一次或多次继承),而无须对每一个“子类”进行单独的修改。例如:“电视”类是比“彩色电视”类更高一级的抽象,可以将某一个“类”(如“电视”类)定义为起点,称为“父类”或“基类”,在此基础上再定义的“类”,则称为“子类(Subclass)”。“子类”可以通过“继承性”使用“父类”中提供的功能,而实现类的继承只需要一条语句即可。

· 多态性。多态性指同一“消息”被不同的“对象”接受时可以导致不同的“行为”。例如,调度员下达“开车”指令(即“消息”)时,不同类型车的开动(即“方法”)是不同的。因此“开车”指令(即“消息”)对于不同的对象(“车”)的启动,就存在“多态性”。在VB.NEI中,很多都提供了“Add”方法。针对不同的类,使用“Add”方法将产生不同的结果,因为不同的类传递的参数不相同。

(4)对象的三要素

· 属性。一个对象的属性描述了对象的外观和内在特征。例如,电话的形状、大小、颜色等就是电话的外观属性,电话的内部使用的器件及其类型和个数等就是电话的内在属性。在VB.NET中窗体对象的宽度、高度、前景色、背景色等就是窗体的外观属性。一个对象可以包含其他对象。如电话机上可以有按键、显示屏等,在窗体对象上可以有命令按钮(Button)、文本框(TextBox)、标签(Label)等对象。

· 方法。一个对象往往要给对象的使用者提供一些方法。一个方法代表着对象向外提供的一种功能,对象使用者通过调用对象的方法来使用对象提供的功能。例如窗体有显示和隐藏的方法,分别为 Show 和 Hide。可以这样引用它们:Me.Hide()、Me.Show()。

· 事件。一些已定义好的而且可以被对象所识别的动作。例如当电话铃声响起时一个事件就产生了,这个事件告诉有人打电话来了。同样地,编程对象也提供事件,例如在按钮上单击,就会触发该按钮的Click事件。在编程时要响应一个编程对象产生的事件,就要为这个事件编写一段响应事件的程序。

2.命名空间

在 VB.NET 中,除了标准的“类”和“对象”的概念以外,还引入了“命名空间”的概念。类是根据功能特性分类,但在现实世界中常常会发生类名称重复的现象,为了避免名称重复以及便于管理,于是又将类依其特性再做个大类。简而言之,命名空间(Namespace)就是类的大分类。.NET的命名空间是阶层化组织,例如:System. Windows.Forms为窗口应用程序相关类的命名空间;System.IO为文件访问相关类的命名空间。

.NET Framework下的类都被有系统的归类到特定的命名空间下,因此在需要调用到某个类时,就必须以完整名称来声明类。例如,声明一个按钮对象,它属于 System. Windows.Forms命名空间,类的完整名称为System. Windows.Forms.Button。语法如下:

Dim BtnOk As System.Windows.Forms.Button

若是每次都要使用到System.Windows.Forms所属的类,就得以完整的名称调用,那么必然导致程序很长。因此,VB.NET 为了简化使用完整命名空间+类的语法,特别提供了Imports 关键字,让程序员在要使用到命名空间的程序文件(.vb)时引入命名空间,调用类时就可以直接调用类名称,而不需要冠上那个很长的命名空间。

引入命名空间必须写在程序文件的第一行,语法如下:

Imports System.Windows.Forms

在之后需要使用此命名空间所属的类,就可以省略命名空间,直接调用类的名称。例如:

Dim BtnOk As Button

2.2.2 “对象”和“类”的使用

1.对象的使用

对象的使用主要包括以下五个方面的内容。

(1)对象的声明

在添加控件的过程中,系统自动对控件对象进行声明(凡进行过声明的对象,均可以在编程过程中,被事件、方法等调用),与变量的声明相同。例如声明一个基于System.Windows.Forms 命名空间中的 Label 类的对象 Label1和声明一个基于System.Windows.Forms命名空间中的TextBox类的对象TextBox1的语句如下:

Friend WithEvents Label1 As System.Windows.Forms.Label
Friend WithEvents TextBox1 As System.Windows.Forms.TextBox

说明 代码中关键字Friend是表示以“友好元素”模式声明以上变量,即可以在同一项目的任意位置对该数据成员进行访问,但不允许在程序的外部对其进行访问。关键字WithEvents,表示允许创建事件处理程序中与Handles子句一同使用的类或模块级对象(变量); Label1、TextBox1分别是对象名。

(2)对象的实例化

描述类中某对象,在窗体中形成一个实际可见的控件(即“实例”)。对象的使用与变量最明显的不同在于,对象在使用前需要进行实例化。方法是通过关键字“New”生成对象的实例。例如将对象Label1和TextBox1实例化,其代码如下:

Me.Label1 = New System.Windows.Forms.Label
Me.TextBox1 = New System.Windows.Forms.TextBox

上述关键字Me指默认的当前类对象。因为当前默认类的对象是Form1,所以Me指的就是当前对象Form1。在实际使用过程中,可以将对象的声明和实例化结合在一条语句中。这一特点与变量的使用相同。例如:

Dim obj As MyClass
Obj=New MyClass

等价于

Dim obj As New MyClass()

(3)取消对象的引用

当对象完成其任务,需要中断与其他对象关联时,可采用取消对象的引用。例如:

Obj=Nothing

Obj指的是已生成的对象名称,Nothing指的是关键字。

对于一个短时间运行的程序,使用取消引用对象这一功能,可能没有多大的意义。因为在程序结束运行并退出以后,程序会取消所有的对象实例,并且释放这些对象占用的内存。但是,对于一个长时间运行的程序,使用取消引用对象就非常必要了。因为没有取消引用的对象,其占用的内存就不会被“无用单元收集器”回收。

(4)对象属性的修改

通过修改对象的属性,可以改变对象的特征。很多对象的属性,在“设计时”和“运行时”的可操作性不同。有些对象的属性,在“设计时”和“运行时”都可以更改。例如,“Button”对象的“Text”属性,都可以直接进行赋值操作。另一些对象的属性,在“设计时”可以选择或改动,在“运行时”不可以直接改动,称之为只读属性。例如,Name 属性;“TextBox”控件的“Font”属性,“设计时”可以写入,“运行时”则为只读,但是,可以通过分配新“Font”对象的方法,进行改变。

在代码编辑器中修改控件的属性值与在窗体设计器中修改控件的属性,其效果是一样的。

(5)对象的事件

指一个对象用来通知某一动作发生而发出的消息。被通知的动作可以由用户的操作触发,如按下键盘按键或单击鼠标等;也可以由程序逻辑触发,如程序的状态发生变化等。

2.类的使用

(1)类的继承

因为系统提供的类都已被分组封装在“命名空间”中,所以,如果想调用某些类,只需调用包含该类的命名空间即可。但是,编程过程应特别注意类的继承特性。在VB.NET中,使用关键字“Inherits”标识类的继承。例如:

Inherits System.Windows.Forms.Form

针对基于“Windows应用程序”模板的程序开发而言,“System.Windows.Forms.Form”是最常应用到的一个基类,且是一个“窗口”类。

“Form”类可以用于创建同类型的窗口,包括“标准窗口”“工具窗口”“无边框窗口”“浮动窗口”,也可以使用“Form”类创建“模式窗口”,如“对话框”“多文档界面(MDI)窗体”,这种特殊类型的窗体可以包含名为“MDI”子窗体的其他窗体。使用继承的特性就可以在编程过程中直接使用这个类所提供的方法和属性。

(2)构造函数

在VB.NET中创建对象时,类可以实现一个调用的方法,这个方法称为“构造函数”。构造函数主要用于为对象分配存储空间,完成初始化操作。构造函数是一个通用过程,过程名为New。

在常规的Windows窗体中,“New”方法经常用于保存窗体的所有初始化代码。它一定在调用任何其他方法之前运行,而且对于每个对象,它只运行一次。如果创建的程序属于常规Windows窗体程序,系统自动生成的代码中就会包含窗体的构造函数,如下面的代码:

Public Sub New()
      MyBase.New()
      ' 此调用是Windows 窗体设计器所必需的。
      InitializeComponent()
      ' 在InitializeComponent() 调用之后添加任何初始化。
 End Sub

说明 关键字“MyBase”表示引用基类的成员对象;语句“MyBase.New()”对当前窗口类的基类成员进行初始化;通过调用“InitializeComponent()”过程,对当前窗体类中包含的控件对象进行初始化。

如果开发过程中需要添加其他自定义的初始化内容,则可以在该语句后面添加自定义初始化语句或函数。

与构造函数对应的是如下代码:

  Protected Overrides Sub Dispose(ByVal disposing As Boolean)
        If disposing AndAlso components IsNot Nothing Then
          components.Dispose()
        End If
        MyBase.Dispose(disposing)
 End Sub

在窗体对象结束时,完成对窗体中包含组件对象的取消操作,并销毁这些对象,释放内存空间。

(3)组件和组件类

类是可重用代码的单位,组件也是。要创作组件,应从创建类开始。那么,它们区别在何处呢?

当类符合组件交互标准时,它就成为组件。此标准通过 Icomponent 接口提供。任何实现 IComponent 接口的类都是组件。这样的标准允许开发人员将组件快速插接在一起以创建较大的程序。公共语言规范(CLS)描述了为公共语言运行库创作的组件可以如何交互。有关详细信息,请参见什么是“公共语言规范”?

.NET Framework提供了IComponent接口和Component基类,使创作适合设计环境的组件更为容易;还提供了UserControl和Control类,使创作可视组件也更加容易。

(4)控件类

在程序窗体中,可以实现人机交互操作的一系列控件,统称为“控件类”。从简单意义上可以理解为具体的按钮、单选框、下拉式列表等。控件类的基类有如下两类:

[1] “System.Windows.Forms.Control”类,用于客户端Windows窗体。

[2] “System.Web.UI.Control()”类,用于ASP.NET服务器(Web开发环境)。

在.NET 框架类库中的所有控件,都直接或间接地从这两个基类中导出。若从基类[1]导出控件,则含带类“Component”中的方法,即为导出控件(如“Button”)提供了用户界面“UI”功能。若从基类[2]导出控件,则实现接口“IComponent”中的方法,虽然不含用户界面“UI”功能,但其提供了“HTML”模式结构,开发者可以很容易地在网页上添加用户界面“UI”(如按钮、文本框等)。

2.2.3 创建自定义类

通常情况下,NET系统为软件开发人员提供了丰富的类,直接使用这些类,或者使用类的继承性,在引用类的基础上进行简单的修改就可以满足程序功能需求。但是模板一般都是针对普遍问题而设计的,常常不能满足某些特定的需求。所以,开发程序经常需要修改甚至设计新的模板,即自定义类。下面以创建一个名为“Person”的类,该类中包含姓名的属性、根据出生日期计算出年龄的方法等为例来说明。

1.创建类

声明类的语法格式如下:

Public Class 类名
          ……   ’类的主体,在这里定义类的成员
End Class

本例创建一个名为“Person”的类。启动VS 2008.NET程序后,右击解决方案资源管理器下的项目,选择“添加”|“添加类”,弹出如图2-6所示的“添加新项”对话框。单击添加即可看到如下代码。

图2-6 “添加新项”对话框

Public Class Person
 
……   ’暂时为空
 
End Class

2.为类添加方法

在VB 2008.net中,使用Sub和Function过程来创建方法。在上面类模块中添加如下代码:

'方法,用于计算年龄
Public Function Age(ByVal mybirthday As Date) As Integer
      Return DateDiff(DateInterval.Year, mybirthday, Now())
End Function

说明 DateDiff 函数用于计算两个时间日期值(Date1和Date2)之间的差值。DateInterval.Year表示Date1和Date2之差单位时间间隔为年。

3.为自定义类添加属性

在VB.NET中,使用Property语句来定义类的属性。具体语法格式如下:

Private  私有变量名 As 数据类型
Public Property 属性名() As 数据类型
      Get
          Return   私有变量名
      End Get
      Set(Byval Value As String)
          私有变量名=Value
      End Set
End Property

说明如下:

· Get 子句。Get 子句用于返回属性值,让程序可以获取类对象的属性值。至少要包含一个Return语句,用于将变量的值返回给外部程序。

· Set子句。Set子句用于将属性值写入类对象,至少要包含一条赋值语句,将数据写入保存属性值的类成员变量。该成员变量是一个用于存储属性值的私有变量,可以在类内部使用。

· 属性的数据类型。属性的数据类型必须与所存储数据的类型匹配。

为本示例添加一个名为Name的属性,具体代码如下:

Private myname As String
    Public Property name() As String
      Get
          Return myname
      End Get
      Set(ByVal value As String)
          myname = value
      End Set
End Property

至此,一个Person类就创建完成了,然后就可以使用它了,当然使用前同样先需要对它进行实例化。

2.3 控件常用属性

VB.NET的控件种类繁多,每种控件又都有许多不同的属性,但是在这些众多的属性中,有相当一部分属性是大多数控件所共有的。因此掌握这些共有属性对掌握控件的使用与设置会起到举一反三的效果。

(1)Name属性

该属性是所有对象都具有的属性,是所创建的对象的名称,所有的控件在创建时由VB.NET自动提供一个默认名称。Name名称属性在属性窗口的“Name”栏可以进行修改。该属性在运行时是只读的。

(2)Text属性

该属性是对象的标题,窗体标题显示在窗口的标题栏中,控件的标题就显示在控件中(即控件上显示的文本内容)。新添加对象的Text属性被自动设置为Name属性的内容。

对某些控件(主要为Button),可在设置标题的字符串中用符号&和1个字母,为控件指定1个热键,热键显示在控件中时带有下划线。在按下Alt键同时按下控件的热键与用鼠标左键点击这个控件的效果是相同的。

(3)Location与Size属性

Location与Size决定了控件的位置与大小,Location具有X、Y两个子属性,分别代表X坐标与Y坐标;而Size也有Height和Width两个子属性,指出了控件的高度与宽度。一般在应用程序设计中,控件的位置与大小都是通过在属性窗口直接设置。如果想在运行时控制控件的位置与大小,例如控制文本框可以使用如下的代码:

TextBox1.Size = New System.Drawing.Size(100, 200)
TextBox1.Location = New System.Drawing.Point(100, 100)

(4)Visible属性

Visible属性决定了控件在运行时是否可见,它也是逻辑值,“True”代表可见,“False”代表不可见,但它不会影响其在设计时的可见性。只有可视控件才有该属性,像Timer那样不可视控件没有该属性。

(5)Enabled属性

Enabled属性决定了控件在运行时是否允许用户进行操作,它是逻辑值,“True”允许用户操作并可对其操作做出响应,“False”禁止用户操作,此时只要是可视的控件均呈灰色。几乎所有的控件都有Enabled属性。

(6)Font属性

在VB.NET中Font是一个对象:System.Drawing.Font,它决定了字符的格式,如字体、字号、字形等。在VB.NET中,字体在运行时是只读的(即不能直接设置这些属性,但可以分配新的 Font 对象),例如:

'将标签的字体设为宋体,大小为20
label1.Font = New System.Drawing.Font("宋体", 20)
'将标签的字体改变为粗体与斜体
label1.Font  =  New  System.Drawing.Font(label1.Font,  FontStyle.Bold  Or FontStyle.Italic)

如果在属性窗口对该属性进行设置,只要通过字体对话框就能实现。

(7)ForeColor与BackColor属性

用于设置控件中的文本、图形的前景色或背景色。通过“属性”面板选中 ForeColor与BackColor属性,弹出调色板,从“自定义”、“Web调色板”或“系统调色板”中选取一种合适的颜色即可。也可以在编程时设置颜色。使用Color类中的属性或方法定义颜色,例如,Button1.Forecolor=Color.Red;使用方法 FromArgb(红、绿、蓝)设置颜色,红、绿、蓝取值范围是0~255,例如,Button1.Forecolor=Color. FromArgb(255、0、0);使用类SystemColors设置颜色,例如,Button1.Forecolor=SystemColors.Control。

(8)Anchor属性

Anchor属性是VB.NET新增的一个属性,用于锁定控件的某边与窗体对应边之间的距离,当窗体的尺寸改变时,指定边的距离可以不变。当某个控件的 Anchor 属性设置成两对边(左右或上下)时,该控件在这个方向的尺寸将随着窗体的大小改变而改变。控件的Anchor属性值如表2-8所示。

表2-8 控件的Anchor属性值

该属性的设置有两种方法:设计时设置与运行时设置。设计时设置就是通过控件的属性窗口进行设置,VB.NET 对控件的Anchor属性采用了可视化的设置方法。例如:要将窗体上的某一文本框设置成与窗体的左右边界保持不变,即在调整窗体大小时,文本框的宽度会自动发生变化以保持左右边界的不变。要实现这一点可采用以下方法:

[1] 单击文本框。

[2] 在属性窗口中找到 Anchor 属性(此时的默认值为Top, Left),单击下拉箭头,会出现一个直观的调整界面,如图2-7所示。

图2-7 控件Anchor属性调整

[3] 使用鼠标单击控件两边的虚线方块(黑色表示锁定,透明表示不锁定),直到控件左右两边的方块涂黑,上下两边的方块透明。

[4] 单击其他任何位置,即可完成设置。

程序运行后,改变窗体的大小就可以看出Anchor属性的作用效果了。

与一般属性一样,Anchor属性也可以通过代码来设置。设置的语法如下:

控件名.Anchor = AnchorStyles.方向

其中方向代表 Top、Bottom、Left、Right。如果需要同时设置几个方向,在两个方向之间用Or连接,例如上例用命令来实现如下:

Text1.Anchor = AnchorStyles.Left Or AnchorStyles.Right

(9)Dock属性

控件的Dock属性也是新增的一个属性,它允许控件“附着”在窗体的一个边界上。如果一个控件的 Dock 属性设置为 Right,则该控件就会自动紧靠窗体的右边界,而且上下贯穿整个窗体;如果该属性设置成Fill,则该控件就会充满整个窗体。

在属性窗口进行Dock属性的设置也是通过可视的方式,如图2-8所示。

图2-8 控件Dock属性调整

Dock属性共有6种不同的取值:

· None:没有停靠属性(默认值)。

· Top:控件上边界停靠在容器的上边界上。

· Bottom:控件下边界停靠在容器的下边界上。

· Left:控件左边界停靠在容器的左边界上。

· Right:控件右边界停靠在容器的右边界上。

· Fill:控件各边界停靠在容器的对应边界上。程序代码的设置方式为:

控件名.Dock = DockStyles.方向

其中方向即为上面6种取值中的一种。

(10)Tag属性

存储与控件相关联的用户定义数据。

以上讲解的为大多数控件所共有的常用属性,当然几乎每个控件都会有些自己的个性属性,且比较重要,请读者自行查阅帮助。

2.4 API函数的应用

2.4.1 API简介

所谓 API 就是“应用程序接口”(Application Programming Interface),是操作系统为程序开发人员提供的一组函数库,开发人员可以通过调用API简易地实现一些操作系统已经提供的功能。API函数在Windows自带的DLL文件中。在32位的Windows中,核心的Windows API DLL见表2-9所示。

表2-9 Windows API中常见的DLL

此外还不断有新的API出现,处理新的操作系统扩展,比如E-mail、网络和新的外设。

当难以自己编写等效的过程时,可以使用API来完成任务。在代码中使用Windows API的优点在于它们可以节省开发时间,因为它们包含许多已经编好的、等待使用的有用函数。缺点是在发生故障时,Windows API可能难以处理并且不可挽回,因为它使用的数据类型与VS.NET中所用的数据类型不同。由于这些差别,且Windows API不是COM对象,所以与Windows API和.NET平台的互操作是通过使用平台调用来完成的。平台调用是一种服务,它使托管代码能够调用DLL中实现的非托管函数,这样就容易导致在使用DLL的过程中发生异常而无法妥善处理。

常用的调用API函数的方式是使用Declare语句将要应用的函数在程序代码里声明,声明完后即可以使用。在VB.NET里还有一种调用API函数的方法,就是利用DllImport将API函数映射到某一过程。

2.4.2 API的声明

API在使用之前都需要进行声明,以定位函数使用的DLL和入口。比较常用的方法是使用Declare语句进行声明,另一种方法是使用DllImport语句将API函数映射到程序代码中的某个自己定义的函数上。下面主要介绍用Declare语句声明API函数。

API的声明必须放在代码的最开头部分。声明API函数的语法格式如下:

Private|Public|Friend|Protected  Declare  Auto  Function  GetTempPath  Lib“Kernel32” 【Alias“GetTempPathA”】(ByVal nBufferLength As Int32, ByVal lpBuffer As String)As Int32

解释如下:

(1)Private|Public|Friend|Protected指定声明的API函数的可访问性和使用范围。各关键字的含义与声明变量相同。

(2)Declare是声明的关键字,后面紧跟Auto修饰符,Auto修饰符指导运行库根据公共语言运行库规则(或已指定的别名)转换基于方法名的字符串。

(3)Function关键字后面为函数名,说明API实际上也是函数,只不过这个函数是外部引用进来的。

(4)关键字Lib指明待调用的函数在哪一个DLL中。在Declare语句里,DLL的名称被包含在一个字符串中(如“Kernel32”)。如果用户的系统中找不到关键字“Lib”后面指定的DLL,对函数的调用将失败,并产生一个代号为“48”运行时错误,即:“调用DLL错误”。这种错误可以在VBA(Visual Basic Application)代码中进行处理。如果调用函数位于某一基本的Windows DLL中,就不存在上述问题,因为要加载应用程序,这些DLL肯定存在。

(5)关键字Alias。关键字Function后面的函数名是在VBA中调用该函数时用的名称,这个名称可以与API函数本身的名称相同,但出于以下原因,一般在关键字Function后指定的函数名不与API函数本身名称相同,即指定为别名,那么需要用关键字Alias指定DLL函数的真实名称。

以下是使用别名的原因。

· 有些API函数的名称以下划线“_”开头,这在VBA中是非法的。在VBA中必须使用别名调用某函数。因为别名允许程序员随意给DLL函数命名,使函数名符合VBA中的命名标准。另外,API函数区分大小写而VBA函数不区分,所以,可用别名更改函数名的大小写。

· 一些DLL函数能接受不同数据类型的参数。这些函数的VBA“Declare”语句,把参数的类型定义为“Any”。凡调用声明了“Any”类型参数的 DLL 函数,有一定的风险,因为 VBA 不做任何数据类型检查。如果想避免传递“Any”类型参数时带来的风险,可以声明同一个DLL函数的多个版本,每个都有不同的名称和数据类型。

· 在Windows API中,所有带字符串参数的函数都有两个版本:一个ANSI版本和一个Unicode版本。ANSI版本的函数名带有后缀A,而Unicode版本的后缀是W。虽然VBA内部使用Unicode版本,但在调用DLL函数前,会把所有字符串转换为ANSI字符串。所以,在VBA中调用Windows API函数时,一般都用ANSI版本。API查看器外接程序,自动给所有带字符串参数的函数取别名,所以在调用函数时不必包括后缀A。

2.4.3 API的应用实例

下面通过讲解一个应用API函数实例,让读者对API有一个更深刻的认识。该实例的功能是在窗体上单击,并以单击的点为终点,以窗体左上角的点为起点画一条直线,如图2-9所示。

图2-9 API函数示例

实现过程如下:

[1] 启动VS 2008,建立一个名为“API函数示例”的Windows应用程序。设置窗体的Text属性为API函数示例,并调整到适当的大小。

[2] 向窗体添加一个PictureBox控件,设置其Dock属性为Fill。

[3] 单击右侧“解决方案资源管理器”面板下的“查看代码”按钮,进入代码编写窗口。

[4] 声明API函数LineTo(用来画直线的函数),声明代码如下:

Private Declare Auto Function LineTo Lib "gdi32" Alias "LineTo" (ByVal hDC As Int32, ByVal x As Int32, ByVal y As Int32) As Int32

LineTo函数的参数说明:

· Hdc,用来绘制图形的设备上下文句柄,长整型表示。

· X, y,线段终点位置,长整型表示。

[5] 继续在代码编辑窗口的上面右侧选择 PictureBox1,再在左边选择 MouseDown,即会自动添加如下两行代码:

Private  Sub  PictureBox1_MouseDown(ByVal  sender  As  Object,  ByVal  e  As System.Windows.Forms.MouseEventArgs) Handles PictureBox1.MouseDown
 
End Sub

[6] 在上述两行代码中间添加如下代码,实现示例功能。

Dim x As Single
      Dim y As Single
      x = e.X ’记住鼠标当前位置的x坐标
      y = e.Y ’记住鼠标当前位置的y坐标
      LineTo(Me.PictureBox1.CreateGraphics.GetHdc.ToInt32, x, y)

[7] 按下F5键或者单击工具栏上的“启动调试”按钮或者单击【调试】|【启动调试】菜单,运行程序,效果如图2-9所示。

至此,API函数应用阐述完毕,要说明的一点是实际上现在VB 2008的功能已非常强大完善,很少使用API函数,但是当使用一些第三方开发的DLL时,调用DLL内部的函数的方法与调用API函数的方法是一致的。

2.5 本章小结

本章首先介绍了标识符的命名、数据类型、变量与常量、自定义结构体、数组、运算符与表达式及结构化控制语句,这些是学习一门语言的基本编程元素;然后介绍了面向对象编程中的两个重要的概念,“对象”和“类”及其它们的使用;接着介绍了控件的一些常用的公共属性;最后阐述了API函数的应用。读者通过学习,将熟悉Visual Basic.NET的编程基础。