大数跨境

Inventor API 进阶4--事件编程:让 Inventor 响应你的操作

Inventor API 进阶4--事件编程:让 Inventor 响应你的操作 锐和软件资讯服务
2026-09-24
9
导读:Inventor API 进阶4--事件编程:让 Inventor 响应你的操作

本文是「Inventor API 进阶」系列第 4 篇。你想在用户保存文件时自动填充 iProperties?在参数变化时触发计算?事件编程是答案。

什么是事件编程?

传统的 API 调用是"你主动做"——你写代码去调用 Inventor 的方法。事件编程是"被动响应"——你注册一个事件处理程序,当 Inventor 中发生某个操作时,Inventor 自动调用你的代码。
常见的应用场景:
  • 文档打开/保存时自动执行检查
  • 参数变化时触发相关计算
  • 用户选择对象时显示额外信息
  • 导出文件时自动添加水印
  • 替换"自动运行宏"功能(Inventor 2014 后废弃)

事件层次结构

Inventor 的事件分布在多个对象上:

事件对象

典型事件

说明

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#)

方式一:VB.NET 的 WithEvents
最传统的方式,在类中声明 WithEvents 变量:
Public Class EventAddInServer    Implements Inventor.ApplicationAddInServer    Private m_inventorApplication As Inventor.Application    ' 声明 WithEvents 变量    Dim WithEvents m_AppEvents As ApplicationEvents    Public Sub Activate(addInSiteObject As ApplicationAddInSite, firstTime As Boolean) _        Implements ApplicationAddInServer.Activate        m_inventorApplication = addInSiteObject.Application        ' 获取 ApplicationEvents 对象        m_AppEvents = m_inventorApplication.ApplicationEvents    End 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 Sub        MessageBox.Show("文档已激活: " & DocumentObject.DisplayName)    End SubEnd Class
方式二:VB.NET 的 AddHandler(委托)
更灵活的方式,用 AddHandler/RemoveHandler:
Public Sub Activate(addInSiteObject As ApplicationAddInSite, firstTime As Boolean) _    Implements ApplicationAddInServer.Activate    m_inventorApplication = addInSiteObject.Application    m_AppEvents = m_inventorApplication.ApplicationEvents    ' 用 AddHandler 订阅事件    AddHandler m_AppEvents.OnActivateDocument, _        AddressOf ApplicationEvents_OnActivateDocumentEnd SubPublic Sub Deactivate() Implements ApplicationAddInServer.Deactivate    ' 退订事件(重要!)    RemoveHandler m_AppEvents.OnActivateDocument, _        AddressOf ApplicationEvents_OnActivateDocument    m_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 Sub    MessageBox.Show("文档已激活: " & DocumentObject.DisplayName)End Sub
方式三:C#的委托
C#用 +=/-= 语法订阅/退订:
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)    {        // 必须设置 HandlingCode        HandlingCode = 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);    }}

事务与撤销

Inventor 的 TransactionManager 允许你将多个操作组合成一个撤销步骤:
Sub CombinedUndoActions()    Dim doc As Document    Set doc = ThisApplication.ActiveDocument    ' 开始一个事务    Dim trans As Transaction    Set 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
嵌套事务
Inventor 支持嵌套事务。内层事务的提交/撤销不影响外层事务,但外层事务撤销时会撤销所有内层变更。

事件编程的坑

1. 必须在 Deactivate 中退订
    忘记退订事件是最常见的内存泄漏原因。在 AddIn 的 Deactivate 方法中务必 RemoveHandler/-=。
2. 必须设置 HandlingCode
    C#的事件处理方法有 out HandlingCodeEnum 参数,必须设置值。不设置会编译报错。
3. OnCloseDocument 对被引用文档不触发
    如果一个零件文档被装配体引用,关闭该零件时 OnCloseDocument不会触发(因为实际没有关闭)。这是 API 帮助文件中明确说明的限制。
4. 事件中的递归调用
    在 OnFileResolution 事件中调用 IsFileInActiveProject 会再次触发 OnFileResolution,导致无限循环。避免在事件处理中调用可能再次触发同类事件的 API。
5. InteractionEvents 的资源释放
    为不同文档创建 InteractionEvents 对象时,如果不释放不再需要的对象,可能导致崩溃。用完的对象要及时置 Nothing 并强制 GC。

本篇小结

要点

说明

事件类型

ApplicationEvents / DocumentEvents / UserInputEvents 等

三种订阅方式

WithEvents / AddHandler / += 委托

BeforeOrAfter

kBefore 可取消操作,kAfter 做后续处理

HandlingCode

C#必须设置,kEventHandled 或 kEventFailed

事务

TransactionManager 将多操作合并为一个撤销

退订事件

Deactivate 中必须 RemoveHandler/-=

OnCloseDocument

被引用文档关闭时不触发


下篇预告:《特征与几何操作实战》——11 篇素材精华,用代码创建拉伸、旋转、扫掠。
本文素材参考自 Autodesk Developer Blog「Mod The Machine」系列文章。

【声明】内容源于网络
0
0
锐和软件资讯服务
专注制造业设计服务20年,Autodesk产品金牌经销商,为您提供专业的技术解答,及时的信息资讯,全新的产品动态。各种好看、好玩、实用的设计咨询,惊爆您的眼球
内容 101
粉丝 0
锐和软件资讯服务 专注制造业设计服务20年,Autodesk产品金牌经销商,为您提供专业的技术解答,及时的信息资讯,全新的产品动态。各种好看、好玩、实用的设计咨询,惊爆您的眼球
总阅读841
粉丝0
内容101