天天看點

C#調用AutoCAD二次開發

轉載自百度文庫https://wenku.baidu.com/view/51f742f8c8d376eeaeaa31c2.html

今天在c#中實作了對AutoCAD的調用,中間遇到了一些問題,現在記下來,希望對大家有點幫助。

參考文獻來源:http://www.knowsky.com/3391.html 根據文章裡講的:

第一步:建立一C#的windows應用程式,

第二步:添加AutoCAD 2008 Type Library的引用, 第三步:根據文章裡的内容寫程式。

這些都沒問題,但是編譯時,出現“使用了未添加的引用程式集”的錯誤,然後在安裝檔案中找到“AUTODESK.AUTOCAD.INTEROP.COMMON.DLL”檔案,再次添加引用,OK,程式正常運作。

例子程式實作了在c#中輸入點,在CAD中完成劃線的功能。

友善大家,将文獻引入如下:

衆所周知,對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的二次開發。在這一講中,主要介紹上一講例子中存在的問題。  

         在上一次的例子中我是通過引用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安裝CD光牒中找到)把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中目前文檔的标題。

這一講的主要内容是介紹AutoCAD對象模型,如果你對VBA開發AutoCAD了解的話,這部分内容應該是超簡單的。

對象是 AutoCAD ActiveX 接口的主要構造塊,每一個顯示的對象均精确代表一個 AutoCAD 元件。AutoCAD ActiveX 接口的主要對象有: • 直線、圓弧、文字和标注等圖形對象。 • 線型與标注樣式等樣式設定對象  • 圖層、編組和塊等組織結構對象  • 視圖與視口等圖形顯示對象。  

• 圖形、AutoCAD 應用程式本身也是對象

所有對象的根對象是AutoCAD 應用程式本身,它用AcadApplication類來表示。獲得目前運作的AcadApplication對象可以使用上一講中介紹的方法來得到。AcadApplication對象下有四個子對象構成,分别是:  

 AcadPreferences 對象,通過此對象可以通路和設定“選項”對話框中的相關選項  AcadDocuments對象,它表示AutoCAD 圖形  AcadMenuBar 對象,它表示AutoCAD主菜單欄 (注意不是AcadMenuBars,因為應用程式隻有一個主菜單欄)  AcadMenuGroups對象, 它表示AutoCAD 菜單和工具欄

上面介紹了AutoCAD ActiveX 接口對象模型的大緻組成,下面重點介紹AcadDocuments對象,因為大部分的程式設計都與它有關。首先大家看到它是複數的形式,是以它是目前打開的AutoCAD所有圖形的集合,這種對象稱為集合對象(呵呵,好像在講廢話)。集合對象有一些比較重要的方法和特性。其中最主要的是:Count特性用于擷取集合中的對象個數(從零開始);Item 方法用于擷取集合中的任何對象。關于它們的用法我會在下面的例子中介紹。而 AcadDocuments的單數形式AcadDocument表示目前打開的一個AutoCAD圖形。AcadDocument對象由以下幾個主要對象組成:

 AcadModelSpace 集合和 AcadPaperSpace集合,提供對圖形對象(直線、圓、等)的通路  AcadLayers、AcadLinetypes 和 AcadTextStyles,則提供對非圖形對象(圖層、線型、文本樣式等)的通路

 AcadPlot 對象提供對“列印”對話框中設定的通路,并為應用過程提供了列印圖形的各種方法

 AcadUtility 對象提供使用者輸入和轉換函數

圖形對象的建立使用Add方法,比如要建立一個圓,就是用AddCircle方法,而非圖形對象的建立使用Add方法。

下面通過一個簡單的例子來說明上面介紹的内容。這個例子是在AutoCAD中建立一個新的層,然後在該層中畫一個紅色的圓和一條綠色的直線。這是程式的源代碼:(請先把上一講中生成的interop.AutoCAD.dll 和 AutoCADExample.dll檔案包含在工程中) using System;

using AcadExample; using AutoCAD;  

namespace CircleLine { ///  

/// Class1 的摘要說明。 ///  class Class1 { ///  

/// 應用程式的主入口點。 ///  

[STAThread]

static void Main(string[] args) {

//

// TODO: 在此處添加代碼以啟動應用程式 //

using(AutoCADConnector connector=new AutoCADConnector()) //連接配接AutoCAD {

AcadDocument aDocument=connector.Application.ActiveDocument;  //取得目前AutoCAD活動圖形對象

double[] center=new Double[3]{20,20,0};//設定圓心 double radius=20;//設定圓的半徑

double[] startPoint=new Double[3]{0,0,0};//設定直線的起點 double[] endPoint=new Double[3]{40,40,0};//設定直線的終點 AcadLayer newLayer=aDocument.Layers.Add("CircleLine"); //建立一個名為CircleLine的新層

aDocument.ActiveLayer=newLayer;//把CircleLine層設定為目前層

AcadCircle circle=aDocument.ModelSpace.AddCircle(center,radius);//加入圓 AcadLine line=aDocument.ModelSpace.AddLine(startPoint,endPoint);//加入直線 circle.color=ACAD_COLOR.acRed;//把圓變為紅色 line.color=ACAD_COLOR.acGreen;//把直線變為綠色 connector.Application.Update();//更新顯示

for(int i=0;i Console.WriteLine("這是第{0}個對象:{1}",i+1,aDocument.ModelSpace.Item(i)); //周遊目前圖形   }

Console.ReadLine(); } } }

好了,今天就到這裡。

繼續閱讀