声明和引发事件

暂且假设有一个 Widget 类。该 Widget 类有一种方法,该方法可能花费很长时间来执行,同时还希望自己的应用程序能够显示出一些类型的完成标志。

当然,可以让 Widget 对象显示一个用来表示完成百分比的对话框,但是以后在每个使用 Widget 对象的工程中,就会都离不开那个对话框了。对象设计的一个较好的原则是让使用该对象的应用程序来处理用户接口—除非设计该对象的全部意图是管理一个窗体或者一个对话框。

Widget 的作用是执行其它任务,因此合理的做法是:把一个 PercentDone 事件给它,然后让调用 Widget 方法的过程来处理那个事件。PercentDone 事件也可以提供一种机制来取消任务。

现在,可以开始为该主题来建立代码示例了,方法是打开一个“标准 EXE”工程,将两个按钮和一个标签添加到“Form1”中。在“工程”菜单上,选择“添加类模块”,将一个类模块添加到工程中。象下表中所示的那样给对象命名。

对象 属性 设置值
类模块 Name Widget
第一个按钮 Caption 启动任务
第二个按钮 Caption 取消
标签 Name
Caption
lblPercentDone
"0"

Widget 类

在类模块的声明部分,用 Event 关键字来声明事件。事件可以有 ByVal 和 ByRef 参数,就象 Widget 的 PercentDone 事件所演示的那样:

Option Explicit
Public Event PercentDone(ByVal Percent As Single, _
ByRef Cancel As Boolean)

当调用对象得到 PercentDone 事件时,Percent 参数包含了任务完成的百分比。可以将 ByRef Cancel 参数设置为 True,以取消引发该事件的方法。

注意   可以象声明过程参数那样声明事件参数,所不同的是:事件不能有命名的参数、可选的参数、或 ParamArray 参数。事件没有返回值。

引发 PercentDone 事件

PercentDone 事件是由 Widget 类的 LongTask 方法引发的。LongTask 方法接受两个参数:该方法工作所要求的时间长度,以及 LongTask 在暂停之前产生 PercentDone 事件的最小时间间隔。

Public Sub LongTask(ByVal Duration As Single, _
ByVal MinimumInterval As Single)
   Dim sngThreshold As Single
   Dim sngStart As Single
   Dim blnCancel As Boolean
   
   'Timer 函数按 Single 返回午夜以来秒数的分数值。
   sngStart = Timer
   sngThreshold = MinimumInterval
   
   Do While Timer < (sngStart + Duration)
      '在实际应用程序中,每次循环时将会在这里
      '做某些单元的工作。
      
      If Timer > (sngStart + sngThreshold) Then
         RaiseEvent PercentDone( _
         sngThreshold / Duration, blnCancel)
         '检查一下,看看操作是否被取消。
         If blnCancel Then Exit Sub
         sngThreshold = sngThreshold + MinimumInterval
      End If
   Loop
End Sub

每隔 MinimumInterval 秒,都会引发 PercentDone 事件。当该事件返回时,LongTask 将检查 Cancel 参数是否设置为 True。

注意   为了简单起见,LongTask 假定事先已经知道任务将持续多长时间。但是,这几乎是不可能的。将任务分解成平均大小的块,可能是比较困难的,而且经常困扰用户的问题是,在他们得到某件事已经发生的指示前,真正经过的时间量。

详细信息   现在已经声明并引发了一个事件,怎样才能使得另一个对象来处理这个事件?下面的“处理对象的事件”,将就 Widget 对象引发继续详细讨论这个问题。