简介:这份资源面向AutoCAD二次开发的学习者与工程技术人员,围绕VLISP、VBA、ARX三条技术路线整理成案头参考包,帮助读者从脚本自动化到C++插件开发逐步建立完整的扩展开发能力。压缩包共21个文件、约17.57MB,以chm帮助文档、pdf函数库查询辞典、doc使用指导为主,辅以cpp、def、arx、lib等ARX工程源码与编译产物,以及dsw、dsp等工程配置文件和pdb、ilk等调试符号文件,兼顾查阅与动手实践。内容覆盖LISP/VLISP函数速查、VBA属性参考、ARX函数示例与工程搭建,读者可据此查阅语法、对照示例代码、理解插件从项目设置到调试安装的流程,并借助案例巩固图形对象操作与界面定制思路。目前已有337人学习下载,适合初学者入门与有经验开发者案头备查。
1. 案头书不是教程,是开发时的第二块屏幕
做 AutoCAD 二次开发的人大概都有过这种体验:写到一半想确认vla-GetBoundingBox到底返回几个值、acedRegCmds注册的命令怎么注销、ARX 里AcDbBlockTableRecord的迭代器在哪个头文件里声明,然后切窗口、翻网页、翻旧项目、翻三年前的聊天记录,十分钟过去了,代码一行没动。这份《AutoCAD 开发案头书 vlisp vba arx》解决的就是这个场景——它把 LISP、VBA、ARX 三条技术路线的常用接口、调用约定、易错点集中成一份可随时翻查的案头资料,而不是从零讲起的入门教程。适合已经能写出能跑的命令、但经常卡在 API 细节和版本差异上的从业者,也适合刚接手旧图纸自动化任务、需要快速判断该用哪条技术栈的人。它不教你 AutoCAD 怎么画图,它教你在 AutoCAD 里怎么把重复劳动变成命令。
2. 三条技术栈怎么选:vlisp、VBA、ARX 的边界与代价
拿到这份资料第一件事不是从头读,而是先搞清楚自己手上的活该落在哪条线上。三条路线在 AutoCAD 开发里并存了很多年,各有各的舒适区和硬边界,选错了后面全是返工。
2.1 从执行模型看三者的本质差异
AutoLISP/Visual LISP 是解释执行,代码以文本形式加载进文档环境,改一行重新加载就能验证,调试成本极低。它的强项是直接操作图形数据库的轻量封装,选择集、图元属性、命令调用都是一两行的事。代价是复杂数据结构处理吃力,大循环性能一般,且逻辑一多就容易写成面条代码。
VBA 走的是 COM 自动化,通过ThisDrawing、ModelSpace这类对象模型访问图形,语法对写过 Office 宏的人几乎零门槛,窗体界面做起来也快。但 VBA 依赖宿主提供的 COM 接口,跨版本兼容性是个老问题,而且它和 LISP 之间的数据传递要靠vlax桥接,来回转换容易丢精度。
ARX 是编译型,直接链接 ObjectARX SDK,能拿到最底层的数据库事务、反应器、自定义实体能力。性能最好,能做的事最多,但编译环境、SDK 版本、运行时 DLL 必须和 AutoCAD 版本严格对齐,一个都对不上就是加载失败。三条线的取舍可以粗略对照:
| 维度 | vlisp | VBA | ARX |
|---|---|---|---|
| 上手成本 | 低 | 低 | 高 |
| 调试便利性 | 高,随改随测 | 中,需重进宏 | 低,需重编译加载 |
| 执行性能 | 中 | 中偏低 | 高 |
| 自定义实体 | 不支持 | 不支持 | 支持 |
| 版本迁移风险 | 低 | 中高 | 高 |
| 适合任务 | 批量改图元、命令封装 | 表单交互、报表导出 | 深层数据库操作、反应器 |
常见做法是:一次性批处理脚本用 vlisp 快速落地,需要给非开发人员用的带界面工具用 VBA 包一层,只有碰到性能瓶颈或必须操作底层对象时才上 ARX。这份案头书的价值在于三条线的接口都收在一起,切换时不用再去找另一份资料。
2.2 用 vlisp 写一个可复用的批量改属性命令
案头书里 LISP 部分最实用的不是语法,而是选择集与图元属性的组合套路。下面这段把当前图中所有指定图层上的文字高度统一改掉,是典型的批处理骨架:
(defun c:BatchTextHeight ( / ss lay hgt i ent ed) ;; 输入目标图层与统一字高 (setq lay (getstring "\n目标图层名: ")) (setq hgt (getreal "\n统一字高: ")) ;; 构造选择集:只选该图层上的 TEXT (setq ss (ssget "X" (list (cons 0 "TEXT") (cons 8 lay)))) (if ss (progn (setq i 0) (repeat (sslength ss) (setq ent (ssname ss i)) (setq ed (entget ent)) ;; 组码 40 是文字高度,替换后回写 (setq ed (subst (cons 40 hgt) (assoc 40 ed) ed)) (entmod ed) (setq i (1+ i)) ) (princ (strcat "\n已处理 " (itoa (sslength ss)) " 个文字对象")) ) (princ "\n未找到匹配对象") ) (princ) )逻辑上分三步:ssget "X"用过滤表在整图范围筛选,过滤表是点对列表,(0 . "TEXT")限定实体类型,(8 . lay)限定图层;ssname按索引取实体名,entget拿到组码表;subst把组码 40 的旧值替换成新值,entmod写回数据库。参数上要注意ssget "X"是跨图纸空间的全图选择,如果只想处理当前布局,得换成不带"X"的交互选择或加(410 . "Model")限定空间。entmod只对能被修改的图元生效,遇到锁定图层会静默失败,所以批量操作前最好先检查图层锁定状态,这一点案头书里专门标了。
2.3 VBA 侧的对象模型调用与窗体交互
VBA 部分的核心是对象模型的层级关系:Application往下是ActiveDocument,再往下是ModelSpace、PaperSpace、Blocks、Layers。案头书把常用集合和方法的签名整理成表,查起来比翻对象浏览器快。下面是一个把当前选择集导出成 CSV 的片段,展示了 VBA 里遍历选择集和写文件的典型写法:
Sub ExportSelectionToCsv() Dim sset As AcadSelectionSet Dim ent As AcadEntity Dim fso As Object, ts As Object Dim line As String ' 复用或新建选择集,避免重名报错 On Error Resume Next Set sset = ThisDrawing.SelectionSets.Item("EXPORT_SS") If sset Is Nothing Then Set sset = ThisDrawing.SelectionSets.Add("EXPORT_SS") Else sset.Clear End If On Error GoTo 0 sset.SelectOnScreen Set fso = CreateObject("Scripting.FileSystemObject") Set ts = fso.CreateTextFile(ThisDrawing.Path & "\export.csv", True) ts.WriteLine "Handle,ObjectName,Layer" For Each ent In sset ' Handle 是跨会话稳定的唯一标识 line = ent.Handle & "," & ent.ObjectName & "," & ent.Layer ts.WriteLine line Next ent ts.Close sset.Delete ' 用完删除,避免残留 End Sub这里有两个参数层面的细节值得记:SelectionSets.Add在集合里已存在同名项时会抛错,所以标准写法是先尝试取、取不到再建,案头书里把这段称为“选择集复用模板”;ent.Handle是十六进制字符串,跨图纸会话稳定,比ObjectID更适合做外部关联键。SelectOnScreen会阻塞等待用户框选,如果要做无人值守批处理,得换成按图层或类型构造过滤条件后调用Select方法。
2.4 ARX 工程的编译链与加载入口
ARX 部分门槛最高,案头书没有铺开讲 C++ 语法,而是把工程配置和加载机制讲透了。一个最小 ARX 模块需要包含入口函数和命令注册:
#include "aced.h" #include "rxregsvc.h" // ARX 模块加载时由 AutoCAD 调用 extern "C" AcRx::AppRetCode acrxEntryPoint(AcRx::AppMsgCode msg, void* pkt) { switch (msg) { case AcRx::kInitAppMsg: acrxDynamicLinker->unlockApplication(pkt); acrxRegisterAppMDIAware(pkt); // 注册命令 HELLO,本地化名同左 acedRegCmds->addCommand( L"MY_GROUP", L"HELLO", L"HELLO", ACRX_CMD_MODAL, helloCommand); break; case AcRx::kUnloadAppMsg: acedRegCmds->removeGroup(L"MY_GROUP"); break; } return AcRx::kRetOK; } void helloCommand() { acutPrintf(L"\nARX 模块已加载并响应命令"); }acrxEntryPoint是每个 ARX 模块的固定入口,kInitAppMsg时注册命令、解锁应用,kUnloadAppMsg时把命令组整个移除,否则重复加载会报命令已存在。acedRegCmds->addCommand的四个参数依次是命令组名、全局名、本地化名、命令标志,ACRX_CMD_MODAL表示模态命令,不能在另一个命令执行期间调用。编译时 SDK 的inc和lib路径必须指向与目标 AutoCAD 版本匹配的目录,运行时还要保证对应的 ARX 依赖 DLL 在搜索路径里,这两点对不上就是加载即失败,案头书用一整页列了版本对应关系。
3. 把案头书用成工作流:检索、验证、沉淀
资料本身是静态的,能不能变成生产力取决于怎么嵌进日常开发节奏。这一章讲三个具体动作:怎么快速定位接口、怎么在真实图纸上验证行为、怎么把验证结果沉淀回自己的笔记。
3.1 按“任务关键词”而不是按“语言”检索
新手常犯的错是先决定用哪种语言,再去资料里找对应章节。更高效的做法是先提炼任务关键词,比如“遍历块内属性”“批量改图层颜色”“响应图元修改事件”,然后带着关键词去三条线里横向比对。案头书的结构支持这种用法:同一个能力在 LISP、VBA、ARX 里往往都有对应实现,横向看一遍就知道哪条线代码量最少、哪条线性能最好。
举个具体例子,“读取块参照的属性值”这个任务,LISP 里是vla-GetAttributes配合vlax-safearray->list展开,VBA 里是ent.GetAttributes返回变体数组再For循环,ARX 里则是打开块表记录后遍历属性定义。三种写法案头书都有,横向比对后会发现:如果只是读几个属性做判断,LISP 最快落地;如果要批量写回并保证事务一致性,ARX 更稳。这种比对结论比背接口签名有用得多。
3.2 用最小图纸验证接口行为再上生产图
案头书里的示例代码是在通用环境下写的,直接丢进生产图纸跑是血泪教训的高发区。我一般会先建一张只含两三个图元的最小图纸,把要用的接口单独跑一遍,确认返回值结构、异常行为和副作用,再往真实图纸上套。
验证时重点看三件事:返回值是单个值还是列表、失败时是抛错还是返回 nil、操作是否改变了选择集或当前图层这类全局状态。比如entmod修改图元后,某些属性变更会触发图形重生成,在大图上表现为明显卡顿;ssget "X"在图纸空间和模型空间混排时的选择范围也和直觉不同。这些行为在文档里往往一句话带过,只有最小图纸上跑一遍才看得清。案头书在每个接口条目下留了“实测备注”的位置,就是给这种验证结论用的。
3.3 把踩过的坑写回自己的接口卡片
案头书是别人的经验,真正省时间的是自己维护的接口卡片。我的习惯是每验证一个接口,就在本地笔记里记三行:调用签名、实测返回结构、一个已知坑。积累几十条之后,检索效率会超过任何通用资料,因为卡片里全是你自己项目里真实出现过的边界条件。
卡片格式不用复杂,纯文本就行:
接口: vla-GetBoundingBox 签名: (vla-GetBoundingBox obj 'minPt 'maxPt) 返回: 通过引用参数回填,函数本身返回 T/nil 坑: 对空文字或零长度线返回 nil,需先判空再取值这种卡片配合案头书的系统性条目,一个负责广度一个负责深度,查接口时先翻卡片命中率高,卡片没有再去案头书里找完整说明。时间长了会发现,真正高频的接口就那么几十个,剩下的都是查一次就够的冷门 API。
4. 避坑与排查:三条技术栈各自的翻车现场
这一章按现象、原因、解决三段式记录几条实际踩过的坑,覆盖 LISP、VBA、ARX 三条线,都是案头书里标了但容易被跳过的地方。
4.1 LISP 命令重复加载后行为异常
现象:同一个 LISP 文件反复APPLOAD后,命令还能用但行为变得奇怪,比如选择集过滤条件失效、变量值残留。原因:defun定义的命令在重复加载时会被覆盖,但用setq定义的全局变量不会重置,上一次运行留下的状态污染了下一次。解决:在命令函数开头显式初始化所有全局变量,或者把变量全部收进defun的局部变量表(/后面的那串),案头书里把局部变量表称为“LISP 的后悔药”,养成习惯后这类问题基本消失。
4.2 VBA 选择集未释放导致后续操作报错
现象:连续运行几次导出宏后,提示选择集已存在或操作被拒绝。原因:SelectionSets.Add创建的选择集在宏结束后不会自动销毁,同名项累积后再次Add就抛错。解决:按 2.3 节的模板先取后建,并在宏末尾调用Delete。更稳妥的做法是把选择集操作包在错误处理里,确保异常路径也能走到清理逻辑。
4.3 ARX 模块加载失败但无明确提示
现象:APPLOAD加载 ARX 后命令不出现,命令行只给一句模糊的加载失败。原因:多数情况是 SDK 版本与 AutoCAD 版本不匹配,或者依赖的运行时 DLL 不在搜索路径。解决:先用arx命令的加载日志确认失败阶段,再核对 SDK 版本号与目标版本是否一致,最后用依赖查看工具确认 DLL 齐全。案头书建议在开发机上保留每个版本的 SDK 目录,切换项目时整体切换环境变量,不要混用。
4.4 跨语言数据传递丢失精度
现象:LISP 算出坐标传给 VBA 再传回来,小数位对不上。原因:LISP 的实数与 VBA 的Double在通过vlax桥接时经过变体转换,某些中间格式会截断。解决:跨语言传递坐标时统一用字符串保留足够位数,或者干脆把计算和写回放在同一条技术栈里完成,减少来回转换。案头书在桥接章节专门提醒过,能不走桥接就不走。
4.5 批量操作在锁定图层上静默失败
现象:批量改属性的脚本报告处理了 N 个对象,但图上部分对象没变。原因:锁定图层上的图元entmod会失败但不抛错,脚本继续往下跑,统计数字照常累加。解决:操作前用tblsearch查图层表确认锁定状态,跳过或提示用户解锁;统计时以实际修改成功的数量为准,不要直接用选择集长度。
5. 进阶用法:把案头书变成可检索的本地知识库
案头书用久了会发现一个问题:内容越全,翻找越慢。真正高效的用法不是每次从头翻,而是把它拆成可检索的本地知识库,配合自己的接口卡片形成两级检索。我的做法是把三条技术栈的条目按“能力域”重新组织,而不是按语言分章。
具体操作上,先建一个纯文本索引文件,每行一条记录,格式是“能力关键词 | 语言 | 条目位置 | 一句话结论”。比如“块属性读取 | lisp | 第X节 | 用 vla-GetAttributes 后 safearray->list 展开”。这个索引不需要工具,任何文本编辑器都能维护,检索时用编辑器的全局搜索,比翻目录快一个数量级。
# 能力索引示例 块属性读取 | lisp | 属性章节 | vla-GetAttributes + safearray->list 块属性读取 | vba | 属性章节 | ent.GetAttributes 返回变体数组 批量改属性 | lisp | 选择集章节 | ssget X + entmod,注意锁定图层 命令注册 | arx | 入口章节 | acedRegCmds->addCommand,卸载时 removeGroup索引维护的关键是“一句话结论”必须写自己的话,不能抄原文。抄来的结论下次看不懂,自己总结的结论带着当时的上下文,一眼就能回忆起来。另一个技巧是给每条索引加一个“验证状态”标记,比如“已实测”“待验证”“有版本差异”,这样检索时能直接过滤掉没把握的条目,避免把未验证的写法带进生产代码。
进阶一点的做法是把索引和最小验证脚本关联起来。每条“已实测”的索引后面跟一个脚本文件名,需要复核时直接跑脚本看行为,不用重新搭环境。这套东西搭起来大概花一个下午,但后面每次查接口都能省几分钟,几个月下来就是实打实的时间。
从那以后我每次接手新的 AutoCAD 开发任务,都强制先花半小时把这次要用的接口在最小图纸上过一遍,把结论写进索引再动生产代码。这个习惯救过我好几次,尤其是版本升级后接口行为悄悄变化的时候。希望帮到你。
本文还有配套的精品资源,点击获取