Visual Basic编程标准012

更新时间:2023-05-03 22:38:01 阅读量: 实用文档 文档下载

说明:文章内容仅供预览,部分内容可能不全。下载后的文档,内容与下面显示的完全一致。下载之前请确认下面内容是否您想要的,是否完整无缺。

第1 2章用户的输入和通知消息

用户是通过鼠标和键盘输入的方法与程序进行通信的,而程序则通过声音、消息框、对话框和其他视觉手段与用户进行通信。这种双向通信方法使用户能够顺利地使用一个应用程序,非常容易地完成他们的任务。

注意目前使用的定点设备有许多不同的类型,比如触摸板、输入板和跟踪球等。总

的来说,本章介绍的一些概念不仅适用于鼠标,而且也适用于其他定点设备。不过,为了简便起见,同时因为鼠标仍然是目前市场上的主要定点设备,因此,我在介绍与

用户的定点设备进行交互操作时,通常指的是鼠标。

应该记住,程序实际上只是个工具而已。除非你编写过游戏程序,否则,大多数用户运行你的程序并不只是为了运行它,相反,他们使用你的程序目的是为了更加有效地完成某项任务。当用户与程序之间的双向通信在任何一个方向上效率不高时,程序作为一种工具的效能就会下降。用户不会再考虑使用这种程序,就像你不再想用黄油刀将果仁黄油抹在面包上一样。

12.1 用户的输入

很明显,并不是每个程序都以相同方式与用户进行交互操作。例如,类似 A d o b e公司的P h o t o S h o p之类的绘图程序在很大程度上是用鼠标操作的一种程序,P h o t o S h o p中的大部分功能是用鼠标或其他某个定点设备来执行。让用户只使用键盘来执行P h o t o S h o p中的每个功能,这肯定是白日做梦,但是,软件开发人员为用户提供了使用键盘来完成某些任务的手段。虽然最好的办法是使程序既适合键盘用户的需要,也适合鼠标用户的需要,因为往往确实存在这两种不同类型的用户,但是应用程序本身的性质是很难实现这一要求的。

另一种程序是数据输入应用程序。从事数据输入的主要是使用键盘的用户。如果你真想触怒这些人,那么在数据输入进程的中间插入一个只能使用鼠标操作的任务(请记住,尽管你的程序对你来说是颗闪光的宝石,然而对于用户来说它仅仅是个工具)。用这种方法来中断用户的工作流程,会使用户的工作进程变得非常复杂,因为它增加了工作方式的变化。由于这种工作方式的变化可能被用户认为是不必要的,因此它很快会使用户感到厌烦。讲到用户与程序之间的交互操作时,必须了解你的目标市场。你应该建立一个预计将会运行你的程序的用户类型概况表,并且认真考虑这个用户的工作方式。

大多数应用程序可以分为两类,一种是用鼠标操作的应用程序,另一种是用键盘操作的应用程序。Microsoft Visual Basic要求你同时熟悉鼠标和键盘的操作。你无法用鼠标编写代码,但是,只用键盘试试将控件添加给窗体,移动和对齐这些控件,并且设置它们的属性,以便创建一个功能良好和美观的界面。由于大多数情况下用户必须同时使用鼠标和键盘进行工作,因此应该尽量使两种输入设备之间的转换变得非常方便。另外,你还必须随时提供鼠标功能和键盘功能。当一个功能同时支持鼠标和键盘时,它就具备了我所说的交互式二重性。交互式二重性可以确保用户能以最适合其需要的方式使用你的程序。

比如说,你将一些代码键入Visual Basic的代码编辑器,这时你想通过运行该代码来测试你

所进行的修改。应该怎么办呢?由于你的手已经放在键盘上了,因此最有效的方法是按F 5。如果你用鼠标在窗体上拖移一个控件,想找到放置该控件的最佳位置。你将控件放到它应有的位置,然后想运行该控件,以便了解它在运行时的样子。当然,这种情况下最有效的方法是单击工具栏上的R u n按钮。由于你已经在使用鼠标,因此这项操作迅速而且容易。每当你必须在键盘和鼠标操作之间进行切换时,你的操作进程中就会出现一个停顿,就像你的脑子指挥你转换车档和移动你的手位时出现停顿一样。无论这个停顿如何短暂,这常常是可以避免的,因为大多数功能都可以用交互式二重性来实现。

程序的界面既是个障碍,也是个桥梁。本章向你介绍如何创建能使用户更容易与程序相融洽的界面。好的界面能使用户不必考虑进程的机制便能执行他们的任务。这无疑会使用户更加满意,也有助于降低支持费用,增加购买升级产品的用户数量,取得更好的广告效果。

12.2 通知消息

要想编写不带任何消息框语句的应用程序是非常困难的。通常而言,一个程序会有几十个消息框语句,分散在它的代码之中。尽管用M s g B o x语句来显示通知消息是很常见的,但是许多软件开发人员都不能正确地编写这样的代码。向用户显示通知消息时,你与用户进行通信的方式就像你跟他打电话的情况一样。

编写出色的通知消息,是涉及多方面技巧的一项工作。最简单的一个技巧是要确定通知消息能否告诉用户他所需要知道的东西,不过这仅仅是个开始。你还必须注意消息文字的语气、礼仪、语法、拼写、格式以及术语的数量等问题。编写好的通知消息是一门技术,但是,即使你不是写文章的行家里手,仍可按照下面的原则写出较好的通知消息。

12.3 编程原则

12.3.1 确保完善的键盘导航和交互操作特性

根据你编写的程序类型,也许无法使可以用鼠标执行的所有功能都能用键盘来执行。但是用户应能不使用鼠标就可以运行你的整个程序。这意味着你的菜单应该支持快捷键和组合键。关于这些键盘的操作方法的详细说明,请参见第11章。

除了使你的菜单更适合键盘操作外,还必须让用户能够用键盘来非常容易地对每个窗体和对话框控件进行定位。此外,它应该使用户能够通过键盘操作来接受或拒绝对话框中的变更。激活所有的键盘访问操作是非常麻烦的,在推出产品之前,你可能无法设想到所有的情况,但是可以相信,你的客户将会非常乐意提醒你已遗忘的情况。

实际应用举例

(1) 精心设置所有窗体的Ta b键顺序。即使用户喜欢使用鼠标,但是早晚他需要使用Ta b键使窗体上的控件向前或向后移动。Ta b键是Microsoft Wi n d o w s在窗体上使焦点向前(或使用S h i f t+T a b键向后)移过控件时所用的标准操作键。你的每个窗体都应该允许使用Ta b键和S h i f t+T a b键进行向前和向后移动。没有理由不提供这项特性。

Ta b键在窗体上移动控件所采用的次序称为Ta b键次序。Ta b键次序由窗体上控件的Ta b I n d e x和Ta b S t o p属性来确定。能够接收焦点的所有控件都有一个Ta b I n d e x属性,但并非所有控件都配有Ta b S t o p属性。具有Ta b I n d e x属性但没有Ta b S t o p属性的控件被视为它们的Ta b S t o p属性总是设置为Tr u e。当用户按下Ta b键时,焦点将从当前拥有焦点的控件上移到下一个拥有最高Ta b I n d e x属性值的控件上。如果拥有下一个最高Ta b I n d e x值的控件没有显示出来,或者它的Ta b S t o p属性设置为F a l s e,那么就连续搜索该控件,直到找到Ta b S t o p属性设置为Tr u e的可视控件。

若要为窗体定义Ta b次序,只要为第一个接收焦点的控件赋予0作为其Ta b I n d e x值,下一个控件的Ta b I n d e x值为1,依此类推。虽然这个操作概念很简单,但是在Viaual Basic中这是个非常复杂的进程。

将控件添加给窗体时,Visual Basic会以递增方式将值赋予Ta b I n d e x属性。例如,放入窗体的第一个控件的Ta b I n d e x值是0,下一个控件的Ta b I n d e x值是1,如此类推。当窗体设计完成时,这可能不是你想要的次序。创建窗体时,你通常要添加新控件,删除现有的控件,并且随意拖移控件,以便创建非常出色的界面。执行这些操作时,系统指定的Ta b I n d e x值变成了任意值。因此核实窗体的Ta b次序应该是你将窗体投入实际使用(也就是编译成可用文件)之前执行的最后任务之一。这并不是说在窗体上工作时不必调整Ta b次序,因为实际上你必须进行这样的调整。但是,不管对窗体的Ta b次序进行多少次调整,当你完成对窗体的操作并准备将它移到另一个窗体上时,请核实它的Ta b次序。比较图1 2-1和图1 2-2。

在窗体上设置控件的Ta b次序,只需进行简单的点击操作。对于创建的每个窗体,你都必须进行这样的操作。但是Visual Basic并不包含这种函数,你必须分别修改每个控件的Ta b I n d e x 属性值。我曾经试图提供比较巧妙的方法来进行这种操作,但是没有成功,这使我大失所望。让我们期望Visual Basic开发小组不久能够为我们提供这样的能力,这将使成千上万个编程人员能够节省大量的编程时间。

用人工方式将值赋予窗体控件的Ta b I n d e x属性时,可以采用两种不同的方法。第一种方法是选定你要使之成为Ta b次序中第一个控件的控件,然后为它的Ta b I n d e x属性赋0值。接着选定Ta b次序中的下一个控件,将1赋予它的Ta b I n d e x属性。继续执行这样的操作,直到所有控件的Ta b I n d e x属性均被赋于正确的值为止。这是个非常麻烦的过程,你很快就会感到心烦意乱。更为糟糕的是,最终你不得不放弃这样的操作。值得高兴的是,你可以使用另一种比较容易的操作方法。

另一种方法不是按从第一个控件到最后一个控件的顺序进行操作,而是从最后一个控件到第一个控件进行操作。这种方法的优点是,你只需将一个值赋予所有的Ta b I n d e x属性,这个值就是0。当你将Ta b I n d e x值赋予一个控件时,带有相同值的任何控件,以及带有较高值的各个控件,均自动调整,以便保留它在Ta b次序中的位置。因此,当你给Ta b次序中的最后一个控件赋予Ta b I n d e x属性值0时,它就成为Ta b次序中的第一个控件。但是,当你给最后第二个控件赋予Ta b I n d e x属性值0时,最后一个控件的Ta b I n d e x值就自动置为1。当最后第三个控件的

Ta b I n d e x 属性值被设置为0时,最后第二个控件被赋于Ta b I n d e x 属性值1,而最后一个控件被赋予Ta b I n d e x 值2。以相反顺序来选定控件并为每个控件赋予Ta b I n d e x 属性值0,要比正向选定它们并输入它们各自的Ta b I n d e x 值容易得多。

注意当使用容器控件,如图文框控件时,你赋予容器控件的Ta b I n d e x 值应该是容器

中接收焦点的第一个控件的Ta b I n d e x 值减1。

图12-1 如果Ta b 次序不正确,就会使用户陷入混乱,并降低他的操作速度。

用户常常必须用鼠标来确定他要操作的对象

图12-2 这里显示的Ta b 次序不包括容器控件的次序。它只是向你

展示用户按下Ta b 键时经过的流程

①①②

⑥④⑧⑧④

⑦⑦⑨

不正确:正确:

(2) 方便时创建对话框中的默认命令按钮和C a n c e l(取消)命令按钮。大多数应用程序都会显示一个模式对话框。这些对话框在关闭前用于搜集用户输入的信息。一般来说,这类对话框至少包含两个命令按钮,即O K(确定)和C a n c e l(取消)。单击O K按钮,可以确认用户的设置,并关闭对话框;单击C a n c e l按钮则可以关闭对话框并取消用户的设置。你也许已经发现,在大多数程序中,按下E s c键的作用与单击C a n c e l按钮是相同的。你可以(并且应该)在你的应用程序中重复这个行为特性。

若要将E s c键赋予一个命令按钮,请将该命令按钮的C a n c e l属性设置为Tr u e。当一个命令按钮的C a n c e l属性被设置为Tr u e,并且窗体上有一个控件拥有焦点时,按下E s c键,就会激活该命令按钮的C l i c k事件。每个窗体上只有一个命令按钮的C a n c e l属性可以设置为Tr u e。如果你将一个命令按钮的C a n c e l属性设置为Tr u e,然后将第二个命令按钮的C a n c e l属性设置为Tr u e,那么第一个按钮的C a n c e l属性将自动被设置为F a l s e。

若要将E n t e r键赋予一个命令按钮,你可以将该按钮的D e f a u l t(默认)属性设置为Tr u e。当一个命令按钮的D e f a u l t属性被设置为Tr u e,并且窗体上有一个控件拥有焦点时,按下E n t e r键,就会激活该按钮的C l i c k事件。与C a n c e l属性的情况一样,每个窗体只能有一个命令按钮的

D e f a u l t属性可以设置为Tr u e,并且将一个命令按钮的D e f a u l t属性设置为Tr u e后,就会使所有其他命令按钮的D e f a u l t属性变为F a l s e。

虽然每个对话框的C a n c e l按钮的C a n c e l属性都应该设置为Tr u e,但是你必须确定是否根据对话框的性质指定一个默认命令按钮(方法是将某个命令按钮的D e f a u l t属性设置为Tr u e)。当你指定默认命令按钮时,应该考虑的主要问题是对话框是否包含任何多行文本框。在多行文本框中,按下E n t e r按钮后,就会创建一个新的文本行(比如当你创建一个新段落时就会出现这种情况)。但是Visual Basic并不会识别这种特殊情况,并且将用户按下E n t e r键解释为对默认按钮的点击。这会使用户非常恼火。如果在对话框中放入了多行文本框,那么最好不要将命令按钮指定为窗体的默认按钮。

(3) 将组合键赋予常用命令按钮。几乎每个人都熟悉菜单中的组合键。当顶层菜单的名字中有一个字母带有下划线(比如F i l e中的字母F)时,按住A l t键的同时按下带下划线的字母键,就可以打开该菜单。但是,许多编程人员不知道,你可以将组合键赋予命令按钮。

究竟如何将组合键赋予命令按钮,这并不容易,因为缺乏专门的组合键属性。若要指定一个组合键,你可以在命令按钮的C a p t i o n属性前面加一个“和”(&)字符。当Visual Basic显示命令按钮的名称时,它就会查找“和”字符。如果找到了一个,该“和”字符不显示出来,而是显示紧跟“和”字符后面的字符,并给它加上下划线,同时该字符便成为该命令按钮的组合键。在按住A l t键的同时按下命令按钮的组合键,就能激活该命令按钮的C l i c k事件,就像用户是用鼠标点击该按钮一样。

注意若要显示按钮名称中的“和”字符,请使用两个“和”字符。例如,若要显示

按钮名称Print & Exit,请将C a p t i o n属性设置为Print && Exit。

组合键具有很强的功能,因为它们为键盘用户提供了一种非常有效的手段,使他们不必点击命令按钮就可以激活这些按钮。因此你应该将组合键赋予窗体上的所有常用命令按钮。但是,当你赋予组合键时,应该注意下面几个问题:

? 不要将组合键赋予D e f a u l t或C a n c e l属性设置为Tr u e的命令按钮。当命令按钮的D e f a u l t或

C a n c e l属性设置为Tr u e时,它就可以通过按下E n t e r键或E s c键而被“点击”,在这种情况

下,就没有必要将组合键赋予命令按钮。比较图1 2-3和图1 2-4。

? 赋予的组合键不要与菜单项的组合键发生冲突。例如,如果窗体有一个F i l e 菜单,F i l e 中的F 应该指定为该菜单的组合键,以便与其他程序保持一致。为此,如果F 已经成为菜单的组合键,那么就不要将字母F 作为窗体上的按钮的组合键,菜单的组合键总是优先起作用。关于菜单的详细说明,请参见第11章。

图12-3 如果没有组合键,用户就不得不使用他需要的命令按钮,

或者设法使用鼠标来进行操作

图12-4 请注意合乎逻辑的组合键的使用方法。C l o s e 按钮

没有组合键,因为它是个默认按钮

(4) 设置与数据域相关联的控件的M a x L e n g t h 属性。当创建数据窗体时,应该尽量使窗体便于使用。你应该使用户能够用键盘对各项功能和菜单进行操作,应该将组合键赋予命令按钮,还要在适当的时候创建默认按钮和C a n c e l 按钮。对于数据输入窗体,可以采取的另一个很有帮助的做法是不让用户过多地在键盘上进行太多的键入操作。

数据库表格中的大多数域都有一个它们能够存放的最大字符数。如果试图将超出允许范围的字符数目存放到数据域中,就会产生图1

2-

5所示的错误。当用户遇到这个错误时,将不得不停止

工作,以确定屏幕上的哪个域出了问题,并减少他输入的字符数目。他常常要缩短输入的项目,不正确:

正确:

然后再次保存输入项,结果发现这个输入项仍然太长。这个输入过程要反复进行,直到最后用户输入的字符串能够放入数据域为止。不过,实在没有说得过去的理由让用户经受这样的麻烦。

图12-5 这肯定不是善待用户的做法

文本框控件配有一个M a x L e n g t h 属性。当单行文本框的M a x L e n g t h 属性设置为

0时(这是默认值),对文本框能够包含的字符数目的唯一限制因素是用户计算机的内存容量。多行文本框的字符数目极限是32 KB 。大于0的任何M a x L e n g t h 都会导致文本框限制它能接受的字符数目。如果用户试图输入的字符数目大于M a x L e n g t h 允许的数目,Visual Basic 将不再允许用户将字符输入该文本框,并发出声响提醒用户。这种方式比允许用户随意输入信息,然后等到你想保存记录时再显示已经出错要好一些。

如果你将文本框与数据控件连接起来,Visual Basic 就会自动设置M a x L e n g t h 属性。这是个非常好的思路,但是实际上它并不会这样去设置该属性。连接文本框控件对控件的M a x L e n g t h 属性没有任何影响,文本框的M a x L e n g t h 属性值与它跟数据源连接之前的M a x L e n g t h 属性值仍然相同。因此,若要防止用户输入文本框的数据量大于基本记录集内能够保存的数据量,必须用人工设置每个文本框的M a x L e n g t h 属性。

你可以采用两种方法来设置M a x L e n g t h 属性。一种方法是在设计时设置文本框的M a x l e n g t h 属性,另一种方法是检索记录集内一个域允许输入的最大字符数,然后在运行时(使用DAO Field 对象的S i z e 属性)设置对应文本框的M a x L e n g t h 属性。后一种方法为你提供了较大的灵活性,因为,如果你改变域的大小,你不必考虑用人工修改访问该域的所有文本框。在运行时设置属性比在设计代码时设置属性要慢一些,但是这种差异是微不足道的。尽管如此,你仍然应该对此有所

考虑。请选择你认为最好的方法,但必须确保M a x L e n g t h 属性的正确设置。比较图12-6和图12-7。

12.3.2 提供统一和直观的鼠标交互操作特性

对于大多数用户来说,鼠标是他们与计算机进行交互操作的主要工具。虽然编程人员常常会忽略键盘用户的需要,但有时他们也会忽略鼠标用户的需要。

实际应用举例

(1) 只要有可能,就应提供弹出式菜单。弹出式菜单是用户右单击

一个对象时弹出的菜图12-6 如果无法保存很长的文本,就不

要让用户输入这么长的文本图12-7 设置文本框的M a x L e n g t h 属性后,就可以限制输入文本框的字符数

右单击,指用鼠标右键单击。

单(见图1 2-8)。这一节的重点并不是介绍弹出式菜单的组织结构,而是要介绍打开弹出式菜单所用的正确方法。Microsoft Windows 95开创了弹出式菜单的新时期,如今,如果没有弹出式菜单,用户简直没有办法过日子。

图12-8 弹出式菜单使用户能够通过右单击一个对象,

迅速访问与上下文相关的各项功能

右单击一个对象是了解应用程序的情况时使用的一种简便方法。例如,如果你不清楚对于Microsoft Outlook 中的某个消息项你能进行什么操作,必须右单击这个消息项,查看与该项目相关的命令的弹出式菜单。应该在程序中尽可能多地创建弹出式菜单。Wi n d o w s 能够为文本框之类的某些控件显示标准的弹出式菜单,因此不必考虑将弹出式菜单添加给窗体上的每个控件。请想像一下,设法将自己放在用户的位置上来考虑问题。一般来说,项目列表(无论是否在列表框中)、树状视图或者列表视图控件,都可以用于显示弹出式菜单。

显示一个项目的弹出式菜单时,该菜单应该包含与右单击的项目相关的一些特定项目。例如,当显示联系人列表中某人名字的弹出式菜单时,按照逻辑,应该显示诸如Add New 、

D e l e t e 、Send Fax 和Dial Phone 等菜单项目。但是,与被单击的对象没有直接关系的项目,如Mark As Read 或Save As 等,就不应该出现在菜单上。弹出式菜单应被视为与上下文相关的菜单。正如按下F 1键对显示与上下文相关的帮助信息一样,右单击一个对象时,应该显示与上下文相关的菜单。

若要显示弹出式菜单,请使用F o r m 对象的P o p u p M e n u 方法。P o p u p M e n u 方法的句法如下:object .PopupMenu menuname, flags, x, y, boldcommand

表12-1 说明了PopupMend 方法的语法。

表 1 2-1

语句元素说明

o b j e c t可选项。显示弹出式菜单的窗体。如果o b j e c t被省略,便使用带有焦点

的窗体

m e n u n a m e必须要有的元素。这是要显示的弹出式菜单的名字。设定的菜单至少必须

拥有一个菜单

F l a g s可选项。用于设定显示的弹出式菜单的位置和运行特性的一个值或常量

x可选项。用于设定显示的弹出式菜单的x坐标。如果省略本元素,则使用

鼠标的x坐标

y可选项。用于设定显示的弹出式菜单的y坐标。如果省略本元素,则使用

鼠标的y坐标

B o l d c o m m a n d可选项。用黑体文本显示的弹出式菜单中的菜单项名字。如果省略本元素,

则弹出式菜单中没有黑体文本项目

若要将F i l e菜单作为窗体上的弹出式菜单来显示(假定菜单控件的名字是m n u F i l e),可以使用下面这个语句:

PopupMenu mnuFile

一般来说,我不喜欢将任何事情当作理所当然的东西,我总是尽可能显式地指定对象,因此我改用下面这个语句:

Me.PopupMenu mnuFile

通常没有必要使用任何一个选项参数,使用默认值就相当不错。但是,如果想调整弹出式菜单的位置或行为特性,请使用一个或多个常量,作为f l a g s参数。如表1 2-2和表1 2-3所示。

表 1 2-2

常量(位置)值描述

v b P o p u p M e n u L e f t A l i g n0弹出式菜单的左边位于x处(默认值)

v b P o p u p M e n u C e n t e r A l i g n4弹出式菜单居中位于x处

v b P o p u p M e n u R i g h t A l i g n8弹出式菜单的右边位于x处

表 1 2-3

常量(行为特性)值描述

v b P o p u p M e n u L e f t B u t t o n0只有当用鼠标左键点击时,弹出式菜单上的项目才对鼠标

点击作出响应(默认值)

v b P o p u p M e n u R i g h t B u t t o n2当用户用鼠标右键或左键点击时,弹出式菜单上的项目便

对鼠标点击作出响应

由于必须显式调用P o p u p M e n u方法才能显示弹出式菜单,因此你应当将代码添加给鼠标事件。用于显示弹出式菜单的正确事件是M o u s e U p事件,而不是M o u s e D o w n事件。

不正确:

Private Sub lstContacts_MouseDown(Button As Integer, _

Shift As Integer, X As Single,Y As Single)

‘* Purpose : Display a pop-up menu for the contact list.

On Error GoTo PROC_ERR

‘* If the user clicked with the right button,

‘* show the menu at the default location.

If Button = vbRightButton Then

Me.PopupMenu mnuContacts

End If

PROC_EXIT:

Exit Sub

PROC_ERR:

Call ShowError(a750fd4733687e21af45a91a, “lstContacts_MouseDown", Err.Number, _

Err.Description)

GoTo PROC_EXIT

End Sub

正确:

Private Sub lstContacts_MouseUp(Button As Integer,_

Shift As Integer, X As Single, Y As Single)

‘* Purpose : Display a pop-up menu for the contact list.

On Error GoTo PROC_ERR

‘* If the user clicked with the right button,

‘* show the menu at the default location.

If Button = vbRightButton Then

Me.PopupMenu mnuContacts

End If

PROC_EXIT:

Exit Sub

PROC_ERR:

Call ShowError(a750fd4733687e21af45a91a, “lstContacts_MouseUp", Err.Number, _

Err.Description)

GoTo PROC_EXIT

End Sub

( 2)用鼠标指针为用户提供反馈信息。大多数时候,鼠标的行为特性就像一个单行道。用户对鼠标进行操作,以便将信息提供给程序,而程序则接收鼠标生成的信息,然后执行某种方式的操作。但是,鼠标也能够运用它的图标将信息发送给用户。

可以改变鼠标指针的图标,方法是更改对象的M o u s e P o i n t e r属性。例如,若要将S c r e e n对象的鼠标指针改为沙漏,请使用下面的语句:

'* set the screen mouse pointer to an hourglass.

Screen.MousePointer = vbHourg lass

表1 2-4列出了M o u s e P o i n t e r属性的常量。这些常量是系统常量,不是枚举值的组成部分。编写代码时,你无法获得这些常量的下拉列表。相反,你必须使用在线H e l p(帮助),或者参考这个表,也可以使用本书所附光盘提供的M o u s e P o i n t e r类,也可以创建你自己的定制枚举值。

注意在本书所附的光盘上,你会找到一个M o u s e P o i n t e r类,可以将它添加给你自己

的项目。这个类将S c r e e n对象的M o u s e P o i n t e r属性包装在一个便于使用的对象中,并

使之包含该常量值的一个枚举值。

表 1 2-4

常量值说明

v b D e f a u l t0由对象规定的形状(默认值)

v b A r r o w1箭头

v b C r o s s h a i r2+ 字光标(+ 字指针)

v b I b e a m3I型光标(常用于文本中的定位)

v b I c o n P o i n t e r4图标(方块中的小方块)

v b S i z e P o i n t e r5调整大小的图标(指向东、南、西和北4个方向的箭头)

v b S i z e N E S W6向东北和西南方向调整大小的图标(指向东北和西南的双向箭头)

v b S i z e N S7向南北方向调整大小的图标(指向南北和双向箭头)

v b S i z e N W S E8向西北和东南方向调整大小的图标(指向西北和东南的双向箭头)

v b S i z e W E9向东西方向调整大小的图标(指向东西的双向箭头)

v b U p A r r o w 1 0上箭头

v b H o u r g l a s s11沙漏(等待图标)

v b N o D r o p 1 2不使用

v b A r r o w H o u r g l a s s 1 3箭头与沙漏混合图标

v b A r r o w Q u e s t i o n 1 4箭头与问号混合图标

v b S i z e A l l 1 5调整所有大小

v b C u s t o m 1 6由Mouse Icon属性设定的自定义图标

虽然上述所有图标都有其特定的用途,但是最常用的两个图标是v b D e f a u l t和v b H o u r g l a s s。当你的程序忙于运行而无法接受来自用户的输入时,将S c r e e n对象的M o u s e P o i n t e r属性设置为v b H o u r g l a s s,就可以显示沙漏图标。当一个程序看上去接受了用户的输入,而实际上并没有接受时,用户就会感到非常迷惑不解。这常常会导致你必须用3个手指进行按键操作(C t r l+A l t+ D e l e t e),这会使事情变得非常复杂。大多数情况下,你可以避免这种情况的出现,方法是显示一个沙漏图标,指明该程序正忙于运行。当进程完成并且控制权返回给用户时,请将S c r e e n 对象的M o u s e P o i n t e r属性重新设置为v b D e f a u l t。

自从Visual Basic的上个版本以来,S c r e e n对象的鼠标指针的行为特性已经发生了变化。在较早的几个版本中,将S c r e e n对象的M o u s e P o i n t e r属性设置为v b H o u r g l a s s,就可以将指针改为沙漏,而不管它在屏幕上的什么位置。而现在,只有当鼠标指针位于你的应用程序窗口上时,对S c r e e n对象的M o u s e P o i n t e r属性所做的修改才会对指针起作用。这样做是很有意义的,因为虽然你的程序正忙于运行,但用户仍可切换到另一个程序继续工作,你并不想影响其他程序中或Wi n d o w s本身中的指针。

当已经改变了鼠标指针的某个过程完成了它的操作时,它始终必须将鼠标指针重新设置为它的默认指针。当鼠标指针的图标不适用于某种情况时,就会使用户感到迷惑不解。例如,当系统运行并不忙时,如果让指针仍然保留为沙漏,用户可能认为他无法与程序进行交互操作,而实际上他是能够对程序进行操作的。这时,你等待着程序将控制权返回给你,而程序却一直等你执行某项操作。

不正确:

Private Sub cmdFil l Years_Click()

‘* Purpose : Fill a list box with the years from 1900 to 2050.

On Error GoTo PROC_ERR

Dim intYear As Integer

Const c_YearMin = 1900

Const c_YearMax = 2050

‘* Set the pointer to an hourglass so that the user knows

‘* we’re busy.

Screen.MousePointer = vbHourglass

'* Populate the list boox with the range of years.

For intYear = c_YearMin To c_YearMax

lstYears.AddItem intYear

Next intYear

PROC_EXIT:

Exit Sub

PROC_ERR:

Call ShowError(a750fd4733687e21af45a91a, “cmdFil l Years_Click", Err.Number, _

Err.Description)

GoTo PROC_EXIT

End Sub

正确:

Private Sub cmdFil l Years_Click()

‘* Purpose : Fill a list box with the years from 1900 to 2050.

On Error GoTo PROC_ERR

Dim intYear As Integer

Const c_YearMin = 1900

Const c_YearMax = 2050

‘* Set the pointer to an hourglass so that the user knows

‘* we’re busy.

Screen.MousePointer = vbHourglass

‘* Populate the list box with the range of years.

Fo r intYear = c_YearMin To c_YearMax

lstYears.AddItem intYear

Next intYear

‘* Restore the mouse pointer.

Screen.MousePointer = vbDefault

PROC_EXIT:

Exit Sub

PROC_ERR:

Call ShowError(a750fd4733687e21af45a91a, “cmdFil l Years_Click", Err.Number, _

Err.Description)

GoTo PROC_EXIT

End Sub

也正确:

Private Sub cmdFil l Years_Click()

‘* Purpose : Fill a list box with the years from 1900 to 2050.

On Error GoTo PROC_ERR

Dim intYear As Integer

Dim intMousePointer As Integer

Const c_YearMin = 1900

Const c_YearMax = 2050

‘* Get the current mouse pointer.

intMousePointer = Screen.MousePointer

‘* Set the pointer to an hourglass so that the user knows

‘* we’re busy.

Screen.MousePointer = vbHourglass

‘* Populate the list box with the range of years.

For intYear = c_YearMin To c_YearMax

lstYears.AddItem intYear

Next intYear

‘* Restore the mouse pointer.

Screen.MousePointer = intMousePointer

PROC_EXIT:

Exit Sub

PROC_ERR:

Call ShowError(a750fd4733687e21af45a91a, “cmdFill Years_Click", Err.Number, _

Err.Description)

GoTo PROC_EXIT

End Sub

(3) 当显示弹出式菜单以便对选定的列表项目进行操作时,始终要在显示弹出式菜单之前选定被点击的项目。虽然鼠标右键可以用来显示弹出式菜单,但是列表框控件并不承认右单击是选定项目的方法。使用对列表框控件中的指定项目进行操作的命令来打开弹出式菜单时,你必须编写代码以便确保鼠标右键点击的项目是菜单出现时被选定的项目。这最好用

M o u s e D o w n事件来实现。

用鼠标右键来选定列表框中的一个项目,比你想像的要困难。实际上你应该考虑鼠标的y 坐标和大写字母的高度,以便计算出被点击的列表行。当你考虑到列表框的容器可能使用许多不同刻度方式中的一个,并且某些容器(比如图文框控件)根本就没有刻度方式时,这个问题就会变得更加复杂。我已经编写了一个过程,你可以将它添加给一个项目,然后通过任何列表框的M o u s e D o w n事件来调用。这个过程用于确定被点击的列表行,如果这个位置上有一个项目,你就可以将它选定。它利用了这样一个条件,即传递给M o u s e D o w n事件的y坐标总是以缇为计量单位,而不管容器的刻度方式是什么,同时它使用列表框的父控件来计算字母的平均高度。如果你将列表框中或父窗体上使用的字体改为非标准字体,这个过程就无法正确运行。

Public Sub SelectListBoxItemFromY(ctlListBox As ListBox, _

intButton As Integer, sngYTwips As Single)

‘* Purpose : Determine which item (if any) in a list box

‘* lies under the y-coordinate, and select it.

‘* Accepts : ctlListBox - the list box control.

‘* intButton - the mouse button clicked.

‘* sngYTwips - the vertical coordinate. This is

‘* expected in twips, which is the way al l MouseDown

‘* events receive it.

On Error GoTo PROC_ERR

Dim intSelectedIndex As Integer

‘* If the user clicked the mouse with a button other than

‘* the right button, get out.

If intButton <> vbRightButton Then GoTo PROC_EXIT

‘* This is a technique for determining which row the user clicked.

‘* We use the letter A to determine how high each row is.

‘* NOTE: Since the list box can appear in any number of containers

‘* having any scale mode, we use the ScaleMode and ScaleY of

‘* the list box’s parent control(usual l y a form) to make

‘* sure al l of the numbers involved are of the same scale.

‘* Remember, y is expected in twips.

intSelectedIndex = (sngYTwips \ _

ctlListBox.Parent.ScaleY(ctlListBox.Parent. _

TextHeight(“A”), ctlListBox.Parent.ScaleMode, _

vbTwips)) + ctlListBox.TopIndex

‘* If the selected index is greater than the index of the last.

‘* item, the empty area below the list was clicked.

‘* Otherwise, a valid item was clicked, so sel ect it.

If intSelectedIndex < ctl ListBox.ListCount Then

ctlListBox.ListIndex = intSelectedIndex

End If

PROC_EXIT:

Exit Sub

PROC_ERR:

Call ShowError(a750fd4733687e21af45a91a, “SelectListBoxItemFromY", Err.Number, _

Err.Description)

GoTo PROC_EXIT

End Sub

若要使用这个过程,你只需通过列表框控件的M o u s e D o w n事件来调用它,并将对列表框、按钮和y坐标的引用传递给它,如下所示:

Private Sub lstNames_MouseDown(Button As Integer, Shift As Integer, _

X As Single, Y As Single)

‘* Purpose : Display a pop-up menu related to the item

‘* clicked if the user clicked with the right mouse

‘* button.

On Error GoTo PROC_EXIT

‘* Select the item where the user clicked if the user clicked with

‘* the right mouse button.

Call SelectListBoxItemFromY(lstNames, Button, Y)

Me.PopupMenu mnuNames

PROC_EXIT:

Exit Sub

PROC_ERR:

Call ShowError(a750fd4733687e21af45a91a, “lstNames_MouseDown“, Err.Number, _

Err.Description)

GoTo PROC_EXIT

End Sub 12.3.3 创建有创意和功能良好的消息框

将某些情况通知用户,最常用的方法是使用M s g B o x 函数。M s g B o x 函数非常灵活,运用该函数,可以提出问题,或者对某些情况进行说明。还可以控制显示的图标类型以及用户可以使用的按钮。由于创建消息框是如此常见和容易的一项工作,因此这个进程是理所当然要执行的,并且很可能创建出很糟糕的消息框。在本节中,我将要介绍创建较好的消息框时你可以使用的一些技巧。

编写消息时,请使用正式的语气,不要使用夸大性的词汇,也不要使用缩写词。文字应该简明易懂,不要使用过分花哨的用语。请记住,消息框不是炫耀文字技巧的场所。它只是用来向用户传达简明扼要的消息。当消息框必须提出问题时,问题必须准确达意,使用能够采取恰到好处的决断。

虽然有时你不得不显示比较长的消息,但是应该尽量使它不要超过两行或3行。要让用户在所有时候都感到非常舒服并能驾驭他的工作环境。如果消息很长,不仅使用户难以把握它的含义,而且也会使用户望而生畏,这是你不愿意看到的。

确实,用户也会出错,有时他们真的会把事情搞得非常糟糕。不过你有责任使他们感到错误并不是他们造成的,尽管实际上是他们出了错。如果消息是作为专用消息而出现的,那么用户就会把它当作针对自己的消息。

实际应用举例

(1) 为既定情况创建适当类型的消息框。消息可分为4种类型,即信息、警告、危急状况和提问(即询问)。信息类消息框应该显示一个i 字样的信息图标(如图1 2-9所示),警告类消息框带有一个惊叹号图标(见图1 2-10),危急状况消息显示一个带有X 字样的红色图标(见图1 2-

11),而向用户提出问题的消息则显示一个问号图标,如图1 2-12所示。若要在消息框中显示图标,必须在M s g B o x 函数的b u t t o n s 参数中提供相应的常量(注意,b u t t o n s 参数实际上用于设定要显示的按钮和图标)。

图12-9 信息类消息框是比较简单的非危

急状况的通知消息。应该显示一

个i 字样的信息图标图1 2-11 危急状况消息框用于将某些绝对必须注意的情况通知用

户。不要将危急状况消息图标用于不太重要的消息上,

你大叫狼来了,而用户却对应该注意的问题麻木不仁图12-10 警告类消息框用于将一些非常重要的消息通知用户。当用户看到惊叹号时,就知道应该注意某个问题

图12-12 问号图标应该用于向用户提出问题的消息框

表1 2-5列出了设定消息框中的图标时使用的常量、常量的值以及它们的说明。

表 1 2-5

M s g B o x 图标常量

值说明V b I n f o r m a t i o n

6 4显示信息图标V b E x c l a m a t i o n

4 8显示惊叹号图标V b C r i t i c a l

1 6显示危急状况消息图标V b Q u s e t i o n 3 2显示问号图标

虽然可以在M s g B o x 函数的第三个参数中设定消息框标题栏中出现的文字,但是常常可以省略t i t l e (标题)参数。省略t i t l e 参数时,Visual Basic 将使用Project Properties (项目属性)对话框中为应用程序标题提供的文字(见图1 2-13)。当允许这样做时,消息框就会给人一种更加统一的感觉,因为它们总是显示程序的名字。比较图1 2-14和图1 2-15。

图12-13 省略M s g B o x 函数的t i t l e 参数,这样,消息框的标题就设置为输入

Project Properties 对话框的应用程序标题

(2) 提供真正有意义的按钮。按照上面的说明规定正确的图标,这只不过是创建好的消息框的第一步。消息框能够显示许多不同的按钮,这取决于你选择在消息框中显示哪个按钮或哪些按钮。表1 2-6列出了设定按钮时使用的常量及其值和说明。

图12-14 消息框中没有消息图标,因此它

无法直观地表示消息的重要性图12-15 这个通知消息必须引起用户的极端重视,里面的惊叹号就是起这个作用。请注意,还可

以创建一个Ye s /N o 消息框,其作用是相同的

正确:

不正确:

表 1 2-6

M s g B o x按钮常量值说明

V b O k O n l y0只显示O K按钮

V b O k C a n c e l1显示O K按钮和C a n c e l按钮

V b A b o r t R e t r y I g n o r e2显示A b o r t(放弃)、R e t r y(重试)和I g n o r e(忽略)按钮

V b Y e s N o C a n c e l3显示Ye s(是)、N o(否)和C a n c e l(取消)按钮

V b Ye s N o4显示Ye s和N o按钮

V b R e t r y C a n c e l5显示R e t r y和C a n c e l按钮

若要为b u t t o n s参数设定多个常量,请使用O r。例如,若要在显示O K按钮时也显示一个惊叹号,请使用下面这个语句:

‘* Combine constants for a single parameter by using Or.

MsgBox “Finished updating table.", vbOKOnly Or vbInformation

消息框的常量是系统常量,可以用在代码中的任何位置,并且必须注意不要对它们互相替使用。例如,M s g B o x函数有一个返回常量v b O K,表示用户点击了O K按钮。常量v b O K的值是1。如果错误地使用下面这个语句编写了一个M s g B o x语句,那么创建的消息框将包含O K铵钮和C a n c e l按钮,而不只是包含O K按钮:

‘* This statement has an error. The constant vbOK should only

‘* be used to check the return value of the MsgBox function.

MsgBox “Finished updating table.", vbOK Or vbInformation

若要指定一个特定按钮作为默认按钮(即周围有一个黑色矩形框的按钮,当用户按下

E n t e r键时即被“点击”),请将表1 2-7中的一个常量添加给b u t t o n s参数。

表 1 2-7

M s g B o x默认按钮常量值说明

vbDefaultButton 10默认的第一个按钮

vbDefaultButton 2 2 56默认的第二个按钮

vbDefaultButton 3 5 12默认的第三个按钮

vbDefaultButton 47 68默认的第四个按钮

应该审慎地选择每个消息框的默认按钮。例如,如果显示的消息框带有Ye s按钮和N o按钮,并且询问用户是否想对他的硬盘进行格式化,那么请将N o设定为默认按钮。消息框上的按钮顺序与b u t t o n s参数中列出的顺序总是相同的。例如,若要使N o按钮成为Ye s/N o消息框中的默认按钮,请使用下面这样的语句:

‘* The button order is the same as listed in the constant.

‘* So button 1 is Yes, and button 2 is No.

If MsgBox(“Format c:?", vbYesNo Or vbQuestion Or vbDefaul tButton2) _

Then ...

使用M s g B o x函数让用户作出一项决定时,该函数将返回表1 2-8中列出的一个值。若要确保代码尽可能做到容易理解,请始终按它的常量来引用其返回值,而不要按它的字面值来引用返回值。见表1 2-8。

选择的所有图标、按钮和默认按钮必须协调一致地工作。例如,如果不是提出要回答

Ye s/N o的问题,那么请不要使用问号图标。如果在执行用户无法撤消的某个操作之前,显示了一个危急状况消息框,那么应该提供一个C a n c e l按钮。每个消息框都各不相同,我无法为每种

情况硬性规定一个原则。请按照下面的思路并且使用常识来创建消息框,并且要考虑每个消息框必须达到什么目的。比较图1 2-16、图1 2-17、图1 2-18和图1 2-19。

表 1 2-8

图12-16 这个消息框存在下面几个问题。首先,如果你要更新用户的文件,那么应该提供一个C a n c e l按钮,这样,用户就能停止更新并对文件进行备份。如果不提供这样

的选项按钮,那么就没有必要使用这个消息框。其次,不应该说按一个按钮,而

应该说点击这个按钮。第三,没有必要告诉用户去点击什么东西,

这是明摆着的情况,无需讲明

(3) 要对所有的消息进行校对。提出这个问题似乎有些傻,然而许多消息显示出来时往往存在许多拼写错误和语法不正确的问题。如果你不经

常从事文字书写工作,那么应该在你的单位里找一个

人来对你写的消息进行校对。另外,如果将程序本地

化为另一种语言,应该找一个能够流利地说这种语言

的人来校对你的消息。

应该将消息框中的文字看作是公司信头上、公司

首席执行官签署的和发送给所有客户的重要文档。如果你的消息太简单,将不利于公司的形象。如果你有一位编程员,他的文字表达能力比较欠缺,那么请为他编写消息框语句,或者在发布消息之前,至少应该对它们进行认真地校对。

(4) 消息框中不要使用技术性术语。以前你是否曾经想对从未搞过编程的人讲述与编程相关的问题呢?如果你这样做过,你一定熟悉人们的脸上表现出的那种不明所以的眼神,它就像你的头上戴了一顶装了一个小推进器的红黄色小帽。生活在一个科技发达的时代并且经常使用各种技术产品时,很容易忘记并非人人都精通技术。另外,一个人使用了软件,并不意味着他是个专业技术人员。

图12-17 这个消息框言简意赅,而且为用

户提供了一个机会,使他能够防

止启动无法逆转的进程

图12-18 即使不考虑拼写错误,这也是个不怎

么样的消息。究竟不能将什么东西放

在什么地方呢?为什么使用惊叹号呢?

图12-19 请注意这个消息使用了比较友好的语句

和信息图标。这个消息框对用户很有帮

助,不会使人不快

除非你的程序是为某个特定纵向市场编写的,否则请不要在消息中使用技术性术语。请记住,消息应该言简意明。使用技术性术语时,就有可能使读者搞不清消息的含义。如果你发现自己创建的消息带有技术性术语,请考虑以非技术性语言重新编写消息。

用户要不断地与程序进行交互操作。应该使他们能够非常容易地在你的程序中移动,执行他们为完成任务而需要执行的功能。当程序必须停止用户的工作流程,以便显示一个通知消息,或者获取对某个问题的答案时,应该尽量使它以最清楚和最简洁的方式来达到这个目的。交互操作越是顺利,用户的工作效率就越高(并且更加喜欢你的程序)。

本文来源:https://www.bwwdw.com/article/jaqe.html

Top