AutoCAD開發選擇----ObjectARX還是.net API(轉載)
本文基于AutoCAD 2006新推出的.NET API為工具,介紹了在.NET平台下對AutoCAD進行二次開發的技術,并與目前常用的VBA、ObjectARX作了對比。同時讨論了如何彌補.NET API某些不足的功能。
目前AutoCAD的二次開發工具主要有:VisualLisp、VBA和ObjectARX等。其中,VisualLisp與VBA較為簡單,特别是 VBA,使用友善且開發速度較快,但其功能相比ObjectARX有所不足,尤其是對面向對象的功能支援不好。而ObjectARX基于VC平台,在C++的支援下,其功能非常強大,可以很好地運用各種面向對象技術,但其缺點是發開速度比較慢,同時對開發人員的能力要求較高。
.NET是微軟新推出的開發平台,具有衆多優點。基于.NET平台對AutoCAD進行二次開發,可充分利用.NET的各種優勢,在保證功能強大的前提下大大提高開發速度。
一、基于.NET的開發
(1).NET API簡介
在新推出的AutoCAD 2006中,Autodesk為其開發增加了.NET API。.NET API提供了一系列托管的外包類(Managed Wrapper Class),使開發人員可在.NET架構下,使用任何支援.NET的語言,如VB.NET、C# 和Managed C++等對AutoCAD進行二次開發。其優點是完全面向對象,在擁有與C++相比對的強大功能的同時,具有友善易用的特點,是較理想的AutoCAD二次開發工具。
(2).NET API與傳統ObjectARX的主要差別
.NET API與傳統ObjectARX的差別主要源于在.NET環境下開發應用程式與在VC環境下開發應用程式的差別。首先,在VC環境下,程式員需要自己管理 記憶體的申請和釋放,而.NET采用了垃圾回收機制,由.NET架構自行判斷記憶體回收的時機并實行回收,進而解決了令C++程式員頭痛的記憶體洩漏問題。也正 是由于這個特點,在.NET環境下不能象在C++環境下那樣利用析構函數釋放其他的資源,需要程式員在程式中顯式地釋放。在.NET API中,主要通過Dispose來函數進行資源的釋放。
其次,ObjectARX中的各種反應器(Reactor)在.NET API中由外包類映射為各種事件(Event),可通過定義這些事件的響應函數來響應AutoCAD的各種操作。同時對于錯誤資訊的處理也從函數傳回值改 變為通常異常來處理,使其更好地相容.NET。由于VB.NET、C#等語言都是完全面向對象的,沒有全局函數的概念,是以.NET API将ObjectARX下的全局函數封裝為.NET API下的某些對象或對象的屬性,如ObjectARX下與使用者互動的系列全局函數被封裝為CommandLinePrompt類。
(3)使用.NET API
下面以C#為例,在Microsoft Visual C# 2005 Express Edition Beta平台上,先建立一個Class Library項目,再将AutoCAD2005安裝目錄下的acdbmgb.dll與acmgb.dll作為引用添加進項目中。這兩個檔案包含了. NET API中所有的外包類。
然後在要使用.NET API的類中添加以下語句以引用.NET API的命名空間。需要添加的語句如下:
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.Runtime;
using Autodesk.AutoCAD.Geometry;
這樣就可以利用.NET API進行開發了。以下代碼可在AutoCAD注冊為一個指令“AddLine”,該指令可在目前工作空間中添加一條起點為(0,0,0),終點(200,200,0)的直線。代碼如下:
[CommandMethod ("AddLine")]
public static void AddLineCmd()
{
Database db = HostApplicationServices.WorkingDatabase;//獲得目前工作空間的資料庫
BlockTable bt = (BlockTable)db.BlockTableId.Open(OpenMode.ForRead); //獲得塊表
BlockTableRecord btr = (BlockTableRecord)bt[BlockTableRecord.ModelSpace].Open(OpenMode.ForWrite); //獲得模型空間的塊表記錄
Line line = new Line(new Point3d(0, 0, 0), new Point3d(200, 200, 0)); //建立一條直線
try {
btr.AppendEntity(line); //将直線添加到模型空間中
line.Close();//關閉該直線
}
finally {
btr.Close();//關閉塊表記錄
bt.Close();//關閉塊表
}
}
由此可見,上述語句與在VC下的開發非常類似,其過程都是先得到資料庫,然後依次打開塊表、塊表記錄,接着添加實體,最後關閉塊表、塊表記錄。值得注意的是finally語句,無論try塊中的語句是否發生異常,finally塊中的語句都會被執行,進而確定關閉塊表和塊表記錄的操作會被執行。
寫完代碼後進行編譯,編譯完成将得到一個dll檔案。在AutoCAD 2006中通過“netload”指令即可選擇該dll檔案進行加載,加載成功後即可以通過“AddLine”指令執行上述代碼。遺憾的是目前的.NET API版本還不支援解除安裝,若要解除安裝隻能關閉AutoCAD。
(4).NET API的初始化與清除
在ObjectARX中,“acrxEntryPoint”函數是ARX程式的載入點,程式的初始化和清除均可在該函數中進行。而在.NET API中則首先需要将初始化代碼封裝在一個類中,同時該類需要壓迫實作
IExtensionApplication接口。該接口包含Initialize與Terminate兩個函數。其中Initialize負責加載程式時的初始化操作,Terminate則負責進行解除安裝程式時的清除操作。代碼如下:
namespace ARXExample {
public class MyARX : IExtensionApplication {
……
public void Initialize() {
//初始化操作
}
public void Terminate() {
//清除操作
}
……
}
}
同時,為加快加載速度,可在MyARX.cs的檔案頭加入以下語句:
[assembly: ExtensionApplication (typeof (ARXExample.MyARX) ) ]
[assembly: CommandClass (typeof (ARXExample.MyARX) ) ]
這樣在加載程式時AutoCAD将直接通過MyARX中的Initialize語句進行初始化,同時注冊MyARX中的指令。否則,AutoCAD将搜尋 dll中所有的類以找到實作IExtensionApplication接口的類進行初始化,如找不到則不進行初始化。同樣,通過 CommandClass屬性,AutoCAD也會直接到MyARX類中搜尋要注冊的指令。當程式中包含的類數目較多時,通過 ExtensionApplication和CommandClass這兩個屬性可顯著地加快程式的加載速度。
(5).NET API與COM互動操作
在目前的.NET API中,其功能與傳統的ObjectARX相比有所不及,有相當的ObjectARX函數目前還沒有封裝到.NET API中,如GetPoint等。但可以通過COM方式使用ActiveX來彌補.NET API的不足。
增加了COM引用後,程式就可以使用許多VBA中的功能了。以AutoCAD ActiveX中的事件為例,以下代碼可以為目前工作空間中所有的圖元添加Modified事件:
Database db = HostApplicationServices.WorkingDatabase;
BlockTable bt = (BlockTable)db.BlockTableId.Open(OpenMode.ForRead);
BlockTableRecord btr = (BlockTableRecord)bt[BlockTableRecord.ModelSpace].Open(OpenMode.ForWrite);
try {
AcadObject obj;
//周遊塊表記錄
foreach (ObjectId objId in btr) {
//由ObjectId得到ActiveX中的AcadObject對象
obj = (AcadObject)((AcadDatabase)db.AcadDatabase).ObjectIdToObject(objId.OldId);
//為obj添加響應Modified事件
obj.Modified += new IAcadObjectEvents_ModifiedEventHandler(obj_Modified);
}
}
finally {
btr.Close();
bt.Close();
}
其中事件響應函數obj_Modified的表示如下所示:
public static void obj_Modified(AcadObject obj) {
CommandLinePrompts.Message("object modified!" + obj.ObjectID + "\n");
}
二、結論
本文以C#為例,對基于.NET API的AutoCAD二次開發作了較詳細的介紹。.NET API在具有ObjectARX強大功能的同時具有VBA使用友善易用的優點,同時具有C++的強大功能,是較為理想的開發工具。但目前.NET API在某些方面還有些不足,但随着其版本的更新、完善,定會成為衆多開發人員的首選工具。
說明:.NET API又是怎麼工作的呢?我們都知道ACAD的功能其實是通過ObjectARX來實作的,是以.NET API其實就通過VC++和C++/CLI(原來的VC++.NET)混合程式設計把ARX功能包裝一下以.NET類的形式展示出來。也就是說使用.NET API其實使用的是ARX,而.NET API能實作多少功能就取決于包裝的程度,也就是包裝了多少ARX的功能。了解ARX的朋友都知道,使用ARX庫,由于C++語言的特點,我們經常需要派生ARX類。但使用.NET就不必了,我們經常隻需對對應的event來個delegate就行了,相比而言簡潔得一塌糊塗(比如:Autodesk.AutoCAD.ApplicationServices.Application.BeginQuit等event)。根據前邊對自定義對象的描述,現在就清楚了,.NET API除了部分自定義對象功能外,基本能代替ARX。