AutoCAD提供了三种主要的开发工具,分别是:使用C/C++的ObjectARX,VB/VBA的ActiveX开发,以及AutoLISP/VisualLISP开发工具。每一个开发者都有自己的爱好,但是抛开所有的偏爱,人们经常想知道哪一种最好,我到底应该选择哪种工具?给这些人的答案是:“它取决于你要完成什么工作。”每一种开发工具都有不同的东西,在某谢情况下都有不可比拟的优点。当决定究竟使用什么开发工具时,你可以问自己四个问题:哪种语言让我感觉最顺手(舒服)?我有多少时间?谁是我的目标用户,他们有多少使用AutoCAD的经验?我到底需要对AutoCAD控制到什么程度,需要多少可能的窗口类型来尽快完成工作?当我介绍不同开发工具所具有的不同功能时,你可能会明白为什么这四个问题是重要的。在谈及这几种开发工具时,我仅仅将它们看作在AutoCAD中使用的功能,而不将它们看作独立的应用程序。
ObjectARX:
在三种开发工具中,这种工具拥有对AutoCAD最深入的控制能力,能够提供最多类型的窗体。使用ARX可以向AutoCAD注册自己的命令,用户运行你的程序时无需了解关于AutoCAD更多的知识。这种便利的代价就是编制ARX程序比VBA和LISP程序需要花费更多的时间,因此用来编制简单的绘图工具有点浪费了。要掌握ARX的前提是你对C和C++非常熟悉,从个人观点来说,我最喜欢这种工具,但那是因为我做的99%的程序都是用C和C++语言,选择ARX意味着我不用学习一门新语言。对我来说,回答“哪种语言让我感觉最顺手?”就足够了。ARX能够访问很多的AutoCAD底层工具(这些东西可能VBA和LISP并不能访问),这是大多数开发者选择ARX的主要原因,他们需要作一些用其他两种开发工具不能完成的工作。此外,这也是唯一一种能够确保你的代码安全(不被别人阅读或非法复制)的开发工具。如果你需要开发自定义实体,使用空间过滤,扩展一个使用其他开发工具的应用程序的功能,正在开发用于销售的第三方工具,或者用到一大堆用VBA和LISP不能访问的东西(或者费很大力气去实现的东西),那么ObjectARX是你的最佳选择。
VBA:
如果你是第一次开发AutoCAD应用程序,那么这就是最适合你的工具!这种工具对初学者来说非常友好,Visual Basic的代码阅读起来非常容易,很多初学者仅读了函数的名称就能理解一个问题。无论如何创建或者执行LISP命令来扩充你的访问手段,这种开发工具没有ARX和LISP那么多对AutoCAD访问的方式(译者注:这也有情可原,毕竟VBA和另外两种开发工具比起来年轻得多!)如果你对VBA非常精通,可以通过再对AutoCAD命令行进行仔细研究和分类(这句话可能不太通顺,原文是:you can subclass the AutoCAD command line),这样你就能实现LISP所能完成的所有功能!对VBA来说,最大的遗憾就是不能向AutoCAD注册命令,必须先用各种加在应用程序的方法将其对应的dvb文件加载,然后通过“工具/宏/宏”菜单项执行,或者在菜单项和自定义的工具栏按钮中执行,如果你的用户的基础知识实在有限,这对你来说是个不小的问题(译者注:已有合适的解决方案)。我曾经研究过很多合同,许多制图者喜欢直接在命令行执行命令,这对VBA(开发工具)的销售不是个好消息(译者注:已经有合适的方法实现这种功能),如果用户组不会在这个问题上纠缠,那么VBA通常是很好的商品,特别是当他们看到你能使用它多么迅速地创建应用程序。和LISP结合起来,VBA首先是一个开发公司内部使用的程序的利器,或者在你已经包工并且需要在现场编写自定义的工具时使用它。在所有的开发工具中,这是一种开发速度最快的工具,特别是在开发需要图形界面(对话框)的程序时。使用这种工具,你同样能从AutoDesk获得最好的技术支持!
LISP:
当我谈到LISP的时候,一般是专指AutoLISP和VisualLISP,而不是在讨论ANSI的通用LISP语言。首先简单描述一下AutoLISP,AutoLISP兼备快速开发工具的特点和COBOL语言的灵活性,很多开发者选择LISP的主要原因是它符合他们对“什么语言让我感到很顺手?”问题的答案,对很多人来说,这是他们第一次开发AutoCAD所使用的语言,并且很快使用该语言进行开发。另一个使用这种开发工具的原因是,你所工作的环境可能已经具有很多LISP程序(的确,AutoLISP的使用历史最为悠久)。学习LISP比VBA难,却又比C和C++简单。直到AutoCAD 2000,VBA还不能很好的在AutoCAD内部执行,并且留下很多开发者希望解决的问题。LISP是快速编写应用程序的最初的开发工具,大量的LISP程序库存在于世界各地在短时间内用VBA重写这些东西不值得,也不容易。如果是这种情况,那么LISP就是为你而打造的开发工具,也许是上帝可怜你,呵呵,开个玩笑。这些年来使用LISP的人大大减少了,如果你是AutoCAD二次开发的初学者,并且你的程序可能要和其他的Windows程序交换数据,你最好去看看VBA。总体来说,如果你正在创建和一个用ARX编写的程序交换数据的程序,对ARX程序员来说,为LISP程序员预留接口比为VBA预留接口要简单一些,但是一个好的程序员应该两者都能做,因此究竟为哪种语言预留接口实际上取决于写C++方面的东西的人。
下面就是一个简单的清单,用于决定到底哪种开发工具对你的项目最合适:
ObjectARX:
你必须感到用C和C++最为顺手(译者注:顺手是对一种语言无缘故的喜欢);
你需要大量的对AutoCAD的控制和多种类型的窗体;
你需要自定义对象;
你需要访问一些用VBA和LISP无法访问的东西;
你的程序需要更高的效率(VBA和LISP无法达到);
你的工作环境需要使用C或者C++开发的程序;
你需要使用一些AutoCAD外部的库函数,这些库函数仅能在C和C++中调用。
VBA:
你感觉用VBA编程最顺手;
你需要使用对话框;
你需要和Windows或者一种Office应用程序(例如Excel)交换数据;
你初学AutoCAD二次开发,或者初学编程;
你需要尽快完成一个程序的开发,而程序的效率不是那么重要;
你知道在开发过程中你需要从Autodesk获得大量的帮助。
LISP:
世界末日,没有其他的工具可选(译者注:就是你觉得VBA和ARX都不适合你);
你感觉用LISP编程很顺手;
你要开发的程序在AutoCAD 2000以前的版本上运行;
你的工作涉及到一些特殊的东西,这些东西用LISP可以直接实现,但是如果用VBA来实现要花费很大的力气;
你的工作环境需要它;
你的工作环境需要使用已经存在的LISP函数库;
你喜欢享受痛苦(译者注:可能有作者的一些个人感情色彩);
在你的程序中除了命令行和图形对象之外不需要任何对话框或者图形用户界面;
Parens让你快乐(译者注:不理解这句话的意思,估计Parens是个熟悉LISP开发的人的名字),哦,看这边,那个穿白大衣的人来找你了。
现在我将提供一些你们来这里的所有人都想要的东西:免费的代码(译者注:作者仍然是在开玩笑)!当然,我们直到这也是你读这一篇文章的原因,不是吗?因此,既然你费尽千辛万苦读完了上面的文字,我想我应该给你一些免费的代码,这样说不定下次你还会来这里。在每种开发工具的示例代码中,我都给出了一种编辑一个块参照中第一个可编辑的属性的方法,在代码中不会看到使用命令行的语句,因为我不喜欢使用那些东西。如果你使用“Command”(译者注:LISP中的command函数,VBA中的SendCommand方法,ARX中的acedCommand函数),你不是在编程,顶多算是在写脚本(译者注:脚本在这里泛指那些解释执行的语言,从某种意义上讲,使用“Command”确实是要求命令行解释并且执行你所提供的语句),这是两码事。
ObjectARX的代码:
void chngAtt()
{
ads_name entres;
ads_point ptres;
AcDbObjectId _Id, _attId;
AcDbObjectIterator *pIttr = NULL;
if(acedEntSel("Select a Block Reference", entres, ptres) != RTNORM )
{
//Selection failed
return;
}
acdbGetObjectId(_Id, entres);
AcDbObjectPointer pRef(_Id,AcDb::kForRead);
if(pRef.openStatus()!=Acad::eOk)
{
//Open failed
return;
}
pIttr = pRef->attributeIterator();
while(!pIttr->done())
{
_attId = pIttr->objectId();
AcDbObjectPointer pAtt(_attId,AcDb::kForWrite);
if(pAtt.openStatus()==Acad::eOk)
{
pAtt->setTextString("We changed this");
break;
}
pIttr->step();
}
delete pIttr;
}
VBA代码:
Option Explicit
Sub chngAtt()
Dim objEnt As AcadObject
Dim objRef As AcadBlockReference
Dim varAtts As Variant
Dim objAtt As AcadAttributeReference
Dim emptyPt As Variant
ThisDrawing.Utility.GetEntity objEnt, emptyPt, "Select Block: "
If objEnt.ObjectName = "AcDbBlockReference" Then
Set objRef = objEnt
If objRef.HasAttributes Then
varAtts = objRef.GetAttributes
Set objAtt = varAtts(0)
objAtt.TextString = "We changed this"
End If
End If
End Sub
LISP代码:
(defun C:chngAtt ()
(setq Mainent (entsel))
(setq entList (entget (car Mainent)))
(setq entAtt (entget (entnext (cdr (assoc -1 entList)))))
(setq entNewAttVal
(subst (cons 1 "We changed this") (assoc 1 entAtt) entAtt))
(entmod entNewAttVal)
(entupd (car Mainent))
(princ)
)
2/26/2005
|