青华模具培训学校

 找回密码
 注册

QQ登录

只需一步,快速开始

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

NET平台的AutoCAD二次开发介绍

[复制链接]
发表于 2011-2-22 14:17 | 显示全部楼层 |阅读模式
本文基于AutoCAD 2006新推出的.NET API为工具,介绍了在.NET平台下对AutoCAD进行二次开发的技术,并与目前常用的VBA、ObjectARX作了对比。同时讨论了如何弥补.NET API某些不足的功能。
3 o4 w$ \' ?; h# l; h4 n# Q( P: }  F  [' F& U+ q( m
+ F' m% A- x1 w  [: F1 \1 u
当前AutoCAD的二次开发工具主要有:VisualLisp、VBA和ObjectARX等。其中,VisualLisp与VBA较为简单,特别是VBA,使用方便且开发速度较快,但其功能相比ObjectARX有所不足,尤其是对面向对象的功能支持不好。而ObjectARX基于VC平台,在C 的支持下,其功能非常强大,可以很好地运用各种面向对象技术,但其缺点是发开速度比较慢,同时对开发人员的能力要求较高。
+ n5 L6 p# \/ ?; b/ Q4 u3 u$ Q' M3 E7 y- P, q$ X4 q
.NET是微软新推出的开发平台,具有众多优点。基于.NET平台对AutoCAD进行二次开发,可充分利用.NET的各种优势,在保证功能强大的前提下大大提高开发速度。
9 e% k# h; K& G+ |  u+ O, S/ W! X7 Z' L  r$ ]
一、基于.NET的开发
# _9 v3 ~6 s, i
$ ]5 F; y. g& N2 w1 C. U1..NET API简介5 W7 w9 F& g6 z; X7 [
# C. W: _' S" g; ^7 ?0 ?
在新推出的AutoCAD 2006中,Autodesk为其开发增加了.NET API。.NET API提供了一系列托管的外包类(Managed Wrapper Class),使开发人员可在.NET框架下,使用任何支持.NET的语言,如VB.NET、C# 和Managed C 等对AutoCAD进行二次开发。其优点是完全面向对象,在拥有与C 相匹配的强大功能的同时,具有方便易用的特点,是较理想的AutoCAD二次开发工具。% ^  P4 c( X/ `6 }  @7 n" S# Y

6 j  J( O8 T. a" R  B2..NET API与传统ObjectARX的主要区别- m9 j  t* d3 c6 j/ d& \- H

2 g: a6 `- u: }; X, \# d.NET API与传统ObjectARX的区别主要源于在.NET环境下开发应用程序与在VC环境下开发应用程序的区别。首先,在VC环境下,程序员需要自己管理内存的申请和释放,而.NET采用了垃圾回收机制,由.NET框架自行判断内存回收的时机并实行回收,从而解决了令C 程序员头痛的内存泄漏问题。也正是由于这个特点,在.NET环境下不能象在C 环境下那样利用析构函数释放其他的资源,需要程序员在程序中显式地释放。在.NET API中,主要通过Dispose来函数进行资源的释放。
. c! `0 v. ^9 a: h/ ?% S: \. k
* u& P% P5 M( Y4 q! G# @9 w6 h  ]其次,ObjectARX中的各种反应器(Reactor)在.NET API中由外包类映射为各种事件(Event),可通过定义这些事件的响应函数来响应AutoCAD的各种操作。同时对于错误信息的处理也从函数返回值改变为通常异常来处理,使其更好地兼容.NET。由于VB.NET、C#等语言都是完全面向对象的,没有全局函数的概念,所以.NET API将ObjectARX下的全局函数封装为.NET API下的某些对象或对象的属性,如ObjectARX下与用户交互的系列全局函数被封装为CommandLinePrompt类。+ }7 E' T2 _" Z+ e! C1 I# H

" |7 K* x/ |4 U9 k% u) x: B' \3.使用.NET API
( F9 i& D! V. F& `9 [8 \# f/ C: S
8 ]( A* \9 S) t& n下面以C#为例,在Microsoft Visual C# 2005 Express Edition Beta平台上,先新建一个Class Library项目,再将AutoCAD2005安装目录下的acdbmgb.dll与acmgb.dll作为引用添加进项目中。这两个文件包含了.NET API中所有的外包类。
+ ~7 b7 x# z5 o8 i" [4 G- o* U" a) Q4 N3 H( t! }4 N" L

: O% E6 N5 D, d! H, a1 r4 c然后在要使用.NET API的类中添加以下语句以引用.NET API的命名空间。需要添加的语句如下:, P' P  W5 b! g' g7 n/ `1 w0 z

( A! Q6 q  N4 s2 z; L+ z' n( v) r3 ~using Autodesk.AutoCAD.ApplicationServices;7 ~5 E5 I. ~( U/ s6 o# u/ H
using Autodesk.AutoCAD.DatabaseServices;# C$ ^  ]  U/ C1 I1 c( W
using Autodesk.AutoCAD.Runtime;
/ d8 r0 }$ o; v" H+ busing Autodesk.AutoCAD.Geometry;
1 u, z4 ]' A7 A6 R

; |3 _/ x1 k+ X& N! Y- L9 k! u这样就可以利用.NET API进行开发了。以下代码可在AutoCAD注册为一个命令“AddLine”,该命令可在当前工作空间中添加一条起点为(0,0,0),终点(200,200,0)的直线。代码如下:5 P$ x+ U" ~+ a6 y  O8 I" F# Q
+ }0 u2 u/ P% c6 v* y
[CommandMethod ("AddLine")]
3 V8 r) l5 D" U! xpublic static void AddLineCmd()5 O. L! k9 H2 h3 {5 v$ ?
{
$ o! V- _2 T$ y% L2 RDatabase db = HostApplicationServices.WorkingDatabase;//获得当前工作空间的数据库: J3 G, @; f* x5 F* {
BlockTable bt = (BlockTable)db.BlockTableId.Open(OpenMode.ForRead); //获得块表* W5 n/ o/ I+ z. Y
BlockTableRecord btr = (BlockTableRecord)bt[BlockTableRecord.ModelSpace].Open(OpenMode.ForWrite); //获得模型空间的块表记录
2 a! ^1 |6 m& f3 m9 F& aLine line = new Line(new Point3d(0, 0, 0), new Point3d(200, 200, 0));//创建一条直线
& L  p0 }" j2 N8 q* a7 r7 N- y0 itry {  W1 w0 E9 }3 P( @7 q7 f" ~
btr.AppendEntity(line);//将直线添加到模型空间中. ?  w4 C8 C4 B( l! }% Q+ L
line.Close();//关闭该直线
# ]: ^$ Z8 T  m, t- ]7 t}
) G0 Q5 j2 O* z8 T( Xfinally {
7 I7 e- D9 I! Z/ p3 b& B: k" E- S, _btr.Close();//关闭块表记录
' _+ u" A) ~  q- a6 v. z/ @bt.Close();//关闭块表4 y# h6 f6 x/ }( `5 W3 A
}! S7 k# w( v% C" h# _6 \* q" T& G7 Q
}

" r" ]( g& B% s
; v! y$ q5 _* L' b6 P  r: e9 Y- |# e由此可见,上述语句与在VC下的开发非常类似,其过程都是先得到数据库,然后依次打开块表、块表记录,接着添加实体,最后关闭块表、块表记录。值得注意的是finally语句,无论try块中的语句是否发生异常,finally块中的语句都会被执行,从而确保关闭块表和块表记录的操作会被执行。5 H/ H: W$ G% k- t: d
# \- G7 R  Y% q; L8 k9 J6 d+ w( Z2 s
写完代码后进行编译,编译完成将得到一个dll文件。在AutoCAD 2006中通过“netload”命令即可选择该dll文件进行加载,加载成功后即可以通过“AddLine”命令执行上述代码。遗憾的是目前的.NET API版本还不支持卸载,若要卸载只能关闭AutoCAD。
* M/ t$ S: h5 t; Z% F  o1 }
/ o/ J: u8 j; `1 w! e& M* U2 V4..NET API的初始化与清除. {& x$ k: {) u9 L4 H
+ C2 `, n6 a7 [1 \- v* K
在ObjectARX中,“acrxEntryPoint”函数是ARX程序的载入点,程序的初始化和清除均可在该函数中进行。而在.NET API中则首先需要将初始化代码封装在一个类中,同时该类需要压迫实现
1 R: X% E$ h& N$ _IExtensionApplication接口。该接口包含Initialize与Terminate两个函数。其中Initialize负责加载程序时的初始化操作,Terminate则负责进行卸载程序时的清除操作。代码如下:
5 |# D; Y( Z; I% }( B7 d1 N

6 `7 y2 ~! e8 N/ V6 b  m: w1 Tnamespace ARXExample {
5 o9 x* z8 l) f) D$ }: {( }public class MyARX : IExtensionApplication {
. B3 n8 z8 o# A' C# k3 v……
( J% m0 W; B, E2 x5 r8 T" [public void Initialize() {
/ T1 \" ]: ~% W0 o4 D" |//初始化操作
2 y( l3 E* f1 i  S6 R  ?- o}
4 s8 x4 t% P9 ]public void Terminate() {
) X7 a3 Q4 s# w( I" ]
' e9 o7 t' W* S  w- W2 T5 i//清除操作( E9 }9 J9 w& ?3 V! H
}) m6 |6 ~7 H) X6 S# l
……+ V% `0 k$ A/ {; X" ~) m

1 ?4 T* u( t5 N5 B}
. H/ ?1 p6 @" G同时,为加快加载速度,可在MyARX.cs的文件头加入以下语句:
2 |5 K, ^* j7 p8 n& O! D[assembly: ExtensionApplication (typeof (ARXExample.MyARX) ) ]
3 a/ p) o' K) A( [7 b8 P" ?[assembly: CommandClass (typeof (ARXExample.MyARX) ) ]

" h# S9 v) b  r- L/ x9 g" M& Y6 P. J
这样在加载程序时AutoCAD将直接通过MyARX中的Initialize语句进行初始化,同时注册MyARX中的命令。否则,AutoCAD将搜索dll中所有的类以找到实现IExtensionApplication接口的类进行初始化,如找不到则不进行初始化。同样,通过CommandClass属性,AutoCAD也会直接到MyARX类中搜索要注册的命令。当程序中包含的类数目较多时,通过ExtensionApplication和CommandClass这两个属性可显著地加快程序的加载速度。3 _. Y- J& F: [7 d' M  b
1 j$ |4 P+ e) S) D; g" y
5..NET API与COM交互操作
7 L4 o6 }0 y6 h3 i5 e
  h5 M5 u6 @! [! ?2 T6 Z在目前的.NET API中,其功能与传统的ObjectARX相比有所不及,有相当的ObjectARX函数目前还没有封装到.NET API中,如GetPoint等。但可以通过COM方式使用ActiveX来弥补.NET API的不足。
. ^  y& X5 G( `: v3 F- c3 W增加了COM引用后,程序就可以使用许多VBA中的功能了。以AutoCAD ActiveX中的事件为例,以下代码可以为当前工作空间中所有的图元添加Modified事件:

  L* h9 j% S% u" e) Q$ |$ @
/ M8 @2 o$ L( E; O" ~% K  wDatabase db = HostApplicationServices.WorkingDatabase;
  w9 o/ I+ ?! n5 t# FBlockTable bt = (BlockTable)db.BlockTableId.Open(OpenMode.ForRead);
  w3 _: X; W; FBlockTableRecord btr = (BlockTableRecord)bt[BlockTableRecord.ModelSpace].Open(OpenMode.ForWrite);8 H( H* m3 h2 ?
try {
1 r6 ?; d! H: r/ L# g, Z7 f  vAcadObject obj;0 C, q4 u- Z" Y; a( N# z
//遍历块表记录
: V" W6 r- O8 R( Q/ }foreach (ObjectId objId in btr) {
! s( }/ {5 J. M& o, i/ ^0 y0 @//由ObjectId得到ActiveX中的AcadObject对象
+ K1 n/ O1 B! ?5 g6 e: |obj = (AcadObject)((AcadDatabase)db.AcadDatabase).ObjectIdToObject(objId.OldId);
! T1 S" H$ L7 J. V0 h9 [6 ^, s5 G. }//为obj添加响应Modified事件
3 }  }9 P9 g& x7 o4 k  zobj.Modified = new IAcadObjectEvents_ModifiedEventHandler(obj_Modified);$ z  A" l" s" s1 c
}" v6 v1 w; k2 T- F1 T+ Q9 {
}" |* ^# a) g' i0 t, k  E/ t
finally {
; Y1 E3 L1 I% \7 nbtr.Close();
. v3 D' y+ r5 B9 Q! c# wbt.Close();
5 g5 }+ d+ \- }  g! m& L}: V( E8 T: a9 z4 ?* F
其中事件响应函数obj_Modified的表示如下所示:
& D- ^. y/ z! N( D0 Ppublic static void obj_Modified(AcadObject obj) {
0 s# {* e$ k6 g8 \5 ZCommandLinePrompts.Message("object modified!" obj.ObjectID "\n");* a& u) Y  Y! w( E8 D
}

- p2 Z  S; \3 ^' A. D# Z1 i* B0 e2 z2 Q+ u2 |
二、结论
% w" K' m+ C+ `9 W
( y) N! s; G! N7 p% Y本文以C#为例,对基于.NET API的AutoCAD二次开发作了较详细的介绍。.NET API在具有ObjectARX强大功能的同时具有VBA使用方便易用的优点,同时具有C 的强大功能,是较为理想的开发工具。但目前.NET API在某些方面还有些不足,但随着其版本的更新、完善,定会成为众多开发人员的首选工具。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

GMT+8, 2025-1-22 21:44 , Processed in 0.050675 second(s), 24 queries .

Powered by Discuz! X3.5 Licensed

© 2001-2024 Discuz! Team.

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