事件(Event)是AutoCAD用来告知或提醒用户(更多的应该是程序员)当前会话的状态、事情的发生等而发出的消息。例如保存一个文档时,BeginSave事件就会被触发。其他的像图形的关闭、命令的开始、系统变量的改变等都会触发事件。通过捕获事件,程序员可以编写自己的事件处理程序来对感兴趣的事件做出合理的响应。 事件的分类 事件大致可分为以下9类:Application、Database、Document、DocumentCollection、Editor、Graphics、Plotting、Publishing、Runtime、Windows 事件的处理
当事件被触发之后,需要对事件进行捕获并做出相应的处理,做出处理的函数被称为事件处理函数(event handler),被指定的事件处理函数将会在事件触发之后自动的执行,由于事件能够产生一些参数,因此可被传递到事件处理函数中去,使得处理函数能够识别事件的来源和它所携带的参数,从而做出更精细的处理。
由于事件只是简单的提供了某些信息,事件处理函数则要根据这些信息来执行,并反馈到AutoCAD中去,所以如何正确的编写事件处理函数将会显得很重要。
关于编写事件处理函数需要注意以下几点:
1.
不要依赖事件顺序 当执行一个动作的时候,可能会产生一系列的事件,而且这些事件的顺序并不总是按某种特定的顺序产生的,唯一能确定顺序的是某个事件的开始和结束 2.
不要依赖操作的顺序 例如使用erase命令删除实体1然后再删除实体2,不要固执的以为会先收到实体1的ObjectErased事件,或许恰好相反 3.
不要在事件处理函数中使用交互操作 由于事件被触发时,AutoCAD可能仍旧在执行命令,所以使用交互操作会带来严重的问题,简单的可能会导致命令被中断,严重会导致AutoCAD崩溃。所以在事件处理函数中不要提示用户输入、实体的选择、或者使用SendStringToExecute方法发送命令。 4.
不要在事件处理函数中使用对话框 由于对话框可能会影响到AutoCAD的操作,所以也被视为交互操作。不过消息框和警告框可以放心的使用,但也不是所有的事件处理函数中都可以的,例如对EnterModal、 LeaveModal,、DocumentActivated以及DocumentToBeDeactivated的事件处理函数中可能导致不可预知的错误。 5.
不要在针对某个事件的处理函数中再次触发该事件 原因很简单,这回导致死循环 6.
当AutoCAD显示一个模式对话框的时候并不会触发事件 事件的注册和注销 事件编程可以简单地分成两个部分:事件发生的类和事件接收处理的类。事件发生的类就是说在这个类中触发了一个事件,但这个类并不知道哪个对象或方法将会接收到并处理它触发的事件,因此要在发送方和接收方之间存在一个媒介。这个媒介在.NET Framework中就是委托(delegate),通过委托完成了事件的注册。 只有先注册了事件之后才能调用相应的事件处理函数,这相当于告诉AutoCAD,我们对什么样的事件感兴趣,并且当这个事件发生的时候,它要做的事。当不再对这个事件感兴趣的时候,也可以注销该事件,这也可以释放系统的资源。
注册事件使用+=操作符,而注销则使用-=操作符。注册事件就是把事件处理函数和事件捆绑起来,大部分的事件处理函数通常有两个形参,一个代表发送事件的对象,另一个则为事件的返回参数。
例如下面将会注册一个事件,即当系统变量发生改变的时候将会触发事件处理函数:
- <div align="left">Application.SystemVariableChanged +=</div><div align="left">new
- SystemVariableChangedEventHandler(MyHandler);</div>
复制代码 |
相应的,注销一个事件则为:
- <div align="left">Application.SystemVariableChanged -=</div><div align="left">new SystemVariableChangedEventHandler(MyHandler);</div>
复制代码 |
其他的事件可以采用类似的方法实现注册和注销。 处理Application事件 Application代表了AutoCAD的程序窗口,因此这类事件主要针对AutoCAD该程序,这类事件除非AutoCAD关系或者显式的注销,否则将一直处于注册状态。 下面是一些常见的事件及触发事件的说明
事件
|
说明
|
BeginCustomizationMode
|
AutoCAD进入自定义模式前触发
|
BeginDoubleClick
|
双击鼠标后触发
|
BeginQuit
|
AutoCAD准备退出前触发
|
DisplayingCustomizeDialog
|
在自定义对话框显示前触发
|
DisplayingOptionDialog
|
在选项对话框被显示前触发
|
EndCustomizationMode
|
当AutoCAD退出自定义模式后触发
|
EnterModal
|
在一个模式对话框被打开之前触发
|
Idle
|
当程序空闲的时候触发
|
LeaveModal
|
当一个有模式对话框被关闭之后触发
|
QuitAborted
|
当放弃退出程序时触发
|
QuitWillStart
|
当BeginQuit被触发后并在准备关闭程序前触发
|
SystemVariableChanged
|
系统变量被改变后触发
|
SystemVariableChanging
|
正试图改变系统变量前触发
|
下面是一个例子:
[CommandMethod("reg")]
public void reg()
{
- <div align="left">
- Application.BeginQuit+=newEventHandler(Application_BeginQuit);</div><div align="left">}
- </div><div align="left">public void Application_BeginQuit(object sender, EventArgs e)<font size="3">
- </font></div><div align="left">{
- </div><div align="left">
- Application.ShowAlertDialog("你要退出系统!");<font size="3">
- </font></div><div align="left">}</div>
复制代码
|
执行reg命令后,将会注册一个事件,当AutoCAD准备退出系统是,就会执行Application_BeginQuit方法,弹出一个对话框,虽然确定之后还是会退出系统,这似乎并不能改变关闭程序的作用,这里做一点解释。Application_BeginQuit的第二个e的类型为EventArgs,这是事件参数的基本类型,在AutoCAD1006中似乎没有和BeginQuit事件专门对应的事件参数类,所以使用的是C#.NET中的基本类型,据说是对托管程序封装的不完整吧,在2010等版本中有对应的事件类,可以使用e.Veto();将该事件抛弃。 处理Document事件 文档事件对应AutoCAD中的文档窗口,文档事件只和它关联的文档建立联系,因此如果文档事件需要在每个文档中注册,必须使用DocumentCollection对象的DocumentCreated事件来注册对每一个打开或创建的文档进行事件的注册。 下面是一些常见的事件及触发事件的说明
事件
|
说明
|
BeginDocumentClose
|
当收到关闭文档的请求时触发
|
CloseAborted
|
当试图放弃关闭文档时触发
|
CloseWillStart
|
当BeginDocumentClose已被触发,并在文档关闭前触发
|
CommandCancelled
|
命令在执行完之前被取消后触发
|
CommandEnded
|
命令执行完后触发
|
CommandFailed
|
命令不是由于取消而执行失败后触发
|
CommandWillStart
|
命令被提交,但在执行前触发
|
ImpliedSelectionChanged
|
当前向选择集(pickfirst selection set)发生改变后触发
|
UnknownCommand
|
当命令行中收到不可知命令后触发
|
下面的例子演示捕获关闭文档所触发的事件,并毫不含糊地阻止文档关闭。
- <div align="left">[CommandMethod("reg")]<font size="3">
- </font></div><div align="left">public void reg()<font size="3">
- </font></div><div align="left">{
- </div><div align="left"> doc.BeginDocumentClose += newDocumentBeginCloseEventHandler(doc_BeginDocumentClose);<font size="3">
- </font></div><div align="left"> doc.Editor.WriteMessage("\n注册完成");<font size="3">
- </font></div><div align="left">}
- </div><div align="left">[CommandMethod("irreg")]<font size="3">
- </font></div><div align="left">public void irreg()<font size="3">
- </font></div><div align="left">{
- </div><div align="left"> doc.BeginDocumentClose -= newDocumentBeginCloseEventHandler(doc_BeginDocumentClose);<font size="3">
- </font></div><div align="left"> doc.Editor.WriteMessage("\n注销完成");<font size="3">
- </font></div><div align="left">}
- </div><div align="left">public void doc_BeginDocumentClose(object sender,DocumentBeginCloseEventArgs e)<font size="3">
- </font></div><div align="left">{
- </div><div align="left"> e.Veto();
- </div><div align="left">}</div>
复制代码 |
程序的逻辑很清晰明了,但是在AutoCAD2006下测试却没有通过,在AutoCAD2008下测试通过了,不知道是不是06对.NET支持的不够完善还是托管程序的封装有问题,没有考虑到06这个版本…… 处理DocumentCollection事件 文档集合对应于处理AutoCAD所有已打开的文件产生的事件,文档集合事件和文档事件不同,更像是应用程序事件,即除非AutoCAD关系或者显式的注销,否则将一直处于注册状态。 下面是一些常见的事件及触发事件的说明
事件
|
说明
|
DocumentActivated
|
当一个文档窗口被激活后触发
|
DocumentCreated
|
当有新的文档被创建或已存在的文件被打开后触发
|
DocumentActivationChanged
|
当前活动文档被关闭或者转变为失活状态时触发
|
DocumentBecameCurrent
|
当一个不同于当前文档窗口的另一个文档窗口被设置为当前窗口时触发
|
DocumentCreateStarted
|
在一个新文档窗口被创建或已存在文件被打开前触发
|
DocumentToBeActivated
|
当一个文档将要被激活前触发
|
DocumentToBeDeactivated
|
当一个文档将要失活前触发
|
DocumentToBeDestroyed
|
当一个文档将要被关闭前触发
|
下例是当一个文档被激活时弹出一个显示该文档名称的对话框。
- <div align="left">[CommandMethod("reg")]<font size="3">
- </font></div><div align="left">public void reg()<font size="3">
- </font></div><div align="left">{
- </div><div align="left">
- Application.DocumentManager.DocumentActivated +=newDocumentCollectionEventHandler(DocumentManager_DocumentActivated);</div><div align="left">
- Application.DocumentManager.MdiActiveDocument.Editor.WriteMessage("\n注册完成");<font size="3">
- </font></div><div align="left">}
- </div><div align="left">[CommandMethod("irreg")]<font size="3">
- </font></div><div align="left">public void irreg()<font size="3">
- </font></div><div align="left">{
- </div><div align="left">
- Application.DocumentManager.DocumentActivated -= newDocumentCollectionEventHandler(DocumentManager_DocumentActivated);</div><div align="left">
- Application.DocumentManager.MdiActiveDocument.Editor.WriteMessage("\n注册完成");<font size="3">
- </font></div><div align="left">}
- </div>
- <div align="left">public void DocumentManager_DocumentActivated(object sender,DocumentCollectionEventArgs e)<font size="3">
- </font></div><div align="left">{
- </div><div align="left">
- Application.ShowAlertDialog(e.Document.Name +" 被激活.");</div>
复制代码}
|
当有不同于当前文档的其他文档被激活时,将会弹出一个警告框显示被激活文档的名称。
转自:http://379910987.blog.163.com/
|