第7章 事件 本章将讨论AutoCAD中的事件。我们将介绍事件处理函数的使用,特别是监视AutoCAD命令的事件处理函数和监视被AutoCAD命令修改的对象的事件处理函数。在解释怎样实现AutoCAD的事件处理之前,我们将首先简要地讨论一下.NET中的事件。 第一部分 VB.NET中的事件 事件只是用来通知一个行为已经发生的信息。在ObjectARX中,我们使用反应器(reactor)来处理AutoCAD的事件。而在AutoCAD .NET API中,ObjectARX反应器被换成了事件。 事件处理函数(或者叫回调函数)是用来监视和反馈程序中出现的事件。事件可以以不同的形式出现。 在介绍AutoCAD .NET API中的事件之前,让我们先来简单地了解一下代理。 第1a部分 代理 代理是一个存储方法索引的类(概念与函数指针类似)。代理对方法是类型安全的(与C中的函数指针类似)。代理有特定的形式和返回类型。代理可以封装符合这种特定形式的任何方法。 代理的一个用途就是作为产生事件的类的分发器。事件是.NET环境中第一级别的对象。虽然VB.NET把事件处理的许多细节给隐藏掉了,但事件总是由代理来实现的。事件代理可以多次调用(就是它们可以存储多于1个的事件处理方法的索引)。它们保存了用于事件的一个注册事件处理的列表。一个典型的代理有以下的形式: Public Delegate Event (sender as Object, e as EventArgs) 第一个参数sender表示引发事件的对象。第二个参数e是一个EventArgs参数(或者是一个派生的类),这个对象通常包含用于事件处理函数的数据。 第1b部分 AddHandler和RemoveHandler语句 要使用事件处理函数,我们必须把它与事件联系起来。这要通过使用AddHandler语句。AddHandler和RemoveHandler允许你在运行时连接、断开或修改与事件联系的处理函数。 当我们使用AddHandler语句时,我们要确定事件引发者的名字,并要使用AddressOf语句来确定事件处理函数,例如: AddHandler MyClass1.AnEvent, AddressOf EHandler 前面我们说过要使用RemoveHandler语句从事件处理函数中断开事件(移除联系)。语法如下所示: RemoveHandler MyClass1.AnEvent, AddressOf EHandler 第2部分 处理.NET中的AutoCAD事件 在ObjectARX中,我们使用反应器来封装AutoCAD事件。在AutoCAD .NET API中,我们可以使用事件来代替ObjectARX反应器。 通常,处理AutoCAD事件的步骤如下: 1. 创建事件处理函数 当一个事件发生时,事件处理函数(或称为回调函数)被调用。任何我们想要处理的回应AutoCAD事件的动作都在事件处理函数中进行。 例如,假定我们只想通知用户一个AutoCAD对象已被加入。我们可以使用AutoCAD数据库事件”ObjectAppended”来完成。我们可以编写回调函数(事件处理函数)如下: Sub objAppended(ByVal o As Object, ByVal e As ObjectEventArgs) MessageBox.Show("ObjectAppended!") ‘在这里加入一些代码 End Sub 函数中的第一个参数代表AutoCAD数据库。第二个参数代表ObjectEventArgs类,它可能包含对处理函数有用的数据。 2. 把事件处理函数与事件联系起来 为了开始监视动作,我们必须把事件处理函数与事件联系起来。在这里,当一个对象加入到数据库时,ObjectAppended事件将会发生。但是,事件处理函数不会响应这个事件,除非我们把它与这个事件联系起来,例如: Dim db As Database db = HostApplicationServices.WorkingDatabase() AddHandler db.ObjectAppended, New ObjectEventHandler(AddressOf objAppended) 3. 断开事件处理函数 要终止监视一个动作,我们必须断开事件处理函数与事件的联系。当对象被加入时,我们想要停止通知用户这个事件,我们要断开事件处理函数与事件ObjectAppended的联系。 RemoveHandler db.ObjectAppended, AddressOf objAppended 第3部分 使用事件处理函数来控制AutoCAD的行为 本章的目的是解释AutoCAD事件怎样才能被用于控制AutoCAD图形中的行为。现在,让我们使用前一章(第六章)的内容在AutoCAD图形中创建几个EMPLOYEE块索引。我们不想让用户能改变EMPLOYEE块索引的位置,而对于其它的非EMPLOYEE块索引的位置则没有这个限制。我们将混合使用数据库与文档事件来做到这一点。 首先,我们想要监视将要被执行的AutoCAD命令(使用CommandWillStart事件)。特别地,我们要监视MOVE命令。另外,当一个对象要被修改时,我们应该被通知(使用ObjectOpenedForModify事件),这样我们可以确定它是否为一个EMPLOYEE块索引。如果这时就修改对象可能是无效的,因为我们的修改可能会再次触发事件,从而引起不稳定的行为。所以,我们要等待Move命令的执行结束(使用CommandEnded事件),这时就可以安全地修改对象了。当然,任何对块索引的修改将会触发ObjectOpenedForModify事件。我们还需要设置一些全局变量来表明一个MOVE命令在运行和被修改的对象是一个EMPLOYEE块索引。 注意:因为本章需要比较多的代码来获得想要的结果,所以我们不会解释任何与事件处理无关的代码,而只是将它们粘贴到事件处理函数中。这里的重点是成功创建和注册事件处理函数。 第一步:创建新工程 我们以第六章的工程开始。请新加入一个类AsdkClass2。我们还要加入四个全局变量。前两个是Boolean型的:一个用来表示我们监视的命令是否是活动的,另外一个用来表示ObjectOpenedForModify事件处理函数是否该被忽略。 ''''全局变量 Dim bEditCommand As Boolean Dim bDoRepositioning As Boolean 接下来,我们要声明一个全局变量来表示一个ObjectIdCollection,它用来存储我们所选择的要修改的对象的ObjectID。 Dim changedObjects As New ObjectIdCollection() 最后,我们要声明一个全局变量来表示一个Point3dCollection,它用来包含我们所选对象的位置(三维点)。 Dim employeePositions As New Point3dCollection() 第2步:创建第一个文档事件处理函数(回调函数) 现在我们要创建一个事件处理函数。当AutoCAD命令开始执行的时候它会通知我们。我们要检查GlobalCommandName的值是否为MOVE。 If e.GlobalCommandName = "MOVE" Then ''''Set the global variables ‘ [1] [2] [3] [4] 下一页 [C语言系列]NET 中C#的switch语句的语法 [系统软件]托拽Explore中的文件到VB.net的窗口 [系统软件]Boost库在XP+Visual C++.net中的安装 [常用软件]新配色面板:Paint.Net3.0RC1官方下载 [常用软件]用内建的“Net Meeting”聊天 [VB.NET程序]Henry的VB.NET之旅(三)—共享成员 [VB.NET程序]Henry的VB.NET之旅(二)—构造与析构 [VB.NET程序]Henry的VB.NET之旅(一)—失踪的窗体 [VB.NET程序]在托盘上显示Balloon Tooltip(VB.NET) [VB.NET程序]Henry手记-VB.NET中动态加载Treeview节点(二)
|