演练:处理事件 (Visual Basic)

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

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 方法不会完全像窗体那样处理事件。例如,在此演练中,必须单击“取消”按钮两次。若要允许窗体直接处理事件,可以使用多线程处理。有关更多信息,请参见线程处理(C# 和 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 变量的数组。

请参见

任务

演练:声明和引发事件 (Visual Basic)

其他资源

事件 (Visual Basic)