AutoCAD 二次开发实用教程
第一部分:基础入门篇
第一章:为什么进行二次开发?
AutoCAD 功能强大,但在特定行业(如机械、建筑、电气)和特定企业中,常常需要根据自身需求进行定制化开发,以提高绘图效率、标准化设计、实现自动化流程等。

二次开发能帮你做什么?
- 自动化重复性工作:比如批量修改图层、属性,自动生成标准件(螺栓、螺母)等。
- 创建专业工具:开发符合公司制图规范的工具栏、菜单、动态块,一键完成复杂操作。
- 数据集成:将 AutoCAD 图纸与数据库(如 SQL Server, Oracle)或 ERP/MES 系统集成,实现 BOM(物料清单)自动统计、图纸管理等。
- 定制用户界面:创建符合个人或团队工作习惯的界面,隐藏不常用的命令,让工作更专注。
第二章:开发环境与工具选择
AutoCAD 提供了多种二次开发接口,各有优劣,选择哪个取决于你的项目需求、团队技能和目标平台。
| 开发工具 | 语言 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|---|
| .NET API | C#, VB.NET | (强烈推荐新手) 强大的类型安全和面向对象特性。 与 Windows 和 Office 集成方便。 调试简单,开发效率高。 64位原生支持。 |
需要 .NET Framework 运行环境。 | 大多数应用,尤其是需要复杂逻辑、UI 和数据交互的项目,是目前的主流。 |
| AutoLISP / Visual LISP | AutoLISP, DCL | (经典) 内置于 AutoCAD,无需额外环境。 轻量级,快速编写小工具。 对图形数据库的直接操作非常方便。 |
功能相对较弱,没有现代语言的面向对象特性,调试不便。 | 快速开发小型、简单的绘图工具,修改现有 LISP 程序。 |
| ObjectARX (C++) | C++ | (功能最强) 性能极高,功能最全面,可以深度定制 AutoCAD 核心。 可以创建自定义实体(ObjectARX Custom Entity)。 |
学习曲线陡峭,开发复杂,调试困难,仅支持 32 位(旧版)或特定 64 位环境。 | 需要极致性能或创建全新实体类型的专业级应用。 |
| VBA (Visual Basic for Applications) | VBA | 快速集成在 AutoCAD 中,适合快速构建宏和简单界面。 | 微软已逐步放弃 VBA,64位支持不佳,性能和安全性差。 | 旧系统维护或非常简单的自动化任务。不推荐新项目使用。 |
本教程将以 .NET API (C#) 为主线,因为它最具现代性、学习资源丰富且是未来的发展方向,也会穿插介绍 AutoLISP,因为它依然是处理纯图形操作的利器。
第三章:你的第一个 C# 程序 - "Hello, AutoCAD!"
目标:创建一个简单的程序,在 AutoCAD 中运行后,在命令行打印 "Hello, AutoCAD from C#!"。

步骤:
-
安装 Visual Studio:推荐使用 Visual Studio Community(免费版),确保安装了“.NET 桌面开发”工作负载。
-
创建项目:
- 打开 Visual Studio,创建一个新项目。
- 选择“类库(.NET Framework)”模板(注意:不是 .NET Core 或 .NET 5/6/7/8,AutoCAD 目前主要基于 .NET Framework)。
- 给项目命名,
HelloAcad。
-
添加引用:
(图片来源网络,侵删)- 在“解决方案资源管理器”中,右键点击“引用” -> “添加引用”。
- 点击“浏览”,找到 AutoCAD 的安装目录(
C:\Program Files\Autodesk\AutoCAD 2025),进入acdbmgd.dll和acmgd.dll,将它们添加进来。 - 技巧:将这两个 DLL 复制到你的项目
bin\Debug目录下,可以避免每次调试时都去查找路径。
-
编写代码:
- 将默认的
Class1.cs重命名为HelloCommands.cs。 - 编写以下代码:
using Autodesk.AutoCAD.Runtime; using Autodesk.AutoCAD.ApplicationServices; using System; // 程序集的版本号、名称等信息 [assembly: CommandClass(typeof(HelloAcad.HelloCommands))] namespace HelloAcad { public class HelloCommands { // 定义一个 AutoCAD 命令,命令名为 "HELLO" [CommandMethod("HELLO")] public void SayHello() { // 获取当前活动文档 Document doc = Application.DocumentManager.MdiActiveDocument; if (doc == null) { Application.ShowError("没有打开的图形文档。"); return; } // 获取当前数据库 Database db = doc.Database; // 获取应用程序和编辑器 Application.DocumentManager.MdiActiveDocument.Editor.WriteMessage("\nHello, AutoCAD from C#!"); } } } - 将默认的
-
生成解决方案:按
Ctrl+Shift+B或点击“生成” -> “生成解决方案”。 -
在 AutoCAD 中加载并运行:
- 打开任意一个 DWG 文件。
- 在命令行输入
NETLOAD,然后找到你生成的HelloAcad.dll文件(通常在项目目录的bin\Debug文件夹下)。 - 加载成功后,在命令行输入
HELLO,按回车,你应该会看到命令行输出了 "Hello, AutoCAD from C#!"。
恭喜!你已经成功迈出了第一步!
第二部分:核心概念与实战篇
第四章:AutoCAD 对象模型
理解 AutoCAD 的对象模型是二次开发的核心,你可以把 AutoCAD 看作一个由各种对象组成的“世界”。
- Application (应用程序):代表整个 AutoCAD 应用程序。
- Document (文档):代表一个打开的 DWG 文件。
- Database (数据库):这是核心!它包含了 DWG 文件的所有数据,包括实体、图层、线型、文字样式等。几乎所有操作都是通过操作 Database 对象来完成的。
- Editor (编辑器):提供与用户交互的接口,如获取用户输入(点、选择集)、在命令行打印信息等。
- Entity (实体):代表图形中的具体对象,如直线、圆、多段线、文字、块参照等,所有实体都继承自
Entity基类。 - Symbol Table (符号表):存储了数据库的“目录”,如:
LayerTable(图层表)LinetypeTable(线型表)TextStyleTable(文字样式表)BlockTable(块表)
- Symbol Table Record (符号表记录):符号表中的具体条目,如
LayerTableRecord(图层记录)。
核心思想:要操作一个对象(比如一条直线),你需要:
- 通过
Database对象找到它所在的“容器”(比如模型空间块表记录)。 - 打开这个“容器”(事务处理)。
- 在“容器”中获取这个对象(实体)。
- 对对象进行修改或读取。
- 保存并关闭“容器”(提交事务)。
第五章:实战 - 创建与修改实体
这是最常用的功能,下面我们通过几个例子来学习。
示例 1:在模型空间画一条直线
[CommandMethod("DRAWLINE")]
public void DrawLine()
{
Document doc = Application.DocumentManager.MdiActiveDocument;
Database db = doc.Database;
Editor ed = doc.Editor;
// 1. 获取用户输入的两个点
PromptPointResult p1Res = ed.GetPoint("\n请输入直线起点: ");
if (p1Res.Status != PromptStatus.OK) return;
PromptPointResult p2Res = ed.GetPoint(p1Res.Value, "\n请输入直线终点: ");
if (p2Res.Status != PromptStatus.OK) return;
// 2. 开始一个事务
using (Transaction trans = db.TransactionManager.StartTransaction())
{
// 3. 打开块表 (BlockTable)
BlockTable bt = (BlockTable)trans.GetObject(db.BlockTableId, OpenMode.ForRead);
// 4. 打开模型空间块表记录 (Model Space)
BlockTableRecord btr = (BlockTableRecord)trans.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForWrite);
// 5. 创建一条直线对象
Line line = new Line(p1Res.Value, p2Res.Value);
// 6. 将直线添加到模型空间,并添加到事务中
btr.AppendEntity(line);
trans.AddNewlyCreatedDBObject(line, true);
// 7. 提交事务,保存更改
trans.Commit();
}
}
代码解析:
using (Transaction trans = ...):事务是 AutoCAD 数据库操作的关键,它确保你的操作要么全部成功,要么全部失败,不会出现“半成品”。using语句确保事务在完成后会被正确关闭和释放。OpenMode.ForRead/OpenMode.ForWrite:打开对象时必须指定模式,只读模式用于查询信息,写入模式用于修改或创建对象,一个对象在同一事务中不能以写入模式多次打开。AppendEntity:将新创建的实体添加到图形数据库中。AddNewlyCreatedDBObject:将新对象与事务关联,以便在提交时能被正确处理。
示例 2:批量修改选中对象的图层
[CommandMethod("CHG_LAYER")]
public void ChangeLayer()
{
Document doc = Application.DocumentManager.MdiActiveDocument;
Database db = doc.Database;
Editor ed = doc.Editor;
// 1. 让用户选择对象
PromptSelectionResult selRes = ed.GetSelection();
if (selRes.Status != PromptStatus.OK) return;
SelectionSet selSet = selRes.Value;
// 2. 让用户输入新的图层名
PromptStringResult layerNameRes = ed.GetString("\n请输入新的图层名: ");
if (layerNameRes.Status != PromptStatus.OK) return;
string newLayerName = layerNameRes.StringResult;
// 3. 开始一个事务
using (Transaction trans = db.TransactionManager.StartTransaction())
{
// 4. 打开图层表,并检查新图层是否存在,不存在则创建
LayerTable lt = (LayerTable)trans.GetObject(db.LayerTableId, OpenMode.ForRead);
if (!lt.Has(newLayerName))
{
// 需要升级为写入模式来创建新图层
using (LayerTableRecord ltr = new LayerTableRecord())
{
ltr.Name = newLayerName;
// 升级图层表为写入模式
lt.UpgradeOpen();
lt.Add(ltr);
trans.AddNewlyCreatedDBObject(ltr, true);
// 降级回只读模式
lt.DowngradeOpen();
}
}
ObjectId layerId = lt[newLayerName];
// 5. 遍历所有选中的对象
foreach (ObjectId id in selSet.GetObjectIds())
{
Entity ent = (Entity)trans.GetObject(id, OpenMode.ForWrite);
ent.LayerId = layerId; // 修改对象的图层ID
}
// 6. 提交事务
trans.Commit();
}
ed.WriteMessage($"\n已成功将 {selSet.Count} 个对象移动到图层 '{newLayerName}'。");
}
第三部分:高级主题与最佳实践篇
第六章:用户界面定制
好的工具需要好的界面。
- 创建自定义命令:我们已经用
[CommandMethod]实现了。 - 创建工具栏和菜单:通过 C# 代码动态创建。
Ribbon:现代 AutoCAD 的功能区。PaletteSet:可停靠的工具窗口,非常适合放置复杂的控件。ToolStrip/MenuStrip:传统的工具栏和菜单栏。
示例:创建一个简单的工具窗口
// 在你的类中添加一个字段来保存工具窗口
private PaletteSet _myPaletteSet;
[CommandMethod("SHOW_PALETTE")]
public void ShowMyPalette()
{
if (_myPaletteSet == null || _myPaletteSet.IsDisposed)
{
_myPaletteSet = new PaletteSet("我的工具集", new Guid("your-guid-here"));
_myPaletteSet.Size = new System.Drawing.Size(300, 400);
// 添加一个用户控件
MyToolUserControl control = new MyToolUserControl();
_myPaletteSet.Add("工具", control);
}
_myPaletteSet.Visible = true;
}
你需要创建一个 Windows Forms 用户控件(User Control),将按钮、文本框等拖拽上去,然后在这个控件里处理逻辑。
第七章:处理用户交互
除了 GetPoint 和 GetSelection,还有更多交互方式:
- GetKeyword: 获取关键字,用于创建带选项的命令。
- GetInteger/GetDouble/GetString: 获取数值或字符串。
- PromptAngleOptions: 获取角度。
- PromptDistanceOptions: 获取距离。
- SelectionFilter: 强制用户选择特定类型的对象(比如只选圆)。
第八章:最佳实践与性能优化
-
事务管理是关键:
- 永远不要在循环外打开事务,尽量将对多个对象的操作放在一个事务中完成。
- 及时释放资源:使用
using语句来包裹Transaction,Database,Object等,确保它们被正确释放,避免内存泄漏。 - 读写模式:尽量只打开必要的模式,只读操作用
ForRead,修改操作用ForWrite。
-
性能优化:
- 减少数据库往返:一次打开一个对象,进行所有操作,然后关闭,避免反复打开同一个对象。
- 使用
IdMapping:当处理大量对象(如 Explode 炸开一个块)时,使用IdMapping可以极大地提高性能,因为它优化了对象ID的映射过程。 - 善用
WorldDraw和ObjectContext:对于需要频繁重绘的自定义实体,使用这些接口可以避免全屏重绘,提升显示性能。 - 避免在
OnExecute中做耗时操作:命令方法应尽可能简洁,耗时操作(如读写文件、网络请求)应放在后台线程中执行,避免界面卡死。
-
错误处理:
- 始终用
try...catch包裹你的代码,特别是文件操作和数据库操作。 - 向用户友好的提示错误信息,而不是直接抛出堆栈跟踪。
- 始终用
第四部分:资源与学习路径
第九章:官方文档与社区
- AutoCAD .NET API 文档:这是最重要的资源!链接
- Autodesk Developer Network (ADN):提供更深度的技术支持和资源。
- 通过代码学习:AutoCAD 自带了很多示例,安装目录下的
Sample文件夹是宝藏。 - 国内社区:
- CAD 联盟:非常活跃的中文社区,有大量教程和源码。
- CSDN / 博客园:搜索 "AutoCAD .NET 二次开发",可以找到很多个人博客和经验分享。
第十章:学习路线建议
-
入门阶段 (1-2周):
- 掌握 Visual Studio 基本操作。
- 理解对象模型,熟练掌握
Document,Database,Transaction。 - 能够编写简单的绘图和修改命令(如画线、改图层)。
- 学习使用
Editor获取用户输入。
-
进阶阶段 (1个月):
- 学习创建和管理块参照、属性块。
- 学习创建和修改标注、文字。
- 学习使用
SelectionFilter进行高级选择。 - 尝试创建自己的工具窗口或简单的功能区面板。
-
高级阶段 (长期):
- 深入研究自定义实体(如果需要)。
- 学习与外部数据源(数据库、Excel、Web API)集成。
- 研究性能优化技巧,处理大规模数据。
- 学习打包和部署你的插件。
也是最重要的建议:动手实践! 从一个你最想解决的小问题开始,尝试用代码去实现它,遇到问题,查阅文档、搜索社区,这个过程会让你成长得最快,祝你开发顺利!
