明輝手游網(wǎng)中心:是一個免費(fèi)提供流行視頻軟件教程、在線學(xué)習(xí)分享的學(xué)習(xí)平臺!

使用C#進(jìn)行AutoCAD的二次開發(fā)(二)

[摘要]大家好,今天我繼續(xù)給各位介紹利用C#進(jìn)行AutoCAD的二次開發(fā)。在這一講中,主要介紹上一講例子中存在的問題。 在上一次的例子中我是通過引用AutoCAD 2004 Type Library來進(jìn)行C#與AutoCAD之間的通信,但這種方法存在兩個致命的缺點(diǎn)。第一個缺點(diǎn)是每次調(diào)試程序...

       大家好,今天我繼續(xù)給各位介紹利用C#進(jìn)行AutoCAD的二次開發(fā)。在這一講中,主要介紹上一講例子中存在的問題。

         在上一次的例子中我是通過引用AutoCAD 2004 Type Library來進(jìn)行C#與AutoCAD之間的通信,但這種方法存在兩個致命的缺點(diǎn)。第一個缺點(diǎn)是每次調(diào)試程序的時候C#都要重新啟動AutoCAD,如果調(diào)試的次數(shù)非常多(比如跟蹤錯誤然后調(diào)試),那么編程的效率就很低,因?yàn)閱右淮蜟AD還是需要較長的時間。相對于第一個缺點(diǎn),第二個缺點(diǎn)則更要命。由于.NET本身的問題,Interop.AutoCAD.dll文件(就是通過它才實(shí)現(xiàn)了C#與AutoCAD之間的通信)存在著一些bug,因此雖然有時你的代碼是完全正確的,但C#編譯器還是拋出莫名其妙的錯誤。那不是完蛋了嗎?我曾經(jīng)有一階段就因?yàn)檫@兩個要命的東東差一點(diǎn)放棄了C#而想改學(xué)ObjectArx了,呵呵,不過還是運(yùn)氣好,我偶爾一次在網(wǎng)上看了一篇外國人寫的文章,他專門介紹了這兩個問題的解決辦法。下面就來解決這兩個問題。

         首先來看第二個難題,按以下步驟來進(jìn)行:

1.        隨便用Visual Studio .NET建立一個C#應(yīng)用程序,然后按照上一篇文章中的設(shè)置加入AutoCAD 2004 Type Library,然后不加入任何代碼,編譯你的程序。

2.        在Visual Studio .NET命令行工具下用ildasm.exe(這個工具可以在Visual Studio .NET安裝光盤中找到)把Interop.AutoCAD.dll文件(這個文件在步驟1中生成的項(xiàng)目的Bin\Release文件夾中)編譯成中間語言Interop. AutoCAD.il。注意:在步驟1中建立的項(xiàng)目的編譯設(shè)置為Release模式。

    ildasm.exe /source Interop.AutoCAD.dll /output=Interop. AutoCAD.il

    又要注意了:把ildasm.exe,Interop.AutoCAD.dll放在同一目錄下。

3.在記事本中打開Interop. AutoCAD.il文件,然后查找結(jié)尾是“SinkHelper”而開頭為 ".class private auto ansi sealed _DAcad“的語句,把語句中的private 改為public,然后保存Interop. AutoCAD.il文件。

4.使用ilasm.exe把Interop. AutoCAD.il文件編譯為Interop.AutoCAD.dll文件,同樣是在Visual Studio .NET命令行工具下進(jìn)行。

    ilasm.exe  /resource=Interop.AutoCAD.res /dll Interop.AutoCAD.il /output=Interop. AutoCAD.dll

 Interop.AutoCAD.res文件是在步驟1中生成的。

5.顯然你不愿意每次編寫應(yīng)用程序時都通過上一篇文章中介紹的方法來加入Interop. AutoCAD.dll,那太麻煩了。你可以用下面的方法來讓程序自動加入該文件:找到C:\Program Files\Microsoft.NET\ Primary Interop Assemblies 文件夾,然后把上面生成的

Interop.AutoCAD.dll文件拷貝進(jìn)去。     

       好了,第二個問題解決了,接下來看第一個。

       在VBA中,編程者可以使用GetObject函數(shù)來獲得當(dāng)前活動的AutoCAD對象,但在C#中卻沒有,為了這個函數(shù)我?guī)缀醢袽SDN給翻遍了,然后去各種C#論壇問各位高手,結(jié)果都沒得到解決,呵呵,可能國內(nèi)使用C#的人比較少吧。還是在老外的論壇上看到了一篇就是講這個問題的文章才把這個難題給解決了。使用下面的語句就可以獲得當(dāng)前活動的AutoCAD對象了:

   (AcadApplication)Marshal.GetActiveObject("AutoCAD.Application.16")

     (對于CAD2000和CAD2002,則把16改為15)

當(dāng)然以上語句必須在AutoCAD打開的情況下才能使用,否則會發(fā)生錯誤,對于AutoCAD沒打開的情況,可以使用上一篇文章的方法來處理。完整的連接AutoCAD與C#的源程序如下所示:

using System;

using AutoCAD;

using System.Runtime.InteropServices;

namespace AcadExample

{

   public class AutoCADConnector : IDisposable

   {

      private AcadApplication _application;

      private bool _initialized;

      private bool _disposed;

      public AutoCADConnector()

      {

         try

         {

            // Upon creation, attempt to retrieve running instance

            _application = (AcadApplication)Marshal.GetActiveObject("AutoCAD.Application.16");

         }

         catch

         {

            try

            {

               // Create an instance and set flag to indicate this

               _application =  new AcadApplicationClass();

               _initialized = true;

            }

            catch

            {

               throw;

            }

         }

      }

      // If the user doesn't call Dispose, the

      // garbage collector will upon destruction

      ~AutoCADConnector()

      {

         Dispose(false);

      }

 

      public AcadApplication Application

      {

         get

         {

            // Return our internal instance of AutoCAD

            return _application;

         }

      }

             

      // This is the user-callable version of Dispose.

      // It calls our internal version and removes the

      // object from the garbage collector's queue.

      public void Dispose()

      {

         Dispose(true);

         GC.SuppressFinalize(this);

      }

 

      // This version of Dispose gets called by our

      // destructor.

      protected virtual void Dispose(bool disposing)

      {

         // If we created our AutoCAD instance, call its

         // Quit method to avoid leaking memory.

         if(!this._disposed && _initialized)

            _application.Quit();

           

         _disposed = true;        

      }

   }

}

利用Visual Studio.net 把上面的程序編譯成一個類庫,你就可以在以后的程序中使用它了,下面的這個例子說明了它的用法。(首先把AcadExample類庫包含在項(xiàng)目中)

using System;

using AcadExample;

using AutoCAD;

namespace ConsoleApplication6

{

   class Class1

   {

      [STAThread]

      static void Main(string[] args)

      {

         using (AutoCADConnector connector = new AutoCADConnector())

         {

            Console.WriteLine(connector.Application.ActiveDocument.Name);

         }

         Console.ReadLine();

      }

   }

}

這個例子是在C#窗口中顯示AutoCAD中當(dāng)前文檔的標(biāo)題。