这是演示如何处理事件的两个主题中的第二个主题。 第一个主题 演练:声明和引发事件,演示如何声明和引发事件。 本部分使用该演练中的窗体和类来演示如何在事件发生时对事件进行处理。
类 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 变量关联的所有事件过程都以前缀的形式提供变量名称。
处理事件
在
mWidget中, 从左侧下拉列表中选择。从右侧的下拉列表中选择
PercentDone事件。 代码编辑器将打开mWidget_PercentDone事件过程。注释
插入新事件处理程序时 ,代码编辑器 非常有用,但不是必需的。 在本演练中,更直接的方式是直接将事件处理程序直接复制到代码中。
将以下代码添加到
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允许标签重新制作,并为用户提供单击“ 取消 ”按钮的机会。为
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 。
创建对象并为其分配引用
在代码编辑器的左侧下拉列表中选择(Form1 事件)。
从右侧的下拉列表中选择
Load事件。 代码编辑器将打开Form1_Load事件过程。为事件过程添加以下代码
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 秒。 每三分之一秒引发一次 PercentDone 事件。 每次引发事件时,mWidget_PercentDone都会执行事件处理程序。
当LongTask完成后,测试mblnCancel以查看是否LongTask正常结束,或者是否因为mblnCancel设置为True而停止。 只有在前一种情况下才会更新完成百分比。
运行程序
按 F5 将项目置于运行模式。
单击 “开始任务 ”按钮。 每次引发
PercentDone事件时,都会使用完成的任务百分比来更新标签。单击“ 取消 ”按钮停止任务。 请注意,单击“ 取消” 按钮的外观不会立即更改。 在
Click语句允许事件处理之后,My.Application.DoEvents事件才能发生。注释
该方法
My.Application.DoEvents不会以与表单完全相同的方式处理事件。 例如,在本演练中,必须单击“ 取消 ”按钮两次。 若要允许窗体直接处理事件,可以使用多线程处理。 有关详细信息,请参阅 托管线程处理。
你可能会发现,使用 F11 运行程序并逐行执行代码会具有启发性。 这样一来,你可以清楚地了解执行进入 LongTask,并且随后在每次引发 Form1 事件时短暂重新进入 PercentDone 的方式。
当代码Form1正在执行时,如果再次调用LongTask方法,会发生什么情况? 最坏的情况是,如果每次引发事件时调用 LongTask,可能会发生堆栈溢出。
可以通过将对新mWidget的引用分配给Widget,使变量Widget处理不同mWidget对象的事件。 事实上,每次单击 Button1_Click 按钮时,都可以使该按钮中的代码执行此操作。
处理不同小组件的事件
将以下代码行添加到
Button1_Click过程,紧邻读取mWidget.LongTask(12.2, 0.33)的行前面:mWidget = New Widget ' Create a new Widget object.
每次单击按钮时,上述代码都会创建新的 Widget 代码。
LongTask方法完成后,将释放对Widget的引用,并销毁Widget。
变量 WithEvents 一次只能包含一个对象引用,因此,如果将另 Widget 一个对象分配给该对象 mWidget,则不再处理上 Widget 一个对象的事件。 如果 mWidget 是唯一包含对旧 Widget对象的引用的对象变量,则会销毁该对象。 如果要处理来自多个 Widget 对象的事件,请使用 AddHandler 语句单独处理每个对象中的事件。
注释
可以根据需要声明任意数量的 WithEvents 变量,但不支持变量数组 WithEvents 。