青华模具培训学校

 找回密码
 注册

QQ登录

只需一步,快速开始

青华模具培训学院
查看: 1470|回复: 0

NET平台的AutoCAD二次开发介绍

[复制链接]
发表于 2011-2-22 14:17 | 显示全部楼层 |阅读模式
本文基于AutoCAD 2006新推出的.NET API为工具,介绍了在.NET平台下对AutoCAD进行二次开发的技术,并与目前常用的VBA、ObjectARX作了对比。同时讨论了如何弥补.NET API某些不足的功能。
' d' X7 c; ]6 E; I. S1 f: a4 u% Q. L3 ?" ^( D

8 |  f% L) k* e0 v6 e2 `# p当前AutoCAD的二次开发工具主要有:VisualLisp、VBA和ObjectARX等。其中,VisualLisp与VBA较为简单,特别是VBA,使用方便且开发速度较快,但其功能相比ObjectARX有所不足,尤其是对面向对象的功能支持不好。而ObjectARX基于VC平台,在C 的支持下,其功能非常强大,可以很好地运用各种面向对象技术,但其缺点是发开速度比较慢,同时对开发人员的能力要求较高。
% L- P, D8 m, [" G. k8 ^' e3 j  o% f* A( G$ D- M1 O
.NET是微软新推出的开发平台,具有众多优点。基于.NET平台对AutoCAD进行二次开发,可充分利用.NET的各种优势,在保证功能强大的前提下大大提高开发速度。
" t0 L# N3 h8 E( B  s$ i0 w+ Z
6 R; e4 h  {2 Z; Y: N- N3 r! t# x一、基于.NET的开发
/ B+ I9 @, a  J2 G! f1 U5 ]
; _: _' D/ p$ i3 j4 `& f1..NET API简介+ N2 Q6 t0 S: x  e2 q8 v* `

8 D& a7 j) k% Z4 D! O( u2 n  I在新推出的AutoCAD 2006中,Autodesk为其开发增加了.NET API。.NET API提供了一系列托管的外包类(Managed Wrapper Class),使开发人员可在.NET框架下,使用任何支持.NET的语言,如VB.NET、C# 和Managed C 等对AutoCAD进行二次开发。其优点是完全面向对象,在拥有与C 相匹配的强大功能的同时,具有方便易用的特点,是较理想的AutoCAD二次开发工具。
5 g3 f" F( ~, a  x$ J, t/ j  z! d4 a) s  k: t
2..NET API与传统ObjectARX的主要区别
5 U; \: u( T: t9 f1 q  v( a
) {- g0 H) B& n6 q.NET API与传统ObjectARX的区别主要源于在.NET环境下开发应用程序与在VC环境下开发应用程序的区别。首先,在VC环境下,程序员需要自己管理内存的申请和释放,而.NET采用了垃圾回收机制,由.NET框架自行判断内存回收的时机并实行回收,从而解决了令C 程序员头痛的内存泄漏问题。也正是由于这个特点,在.NET环境下不能象在C 环境下那样利用析构函数释放其他的资源,需要程序员在程序中显式地释放。在.NET API中,主要通过Dispose来函数进行资源的释放。" b4 g2 Q; G7 N  X
$ G, s: q/ F7 B
其次,ObjectARX中的各种反应器(Reactor)在.NET API中由外包类映射为各种事件(Event),可通过定义这些事件的响应函数来响应AutoCAD的各种操作。同时对于错误信息的处理也从函数返回值改变为通常异常来处理,使其更好地兼容.NET。由于VB.NET、C#等语言都是完全面向对象的,没有全局函数的概念,所以.NET API将ObjectARX下的全局函数封装为.NET API下的某些对象或对象的属性,如ObjectARX下与用户交互的系列全局函数被封装为CommandLinePrompt类。3 u8 V4 m; t7 P; m. A: g: Y: y
- Y+ s4 z7 Z6 X0 x3 t' A( h. S
3.使用.NET API2 @8 X+ N4 _" Y% D

. p: i7 ~9 [$ c% U下面以C#为例,在Microsoft Visual C# 2005 Express Edition Beta平台上,先新建一个Class Library项目,再将AutoCAD2005安装目录下的acdbmgb.dll与acmgb.dll作为引用添加进项目中。这两个文件包含了.NET API中所有的外包类。( N7 T, `2 r$ U0 H+ W! B
! ^% n- G5 H* a
7 q6 ]9 E* W/ ]* C8 ?
然后在要使用.NET API的类中添加以下语句以引用.NET API的命名空间。需要添加的语句如下:
/ i* t$ t5 v4 |/ q. m2 G4 p" }8 L0 Z2 N+ ]' l( C* b
using Autodesk.AutoCAD.ApplicationServices;( ?1 y1 _  J. k
using Autodesk.AutoCAD.DatabaseServices;& g2 P  I8 p* D: ^
using Autodesk.AutoCAD.Runtime;9 }" B' @6 |" h$ x2 Y
using Autodesk.AutoCAD.Geometry;
2 s( u% z0 ?5 V1 {
9 F& S% h( H8 P* t
这样就可以利用.NET API进行开发了。以下代码可在AutoCAD注册为一个命令“AddLine”,该命令可在当前工作空间中添加一条起点为(0,0,0),终点(200,200,0)的直线。代码如下:5 |; N* J9 p$ A& c5 ~" M+ x1 H* Z
3 O2 _* i" [9 u/ X0 i2 l  d$ J
[CommandMethod ("AddLine")]
9 L# f$ t/ E. E- Xpublic static void AddLineCmd()# h8 e$ S; t7 `' p+ s
{
$ w) y* @1 ~2 ?0 f- }+ b1 fDatabase db = HostApplicationServices.WorkingDatabase;//获得当前工作空间的数据库
' ]+ i7 ~' K# M3 lBlockTable bt = (BlockTable)db.BlockTableId.Open(OpenMode.ForRead); //获得块表
, h5 L% ?5 `3 ]' d& ]BlockTableRecord btr = (BlockTableRecord)bt[BlockTableRecord.ModelSpace].Open(OpenMode.ForWrite); //获得模型空间的块表记录
+ X4 {! u" R! C# MLine line = new Line(new Point3d(0, 0, 0), new Point3d(200, 200, 0));//创建一条直线
/ f9 h, Z9 T" G6 f. [* I+ k  ktry {) I' J) d0 p4 T  V5 E
btr.AppendEntity(line);//将直线添加到模型空间中
4 h, j& }7 X1 U, P+ G2 E4 `  {line.Close();//关闭该直线
& D9 D, g' i0 m}5 ]/ W9 _' b! W4 B
finally {% C) S8 A. u) ~
btr.Close();//关闭块表记录  o: k# V6 _# }* q7 R3 ]& E
bt.Close();//关闭块表
2 ]1 h* E) L+ r. ~}
% g# {) Z( a4 m% J. S* f}

- n" B5 K1 N, s- L. B4 ?# s+ a9 U( F/ C3 F: Z) l0 ^  L
由此可见,上述语句与在VC下的开发非常类似,其过程都是先得到数据库,然后依次打开块表、块表记录,接着添加实体,最后关闭块表、块表记录。值得注意的是finally语句,无论try块中的语句是否发生异常,finally块中的语句都会被执行,从而确保关闭块表和块表记录的操作会被执行。4 u: M* }9 Y% b% \2 Y( ?8 D

0 M7 @* ?" _+ b5 U/ V+ v写完代码后进行编译,编译完成将得到一个dll文件。在AutoCAD 2006中通过“netload”命令即可选择该dll文件进行加载,加载成功后即可以通过“AddLine”命令执行上述代码。遗憾的是目前的.NET API版本还不支持卸载,若要卸载只能关闭AutoCAD。. a8 J$ }$ A9 M/ V
8 C. s3 b4 G9 T6 k" ]- u
4..NET API的初始化与清除
! a- p6 p) g: d* ^5 x" U4 j/ I9 o( m/ K7 Q# P( N! ~
在ObjectARX中,“acrxEntryPoint”函数是ARX程序的载入点,程序的初始化和清除均可在该函数中进行。而在.NET API中则首先需要将初始化代码封装在一个类中,同时该类需要压迫实现! z! @# _2 p+ G8 |$ C+ ?2 v/ |
IExtensionApplication接口。该接口包含Initialize与Terminate两个函数。其中Initialize负责加载程序时的初始化操作,Terminate则负责进行卸载程序时的清除操作。代码如下:
$ n- R. L' z( ?5 s0 V/ w

6 a! f% q4 `8 d. U" L- h5 n/ |: {! nnamespace ARXExample {! o9 ~7 E0 k: S0 m% i
public class MyARX : IExtensionApplication {0 m4 l: W2 `# a5 G$ t( W7 |- G* _7 F, G
……
! g4 K$ L; a0 d1 O/ z2 _public void Initialize() {! H4 ]+ l# r- b4 u' ?% x& O
//初始化操作
: l& W, E# V& F% O+ X( [}
8 j3 h3 r6 k& ^6 `0 M$ {public void Terminate() {. }5 C* j6 w7 M5 H) C; t6 e

/ `  D9 \7 B% K. }//清除操作
6 ?' z& ^+ L; |: I2 [5 }, a}
; w6 Q+ `  b3 @7 @; \5 s……
* ?4 q& l/ j  l4 x3 F) }* w% U$ o. p
}- w# p$ _3 E1 x. Z! ]+ x
同时,为加快加载速度,可在MyARX.cs的文件头加入以下语句:7 ?6 i* A6 J% Z
[assembly: ExtensionApplication (typeof (ARXExample.MyARX) ) ]* y! K) s# W3 \+ s$ l6 `
[assembly: CommandClass (typeof (ARXExample.MyARX) ) ]

1 D1 d2 n9 @" W: q! ^; {0 w7 Y  |
* U  _% U2 k: I, d* c0 V这样在加载程序时AutoCAD将直接通过MyARX中的Initialize语句进行初始化,同时注册MyARX中的命令。否则,AutoCAD将搜索dll中所有的类以找到实现IExtensionApplication接口的类进行初始化,如找不到则不进行初始化。同样,通过CommandClass属性,AutoCAD也会直接到MyARX类中搜索要注册的命令。当程序中包含的类数目较多时,通过ExtensionApplication和CommandClass这两个属性可显著地加快程序的加载速度。
2 G+ R8 ~- N% r8 }" O! s% {( y
0 B: q1 M  W% b. B  r2 A5..NET API与COM交互操作* T2 H; ?& ]0 o5 t9 U
7 `6 M& F% U6 ^1 \3 x' d
在目前的.NET API中,其功能与传统的ObjectARX相比有所不及,有相当的ObjectARX函数目前还没有封装到.NET API中,如GetPoint等。但可以通过COM方式使用ActiveX来弥补.NET API的不足。0 _: j) [. B8 r; Q& c5 z
增加了COM引用后,程序就可以使用许多VBA中的功能了。以AutoCAD ActiveX中的事件为例,以下代码可以为当前工作空间中所有的图元添加Modified事件:

' w4 m2 V* G$ r9 S
8 m' D$ C1 B3 ]# `7 [! v3 a4 \Database db = HostApplicationServices.WorkingDatabase;6 p1 o7 V+ Q" h2 i. W) A
BlockTable bt = (BlockTable)db.BlockTableId.Open(OpenMode.ForRead);4 ]& S% s* P" j. y' \
BlockTableRecord btr = (BlockTableRecord)bt[BlockTableRecord.ModelSpace].Open(OpenMode.ForWrite);
3 [5 \2 K3 `9 Ztry {
5 x$ ~. X6 A, y! S; ]AcadObject obj;" R" p; X2 T% E+ n$ J
//遍历块表记录
6 H1 [9 }- ~. p: L  ]+ E0 lforeach (ObjectId objId in btr) {/ t) ?- \) z2 M
//由ObjectId得到ActiveX中的AcadObject对象; ]* j0 y8 g5 t9 }
obj = (AcadObject)((AcadDatabase)db.AcadDatabase).ObjectIdToObject(objId.OldId);( H' U8 x$ K; p; z
//为obj添加响应Modified事件
9 n& t9 Q- C& Y+ K) ]: _obj.Modified = new IAcadObjectEvents_ModifiedEventHandler(obj_Modified);
4 m' I$ h0 N! l$ a$ P) z' O}  \/ D& ~( j3 S5 V2 N
}
6 v$ t4 [  j' `* U$ D% ifinally {
5 n8 R! ~2 @% r+ L9 L1 S' ~% dbtr.Close();
3 `+ {4 U  U- d& f8 q$ bbt.Close();
" p; T/ w! W3 r}2 I0 O& |& [9 A% V8 S* N5 I
其中事件响应函数obj_Modified的表示如下所示:5 ]6 N: n8 p5 E
public static void obj_Modified(AcadObject obj) {
7 i2 ?3 [* `3 e* w6 [CommandLinePrompts.Message("object modified!" obj.ObjectID "\n");, |0 [: T+ g2 Q7 A- S
}

6 F% n1 e! x! q" p: E0 J! V3 Q# N  C; V8 D/ M! t  s" h% ]. K
二、结论$ H; K0 H* n& }/ `+ ^
, j" D! O+ M! A& k: U$ N; [+ W. A
本文以C#为例,对基于.NET API的AutoCAD二次开发作了较详细的介绍。.NET API在具有ObjectARX强大功能的同时具有VBA使用方便易用的优点,同时具有C 的强大功能,是较为理想的开发工具。但目前.NET API在某些方面还有些不足,但随着其版本的更新、完善,定会成为众多开发人员的首选工具。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

QQ|关于我们|sitemap|小黑屋|Archiver|手机版|UG网-UG技术论坛-青华数控模具培训学校 ( 粤ICP备15108561号 )

GMT+8, 2025-4-17 17:13 , Processed in 0.144894 second(s), 24 queries .

Powered by Discuz! X3.5 Licensed

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表