演练:处理事件

更新:2007 年 11 月

这是说明如何处理事件的两个主题中的第二个主题。第一个主题演练:声明和引发事件演示如何声明和引发事件。本节使用该演练中的窗体和类来展示当事件发生时如何进行处理。

Widget 类示例使用传统的事件处理语句。Visual Basic 提供了其他处理事件的技术。作为练习,您可以修改该示例以使用 AddHandler 和 Handles 语句。

处理 Widget 类的 PercentDone 事件

  • 在 Form1 中插入下列代码:

    Private WithEvents mWidget As Widget
    Private mblnCancel As Boolean
    

    WithEvents 关键字指定 mWidget 变量用于处理对象的事件。通过提供将从其中创建对象的类的名称来指定对象的类型。

    变量 mWidget 在 Form1 中声明,因为 WithEvents 变量必须是类级变量。无论要将这些变量放入什么类型的类,都是这样。

    mblnCancel 变量用于取消 LongTask 方法。

编写代码来处理事件

在使用 WithEvents 声明变量后,变量名称立即显示在类的“代码编辑器”左边的下拉列表中。当选择 mWidget 时,Widget 类的事件显示在右边的下拉列表中。选择一个事件就会显示带有 mWidget 前缀和下划线的对应的事件过程。与某 WithEvents 变量关联的所有事件过程均以该变量名作为前缀。

处理事件

  1. 从“代码编辑器”左边的下拉列表中选择 mWidget。

  2. 从右边的下拉列表中选择 PercentDone 事件。“代码编辑器”将打开 mWidget_PercentDone 事件过程。

    说明:

    “代码编辑器”对于插入新的事件处理程序很有用,但不是必需的。在此演练中,仅将事件处理程序直接复制到代码中将更为直接。

  3. 将下面的代码添加到 mWidget_PercentDone 事件处理程序中:

    Private Sub mWidget_PercentDone( _
        ByVal Percent As Single, _
        ByRef Cancel As Boolean _
    ) Handles mWidget.PercentDone
        lblPercentDone.Text = CInt(100 * Percent) & "%"
        My.Application.DoEvents()
        If mblnCancel Then Cancel = True
    End Sub
    

    每当引发 PercentDone 事件时,事件过程就会在一个 Label 控件中显示完成百分比。DoEvents 方法允许重新绘制标签,并且还为用户提供机会单击“取消”按钮。

  4. 为 Button2_Click 事件处理程序添加下面的代码:

    Private Sub Button2_Click( _
        ByVal sender As Object, _
        ByVal e As System.EventArgs _
    ) Handles Button2.Click
        mblnCancel = True
    End Sub
    

如果用户在 LongTask 运行时单击“取消”按钮,则 Button2_Click 事件将在 DoEvents 语句允许进行事件处理时立即执行。类级变量 mblnCancel 设置为 True,然后 mWidget_PercentDone 事件测试它并将 ByRef Cancel 参数设置为 True。

将 WithEvents 变量连接到对象

现在已设置好 Form1,可以处理 Widget 对象的事件。余下的所有工作就是在某处找到一个 Widget。

当在设计时声明 WithEvents 变量时,并没有对象与之相关联。WithEvents 变量就像其他任何对象变量一样。必须创建一个对象并使用 WithEvents 变量为其分配一个引用。

创建对象并为其分配一个引用

  1. 从“代码编辑器”左边的下拉列表中选择 “(Form1 事件)”。

  2. 从右边的下拉列表中选择 Load 事件。“代码编辑器”将打开 Form1_Load 事件过程。

  3. 为 Form1_Load 事件过程添加下面的代码以创建 Widget:

    Private Sub Form1_Load( _
        ByVal sender As System.Object, _
        ByVal e As System.EventArgs _
    ) Handles MyBase.Load
        mWidget = New Widget
    End Sub
    

当执行这段代码时,Visual Basic 将创建一个 Widget 对象,并将其事件连接到与 mWidget 相关联的事件过程。自此以后,每当 Widget 引发其 PercentDone 事件时,就会执行 mWidget_PercentDone 事件过程。

调用 LongTask 方法

  • 将下面的代码添加到 Button1_Click 事件处理程序中:

    Private Sub Button1_Click( _
        ByVal sender As Object, _
        ByVal e As System.EventArgs _
    ) Handles Button1.Click
        mblnCancel = False
        lblPercentDone.Text = "0%"
        lblPercentDone.Refresh()
        mWidget.LongTask(12.2, 0.33)
        If Not mblnCancel Then lblPercentDone.Text = CStr(100) & "%"
    End Sub
    

在调用 LongTask 方法之前,必须初始化将显示完成百分比的标签,而且用于取消该方法的类级 Boolean 标志必须设置为 False。

调用 LongTask,其任务持续时间为 12.2 秒。每 1/3 秒引发一次 PercentDone 事件。每次引发该事件时,都会执行 mWidget_PercentDone 事件过程。

当 LongTask 完成以后,将测试 mblnCancel 以查看 LongTask 是否正常结束,或者它是否因为 mblnCancel 设置为 True 而停止。仅在前一种情况下才会更新完成百分比。

运行程序

  1. 按 F5 键使该项目进入运行模式。

  2. 单击“开始任务”按钮。每次引发 PercentDone 事件时,都将以任务完成的百分比来更新标签。

  3. 单击“取消”按钮停止任务。请注意,当单击“取消”按钮时,其外观并不立即更改。直到 My.Application.DoEvents 语句允许进行事件处理时才会发生 Click 事件。

    说明:

    My.Application.DoEvents 方法不会完全像窗体那样处理事件。例如,在此演练中,必须单击“取消”按钮两次。若要允许窗体直接处理事件,可以使用多线程处理。有关更多信息,请参见多线程处理 (Visual Basic)

您可能发现按 F11 键逐句通过代码(即一次一行)的方式运行程序很有益。这样可以清楚地看到执行焦点如何进入 LongTask,以及每次引发 PercentDone 事件以后如何暂时地重新进入 Form1。

如果当执行焦点返回 Form1 的代码中时,LongTask 方法再次被调用,这时会发生什么情况呢? 在最坏的情况下,如果每次引发该事件时都调用 LongTask,那么可能发生堆栈溢出。

可以通过向 mWidget 分配对新 Widget 的引用而使 mWidget 变量处理另一个 Widget 对象的事件。实际上,可以让 Button1_Click 中的代码在每次单击该按钮时实现此操作。

处理另一个小部件的事件

  • 将下面一行代码添加到 Button1_Click 过程,并放置在 mWidget.LongTask(12.2, 0.33) 的紧前面:

    mWidget = New Widget
    ' Create a new Widget object.
    

上面的代码在每次单击该按钮时均创建一个新的 Widget。在 LongTask 方法完成后,立即释放对该 Widget 的引用并销毁 Widget。

WithEvents 变量一次只能包含一个对象引用,所以如果向 mWidget 分配了另一个 Widget 对象,则将不会再处理以前的 Widget 对象的事件。如果 mWidget 是唯一包含对旧 Widget 的引用的对象变量,则销毁该对象。如果需要处理几个 Widget 对象的事件,则使用 AddHandler 语句来分别处理每个对象的事件。

说明:

可以根据需要声明任意多个 WithEvents 变量,但不支持 WithEvents 变量的数组。

请参见

任务

演练:声明和引发事件

如何:编写事件处理程序

概念

事件和事件处理程序

委托和 AddressOf 运算符

AddHandler 和 RemoveHandler

参考

Handles

WithEvents

其他资源

多态性