1

我已经使用 .NET Reflector 从 AutoCAD 互操作 .dll 重新创建了 _DAcadApplicationEvents 接口,并且我的代码适用于 AutoCAD 2010。问题是我需要它与 AutoCAD 2006 一直兼容到 2012 年及以后. 我正在运行 .NET 4.0,因此我将 Embed Interop Type 设置为 true 以确保我的 Application 对象正确解析到运行时而不需要反射调用方法,但我似乎无法找到一种方法来让事件接口在没有的情况下工作GUID 中的硬编码(特定于程序集)。


这是我从原始 AutoDesk.AutoCAD.Interop.dll 创建的自定义界面:

    <ComImport(), Guid("1F893620-C96D-4361-BBAF-A61D4144B7F8"), TypeLibType(CShort(&H1010))>
    Public Interface _DAcadApplicationEventsClone
        <MethodImpl(MethodImplOptions.InternalCall, MethodCodeType:=MethodCodeType.Runtime), DispId(1)>
        Sub SysVarChanged(<[In](), MarshalAs(UnmanagedType.BStr)> ByVal SysvarName As String, <[In](),
                          MarshalAs(UnmanagedType.Struct)> ByVal newVal As Object)

        <MethodImpl(MethodImplOptions.InternalCall, MethodCodeType:=MethodCodeType.Runtime), DispId(8)>
        Sub BeginQuit(<[In](), Out()> ByRef Cancel As Boolean)
    End Interface

Application 对象以这种方式创建:

Public Application As Object

Application = Marshal.GetActiveObject("AutoCAD.Application")

接下来我使用 IConnectionPoint 连接到克隆的接口:

Dim acGUID As New Guid(GetInterfaceGUID())

Dim acConnectionPoint As ComTypes.IConnectionPoint = Nothing
TryCast(Application, ComTypes.IConnectionPointContainer).FindConnectionPoint(acGUID, acConnectionPoint)

Dim acSinkCookie As Integer
acConnectionPoint.Advise(Me, acSinkCookie)

如您所见,我正在运行一个名为“GetInterfaceGUID”的函数,以根据系统上安装的 AutoCAD 版本动态搜索正确的 GUID。但是,如果返回的 GUID 与接口上的硬编码 GUID 不匹配,则无论如何它都不会工作。我已经尝试过不同的反射方法来处理 System._ComObject,这是我已经接近的唯一方法。我觉得我非常接近成功,并且在这一点上将不胜感激。提前致谢。

-洛克

4

1 回答 1

0

如您所见,AutoCAD COM 互操作取决于版本甚至位数(32 位/64 位)。为什么不使用 AutoCAD .NET 应用程序事件来摆脱这些麻烦,如下所示?

using System;
using System.Text;
using System.Linq;
using System.Xml;
using System.Reflection;
using System.ComponentModel;
using System.Collections;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Media.Imaging;
using System.Windows.Forms;

using System.IO;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.Runtime;
using Autodesk.AutoCAD.EditorInput;

using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.Windows;

using AcadApplication = Autodesk.AutoCAD.ApplicationServices.Application;
using AcadDocument = Autodesk.AutoCAD.ApplicationServices.Document;
using AcadWindows = Autodesk.AutoCAD.Windows;

namespace AcadNetAddinByVS2010
{
    public class AppEvents1
    {
        bool mSuppressMsgOutput = false;

        void OptionalMessageOutput(EventArgs obj, string eventName)
        {
            if (!mSuppressMsgOutput)
            {
                string msg = string.Format("Info about the {0} event:{1}", eventName, Environment.NewLine);

                PropertyInfo[] piArr = obj.GetType().GetProperties();
                foreach (PropertyInfo pi in piArr)
                {
                    string attValue = pi.GetValue(obj, null).ToString();
                    msg += string.Format("\t{0}: {1}{2}", pi.Name, attValue, Environment.NewLine);
                }

                MessageBox.Show(msg, "Event: " + eventName, MessageBoxButtons.OK, MessageBoxIcon.Information);
                System.Diagnostics.Debug.Write(msg);
            }
        }

        public void Register()
        {
            AcadApplication.SystemVariableChanging += AppEvent_SystemVariableChanging_Handler;
            AcadApplication.SystemVariableChanged += AppEvent_SystemVariableChanged_Handler;
            AcadApplication.QuitWillStart += AppEvent_QuitWillStart_Handler;
            AcadApplication.QuitAborted += AppEvent_QuitAborted_Handler;
            AcadApplication.PreTranslateMessage += AppEvent_PreTranslateMessage_Handler;
            AcadApplication.LeaveModal += AppEvent_LeaveModal_Handler;
            AcadApplication.Idle += AppEvent_Idle_Handler;
            AcadApplication.EnterModal += AppEvent_EnterModal_Handler;
            AcadApplication.DisplayingOptionDialog += AppEvent_DisplayingOptionDialog_Handler;
            AcadApplication.DisplayingDraftingSettingsDialog += AppEvent_DisplayingDraftingSettingsDialog_Handler;
            AcadApplication.DisplayingCustomizeDialog += AppEvent_DisplayingCustomizeDialog_Handler;
            AcadApplication.BeginQuit += AppEvent_BeginQuit_Handler;

        }

        public void UnRegister()
        {
            AcadApplication.SystemVariableChanging -= AppEvent_SystemVariableChanging_Handler;
            AcadApplication.SystemVariableChanged -= AppEvent_SystemVariableChanged_Handler;
            AcadApplication.QuitWillStart -= AppEvent_QuitWillStart_Handler;
            AcadApplication.QuitAborted -= AppEvent_QuitAborted_Handler;
            AcadApplication.PreTranslateMessage -= AppEvent_PreTranslateMessage_Handler;
            AcadApplication.LeaveModal -= AppEvent_LeaveModal_Handler;
            AcadApplication.Idle -= AppEvent_Idle_Handler;
            AcadApplication.EnterModal -= AppEvent_EnterModal_Handler;
            AcadApplication.DisplayingOptionDialog -= AppEvent_DisplayingOptionDialog_Handler;
            AcadApplication.DisplayingDraftingSettingsDialog -= AppEvent_DisplayingDraftingSettingsDialog_Handler;
            AcadApplication.DisplayingCustomizeDialog -= AppEvent_DisplayingCustomizeDialog_Handler;
            AcadApplication.BeginQuit -= AppEvent_BeginQuit_Handler;

        }

        public void AppEvent_BeginQuit_Handler(object sender, EventArgs e)
        {
            OptionalMessageOutput(e, "BeginQuit");

        }

        public void AppEvent_DisplayingCustomizeDialog_Handler(object sender, TabbedDialogEventArgs e)
        {
            OptionalMessageOutput(e, "DisplayingCustomizeDialog");

        }

        public void AppEvent_DisplayingDraftingSettingsDialog_Handler(object sender, TabbedDialogEventArgs e)
        {
            OptionalMessageOutput(e, "DisplayingDraftingSettingsDialog");

        }

        public void AppEvent_DisplayingOptionDialog_Handler(object sender, TabbedDialogEventArgs e)
        {
            OptionalMessageOutput(e, "DisplayingOptionDialog");

        }

        public void AppEvent_EnterModal_Handler(object sender, EventArgs e)
        {
            OptionalMessageOutput(e, "EnterModal");

        }

        public void AppEvent_Idle_Handler(object sender, EventArgs e)
        {
            OptionalMessageOutput(e, "Idle");

        }

        public void AppEvent_LeaveModal_Handler(object sender, EventArgs e)
        {
            OptionalMessageOutput(e, "LeaveModal");

        }

        public void AppEvent_PreTranslateMessage_Handler(object sender, PreTranslateMessageEventArgs e)
        {
            OptionalMessageOutput(e, "PreTranslateMessage");

        }

        public void AppEvent_QuitAborted_Handler(object sender, EventArgs e)
        {
            OptionalMessageOutput(e, "QuitAborted");

        }

        public void AppEvent_QuitWillStart_Handler(object sender, EventArgs e)
        {
            OptionalMessageOutput(e, "QuitWillStart");

        }

        public void AppEvent_SystemVariableChanged_Handler(object sender, Autodesk.AutoCAD.ApplicationServices.SystemVariableChangedEventArgs e)
        {
            OptionalMessageOutput(e, "SystemVariableChanged");

        }

        public void AppEvent_SystemVariableChanging_Handler(object sender, Autodesk.AutoCAD.ApplicationServices.SystemVariableChangingEventArgs e)
        {
            OptionalMessageOutput(e, "SystemVariableChanging");

        }

    }
}

顺便说一下,选择的 IExtensionApplication 实现中的事件注册代码如下:

#region Namespaces

using System;
using System.Text;
using System.Linq;
using System.Xml;
using System.Reflection;
using System.ComponentModel;
using System.Collections;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Media.Imaging;
using System.Windows.Forms;
using System.Drawing;
using System.IO;

using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.Runtime;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.Windows;

using AcadApplication = Autodesk.AutoCAD.ApplicationServices.Application;
using AcadDocument = Autodesk.AutoCAD.ApplicationServices.Document;
using AcadWindows = Autodesk.AutoCAD.Windows;

#endregion

namespace AcadNetAddinByVS2010
{
    public class ExtApp : IExtensionApplication
    {
        #region IExtensionApplication Members

        public void Initialize()
        {
            //TODO: add code to run when the ExtApp initializes. Here are a few examples:
            //          Checking some host information like build #, a patch or a particular Arx/Dbx/Dll;
            //          Creating/Opening some files to use in the whole life of the assembly, e.g. logs;
            //          Adding some ribbon tabs, panels, and/or buttons, when necessary;
            //          Loading some dependents explicitly which are not taken care of automatically;
            //          Subscribing to some events which are important for the whole session;
            //          Etc.

            mAppEvents1.Register();
        }

        public void Terminate()
        {
            //TODO: add code to clean up things when the ExtApp terminates. For example:
            //          Closing the log files;
            //          Deleting the custom ribbon tabs/panels/buttons;
            //          Unloading those dependents;
            //          Un-subscribing to those events;
            //          Etc.

            mAppEvents1.UnRegister();
        }

        #endregion

        AppEvents1 mAppEvents1 = new AppEvents1();
    }
}
于 2012-06-10T08:13:23.383 回答