利用C#進行AutoCAD的二次開發)

來源:互聯網
上載者:User

利用C#進行AutoCAD的二次開發(一)

      
    眾所周知,對AutoCAD進行二次開發用到的主要工具有:ObjectArx,VBA,VLisp。但它們的優缺點是顯而易見的:ObjectArx功能強大,編程效率高,但它的缺點是編程者必須掌握VC++,而這門語言非常的難學;VBA和VLisp雖然簡單易上手,但它們對於開發大型的程式好象無能為力。那究竟有沒有一種語言能結合它們的優點而盡量避免它們的缺點呢? 回答是肯定的,那就是微軟新推出的21世程式設計語言C#。關於C#的詳細介紹,大家可以參考有關的文章。
  C#是通過AutoCAD ActiveX 這座橋樑來和AutoCAD之間進行通訊的。AutoCAD ActiveX 使使用者能夠從 AutoCAD 的內部或外部以編程方式來操作 AutoCAD。它是通過將 AutoCAD 對象顯示到“外部世界”來做到這一點的。一旦這些對象被顯示,許多不同的程式設計語言和環境就可以訪問它們。關於AutoCAD ActiveX 的情況,大家可以參考AutoCAD內建的協助。
  呵呵,說了這麼多無聊的,還是讓我們通過一個具體的例子來說明怎樣利用C#進行AutoCAD的二次開發吧。在介紹例子之前先講一下有關的配置:
(1)Visual Studio .net (2003和2002都可以,我用的是2002)

(2)AutoCAD2000以上版本(我用的是2004)
  這個例子非常簡單,就是通過C#建立的表單來啟動AutoCAD並畫一條直線。下面是編程的具體步驟:
(1)通過Visual Studio .net 建立一C#的windows應用程式。
(2)在“方案總管”中右擊“引用”標籤,在彈出的菜單中選擇“添加引用”,在“添加引用”對話方塊中選擇“com"選項卡下的下拉式清單方塊中的“AutoCAD 2004 Type Library"項(注意:不同版本的CAD的數字不同),單擊右邊的“選擇”按鈕,最後單擊下面的“確定”按鈕。
(3)在C#表單中加入兩個文字框和一個按鈕,分別用於輸入直線起點、終點的座標和在CAD中畫直線。下面主要解釋一下添加的代碼。
(a)在程式的開頭加入:using AutoCAD;//匯入AutoCAD引用空間
(b)在表單的變數聲明部分加入: private AcadApplication a;//聲明AutoCAD對象
(c)在表單的建構函式部分加入:a=new AcadApplicationClass();//建立AutoCAD對象
                          a.Visible=true;//使AutoCAD可見
(d)在按鈕的訊息處理函數中加入:
double[] startPoint=new double[3]; //聲明直線起點座標
double[] endPoint=new double[3];//聲明直線終點座標
string[] str=textBox1.Text.Split(',');

//取出直線起點座標輸入文字框的值,文字框的輸入模式為"x,y,z"
for(int i=0;i<3;i++)
startPoint[i]=Convert.ToDouble(str[i]);//將str數組轉為double型
    str=textBox2.Text.Split(',');//取出直線終點座標輸入文字框的值
for(int i=0;i<3;i++)
endPoint[i]=Convert.ToDouble(str[i]);
a.ActiveDocument.ModelSpace.AddLine(startPoint,endPoint);//在AutoCAD中畫直線
   a.Application.Update();//更新顯示
好了,簡單吧,你可以試著編譯一下。關於上面一些語句的用法,我會在下一講中作詳細介紹。

利用C#進行AutoCAD的二次開發(二)

利用C#進行AutoCAD的二次開發(二)

C#才鳥

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

         在上一次的例子中我是通過引用AutoCAD 2004 Type Library來進行C#與AutoCAD之間的通訊,但這種方法存在兩個致命的缺點。第一個缺點是每次偵錯工具的時候C#都要重新啟動AutoCAD,如果調試的次數非常多(比如跟蹤錯誤然後調試),那麼編程的效率就很低,因為啟動一次CAD還是需要較長的時間。相對於第一個缺點,第二個缺點則更要命。由於.NET本身的問題,Interop.AutoCAD.dll檔案(就是通過它才實現了C#與AutoCAD之間的通訊)存在著一些bug,因此雖然有時你的代碼是完全正確的,但C#編譯器還是拋出莫名其妙的錯誤。那不是完蛋了嗎?我曾經有一階段就因為這兩個要命的東東差一點放棄了C#而想改學ObjectArx了,呵呵,不過還是運氣好,我偶爾一次在網上看了一篇外國人寫的文章,他專門介紹了這兩個問題的解決辦法。下面就來解決這兩個問題。

         首先來看第二個難題,按以下步驟來進行:

1.        隨便用Visual Studio .NET建立一個C#應用程式,然後按照上一篇文章中的設定加入AutoCAD 2004 Type Library,然後不加入任何代碼,編譯你的程式。

2.        在Visual Studio .NET命令列工具下用ildasm.exe(這個工具可以在Visual Studio .NET安裝光碟片中找到)把Interop.AutoCAD.dll檔案(這個檔案在步驟1中產生的項目的Bin\Release檔案夾中)編譯成中繼語言Interop. AutoCAD.il。注意:在步驟1中建立的項目的編譯設定為Release模式。

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

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

3.在記事本中開啟Interop. AutoCAD.il檔案,然後尋找結尾是“SinkHelper”而開頭為 ".class private auto ansi sealed _DAcad“的語句,把語句中的private 改為public,然後儲存Interop. AutoCAD.il檔案。

4.使用ilasm.exe把Interop. AutoCAD.il檔案編譯為Interop.AutoCAD.dll檔案,同樣是在Visual Studio .NET命令列工具下進行。

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

 Interop.AutoCAD.res檔案是在步驟1中產生的。

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

Interop.AutoCAD.dll檔案拷貝進去。     

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

       在VBA中,編程者可以使用GetObject函數來獲得當前活動的AutoCAD對象,但在C#中卻沒有,為了這個函數我幾乎把MSDN給翻遍了,然後去各種C#論壇問各位高手,結果都沒得到解決,呵呵,可能國內使用C#的人比較少吧。還是在老外的論壇上看到了一篇就是講這個問題的文章才把這個難題給解決了。使用下面的語句就可以獲得當前活動的AutoCAD對象了:

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

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

當然以上語句必須在AutoCAD開啟的情況下才能使用,否則會發生錯誤,對於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類庫包含在項目中)

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中當前文檔的標題。

在C#中使用ObjectDBX技術從未開啟圖形中獲得圖塊的資訊

在C#中使用ObjectDBX技術從未開啟圖形中獲得圖塊的資訊

    從未開啟圖形中能獲得圖塊的資訊嗎?回答是肯定的。下面就來說明具體的實現方法。

    要求:

n         會用C#編程

n         讀過我寫的“利用C#進行AutoCAD的二次開發”

    開始:

n         在visual studio.net中建立一C#控制台程式

n         在引用選項卡中添加下列類庫:

l         interop.AutoCAD.dll

l         AcadExample.dll

l         ObjectDBX16(在“方案總管”中右擊“引用”標籤,在彈出的菜單中選擇“添加引用”,在“添加引用”對話方塊中選擇“com"選項卡下的下拉式清單方塊中的“AutoCAD/ObjectDBX Common 16.0 Type Library"項)

    然後鍵入以下代碼:

 1:  using System;

 2:  using AutoCAD;

 3:  using dbx = AXDBLib;

 4:  using AcadExample;

 5:

 6:  namespace ConsoleApplication1

 7:  {

 8:      /// <summary>

 9:      /// Summary description for Class1.

10:      /// </summary>

11:      class Class1

12:      {

13:          /// <summary>

14:          /// The main entry point for the application.

15:          /// </summary>

16:          [STAThread]

17:          static void Main(string[] args)

18:          {

19:              using (AutoCADConnector connector = new AutoCADConnector())

20:              {

21:                  string progid = "ObjectDBX.AxDbDocument.16"

                      //注意,這是AutoCAD2004的寫法,

                    //若是AutoCAD2002和AutoCAD2000i是”ObjectDBX.AxDbDocument.1“   

22:                  AcadApplication acadApp = connector.Application;

23:                  dbx.AxDbDocument dbxDoc;

24:                  dbxDoc = (dbx.AxDbDocument)acadApp.GetInterfaceObject(progid);

25:                  dbxDoc.Open(@"F:\Test.dwg");

26:                  foreach (dbx.AcadEntity entity in dbxDoc.ModelSpace)

27:                  {

28:                      if (entity.EntityName == "AcDbBlockReference")

                              //判斷實體是否是塊參照

29:                      {

30:                          dbx.AcadBlockReference blkRef;    

31:                          blkRef = (dbx.AcadBlockReference)entity; 

                               //將是塊參照的實體強制轉換為塊參照類型

32:                          object[] atts = (object[])blkRef.GetAttributes();

                              //擷取塊參照中的屬性(為物件類型)

33:                          for (int i = 0; i < atts.Length; i++) //遍曆塊參照屬性

34:                          {

35:                              dbx.AcadAttributeReference att;

36:                              att = (dbx.AcadAttributeReference)atts[i];

                            //將塊參照屬性(物件類型)強制轉換為塊參照屬性類型

37:                              Console.WriteLine("Tag: {0}\tValue: {1}\n",

38:                              att.TagString,

39:                              att.TextString);//顯示塊參照屬性的Tag和Text的值

40:                          }

41:                      }

42:                  }

43:                  Console.ReadLine();

44:              }

45:          }

46:      }

47:  }

    第一個要注意的是第三行,使用了一個別名。因為AutoCAD和ObjectDBX命名空間有許多相同的類名,因此,你必須使用全名,而不能使用簡寫的形式,但ObjectDBX寫起來比較麻煩,所以用別名dbx來使輸入方便一些。

    程式前面部分的代碼,你可以參考我寫的“利用C#進行AutoCAD的二次開發“這篇文章。讓我們來看第21行,程式定義了一個字串progid,作為第24句的函數GetInterfaceObject的參數,該函數是用來產生一個AxDbDocument對象。但要注意, GetInterfaceObject函數返回的類型是object,所以你必須用強制轉換把它變為AxDbDocument類。然後在第25行使用24行產生的AxDbDocument對象來”開啟“一個.dwg檔案(其實沒有開啟),需要注意的是這個檔案的路徑必須是正確的。這個檔案就是我們要獲得的塊資訊所在的檔案。

由於ObjectDBX 沒有選擇集,所以只有通過遍曆檔案的模型空間來獲得塊的資訊(26-28行)。

餘下語句的說明我已經寫在程式的注釋中了。

你可以發現ObjectDBX的工作原理在C#中與VBA是類似的,只不過要進行必要的類型轉換。

----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
藍色力量註:
         對於文章中提到的對於Interop. AutoCAD.dll需要反編譯、修改、再編譯的過程,在VS2005中已經不需要這樣操作,VS2005已經把private改成了public。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.