这是演示如何处理事件的两个主题中的第二个主题。 第一个主题 演练:声明和引发事件,演示如何声明和引发事件。 本部分使用该演练中的窗体和类来演示如何在事件发生时对事件进行处理。
类 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
。