本文是「Inventor API 进阶」系列第 4 篇。你想在用户保存文件时自动填充 iProperties?在参数变化时触发计算?事件编程是答案。
什么是事件编程?
-
文档打开/保存时自动执行检查 -
参数变化时触发相关计算 -
用户选择对象时显示额外信息 -
导出文件时自动添加水印 -
替换"自动运行宏"功能(Inventor 2014 后废弃)
事件层次结构
事件对象 |
典型事件 |
说明 |
ApplicationEvents |
OnActivateDocument, OnOpenDocument, OnSaveDocument, OnCloseDocument, OnTranslateDocument |
应用级事件 |
DocumentEvents |
OnChange, OnDelete, OnUndo |
文档级事件 |
UserInputEvents |
OnActivateCommand, OnStopPreSelect |
用户交互事件 |
FileUIEvents |
OnPopulateFileMetadata, OnFileInsertNewDialog |
文件 UI 事件 |
DrawingViewEvents |
OnUpdate |
工程图视图事件 |
SelectEvents |
OnSelect, OnUnSelect |
选择事件 |
InteractionEvents |
OnSuspend, OnResume |
交互事件 |
三种订阅方式(VB.NET / C#)
Public Class EventAddInServerImplements Inventor.ApplicationAddInServerPrivate m_inventorApplication As Inventor.Application' 声明 WithEvents 变量Dim WithEvents m_AppEvents As ApplicationEventsPublic Sub Activate(addInSiteObject As ApplicationAddInSite, firstTime As Boolean) _Implements ApplicationAddInServer.Activatem_inventorApplication = addInSiteObject.Application' 获取 ApplicationEvents 对象m_AppEvents = m_inventorApplication.ApplicationEventsEnd Sub' 事件处理方法(用 Handles 关键字关联)Private Sub m_AppEvents_OnActivateDocument( _ByVal DocumentObject As Inventor._Document, _ByVal BeforeOrAfter As Inventor.EventTimingEnum, _ByVal Context As Inventor.NameValueMap, _ByRef HandlingCode As Inventor.HandlingCodeEnum) _Handles m_AppEvents.OnActivateDocument' 只在事件之后处理If BeforeOrAfter <> EventTimingEnum.kAfter Then Exit SubMessageBox.Show("文档已激活: " & DocumentObject.DisplayName)End SubEnd Class
Public Sub Activate(addInSiteObject As ApplicationAddInSite, firstTime As Boolean) _Implements ApplicationAddInServer.Activatem_inventorApplication = addInSiteObject.Applicationm_AppEvents = m_inventorApplication.ApplicationEvents' 用 AddHandler 订阅事件AddHandler m_AppEvents.OnActivateDocument, _AddressOf ApplicationEvents_OnActivateDocumentEnd SubPublic Sub Deactivate() Implements ApplicationAddInServer.Deactivate' 退订事件(重要!)RemoveHandler m_AppEvents.OnActivateDocument, _AddressOf ApplicationEvents_OnActivateDocumentm_AppEvents = Nothing' 强制垃圾回收System.GC.Collect()System.GC.WaitForPendingFinalizers()End SubPrivate Sub ApplicationEvents_OnActivateDocument( _ByVal DocumentObject As Inventor._Document, _ByVal BeforeOrAfter As Inventor.EventTimingEnum, _ByVal Context As Inventor.NameValueMap, _ByRef HandlingCode As Inventor.HandlingCodeEnum)If BeforeOrAfter <> EventTimingEnum.kAfter Then Exit SubMessageBox.Show("文档已激活: " & DocumentObject.DisplayName)End Sub
public class EventAddInServer : ApplicationAddInServer{private Inventor.Application m_inventorApplication;private Inventor.ApplicationEvents m_appEvents;public void Activate(ApplicationAddInSite addInSiteObject, bool firstTime){m_inventorApplication = addInSiteObject.Application;m_appEvents = m_inventorApplication.ApplicationEvents;// 订阅事件m_appEvents.OnActivateDocument +=new ApplicationEventsSink_OnActivateDocumentEventHandler(ApplicationEvents_OnActivateDocument);}public void Deactivate(){// 退订事件(必须!)m_appEvents.OnActivateDocument -=new ApplicationEventsSink_OnActivateDocumentEventHandler(ApplicationEvents_OnActivateDocument);m_appEvents = null;// 强制垃圾回收GC.Collect();GC.WaitForPendingFinalizers();}private void ApplicationEvents_OnActivateDocument(_Document DocumentObject,EventTimingEnum BeforeOrAfter,NameValueMap Context,out HandlingCodeEnum HandlingCode){// 必须设置 HandlingCodeHandlingCode = HandlingCodeEnum.kEventNotHandled;if (BeforeOrAfter != EventTimingEnum.kAfter)return;HandlingCode = HandlingCodeEnum.kEventHandled;MessageBox.Show("文档已激活: " + DocumentObject.DisplayName);}}
BeforeOrAfter 参数
-
kBefore:操作执行之前——你可以在这里取消操作 -
kAfter:操作执行之后——你在这里做后续处理
private void OnSaveDocument(_Document DocumentObject,EventTimingEnum BeforeOrAfter,NameValueMap Context,out HandlingCodeEnum HandlingCode){HandlingCode = HandlingCodeEnum.kEventNotHandled;if (BeforeOrAfter == EventTimingEnum.kBefore){// 保存前检查if (!ValidateDocument(DocumentObject)){// 取消保存操作HandlingCode = HandlingCodeEnum.kEventFailed;return;}}else if (BeforeOrAfter == EventTimingEnum.kAfter){// 保存后执行LogSaveEvent(DocumentObject);}HandlingCode = HandlingCodeEnum.kEventHandled;}
常用事件实战
// 监听用户执行的命令m_userInputEvents = m_inventorApplication.UserInputEvents;m_userInputEvents.OnActivateCommand +=new UserInputEventsSink_OnActivateCommandEventHandler(UserInputEvents_OnActivateCommand);private void UserInputEvents_OnActivateCommand(string CommandName,NameValueMap Context,out HandlingCodeEnum HandlingCode){HandlingCode = HandlingCodeEnum.kEventHandled;Debug.WriteLine("用户执行了命令: " + CommandName);}
// 用 DocumentEvents.OnChange 监听参数变化private void DocEvents_OnChange(object Context,out HandlingCodeEnum HandlingCode){HandlingCode = HandlingCodeEnum.kEventHandled;// 检查是否是参数变化// Context 包含变化类型信息Debug.WriteLine("文档已变更");}
// 用 ApplicationEvents.OnTranslateDocument 监听导出m_appEvents.OnTranslateDocument +=new ApplicationEventsSink_OnTranslateDocumentEventHandler(AppEvents_OnTranslateDocument);private void AppEvents_OnTranslateDocument(_Document DocumentObject,string FileName,NameValueMap Context,EventTimingEnum BeforeOrAfter,out HandlingCodeEnum HandlingCode){HandlingCode = HandlingCodeEnum.kEventHandled;if (BeforeOrAfter == EventTimingEnum.kAfter){Debug.WriteLine("文件已导出: " + FileName);}}
事务与撤销
Sub CombinedUndoActions()Dim doc As DocumentSet doc = ThisApplication.ActiveDocument' 开始一个事务Dim trans As TransactionSet trans = ThisApplication.TransactionManager.StartTransaction( _doc, "批量修改参数")' 执行多个操作doc.ComponentDefinition.Parameters.Item("Length").Expression = "100 mm"doc.ComponentDefinition.Parameters.Item("Width").Expression = "50 mm"doc.ComponentDefinition.Parameters.Item("Height").Expression = "25 mm"' 结束事务——用户按一次 Ctrl+Z 就能撤销所有修改trans.EndEnd Sub
事件编程的坑
本篇小结
要点 |
说明 |
事件类型 |
ApplicationEvents / DocumentEvents / UserInputEvents 等 |
三种订阅方式 |
WithEvents / AddHandler / += 委托 |
BeforeOrAfter |
kBefore 可取消操作,kAfter 做后续处理 |
HandlingCode |
C#必须设置,kEventHandled 或 kEventFailed |
事务 |
TransactionManager 将多操作合并为一个撤销 |
退订事件 |
Deactivate 中必须 RemoveHandler/-= |
OnCloseDocument |
被引用文档关闭时不触发 |


