Go to file
sladro f11403cc2f refactor: 更新自由锻方轴绘制器的二进制资源
更新了 ShaftRawFreeForgeSquareShaftDrawer.cs 文件的二进制内容。
2026-02-04 18:29:19 +08:00
Cad refactor: 更新自由锻方轴绘制器的二进制资源 2026-02-04 18:29:19 +08:00
Common 增加方轴选项 2026-02-03 18:58:13 +08:00
Data Update plugin UI with new fields, layout fixes, and settings dialog 2025-12-11 16:23:18 +08:00
Domain 配置了全部参数 2025-12-17 10:04:08 +08:00
Properties 实现插件弹出,使用命令PARAM_PANEL 2025-12-11 14:03:25 +08:00
UI 设计架构,隔离图纸生成逻辑 2026-01-20 11:19:19 +08:00
.gitignore 实现插件弹出,使用命令PARAM_PANEL 2025-12-11 14:03:25 +08:00
CadParamPluging.csproj 增加方轴选项 2026-02-03 18:58:13 +08:00
CadParamPluging.sln 实现插件弹出,使用命令PARAM_PANEL 2025-12-11 14:03:25 +08:00
PackageContents.xml 实现插件弹出,使用命令PARAM_PANEL 2025-12-11 14:03:25 +08:00
Plan.md 实现插件弹出,使用命令PARAM_PANEL 2025-12-11 14:03:25 +08:00
PluginEntry.cs 就差参数生成图纸了 2025-12-16 10:21:37 +08:00
Readme.md 设计架构,隔离图纸生成逻辑 2026-01-20 11:19:19 +08:00
repro.cs 更新标注样式,删除无用元素 2025-12-23 17:34:17 +08:00

0. 目标 & 新流程说明

0.1 功能目标

基于 AutoCAD 2014 开发一个插件,实现:

  1. 在 AutoCAD 中新建图纸后,打开插件面板;
  2. 用户在插件面板中输入一组模板相关参数(如图纸类别、项目类型、图幅、比例等),
    插件根据这些参数自动匹配模板DWT/DWG中的某个图纸
  3. 用户再输入出图相关的其它参数(构件数量、尺寸、布置方式等,开发时再定);
  4. 插件结合选中的模板 + 业务参数,自动在 CAD 中生成图形;
  5. 生成后通过插件提供的“保存”功能,让用户选择保存位置和文件名。

0.2 使用体验要求(不走命令行)

  • 使用人员只通过 侧边面板 UI 操作,不需要输入命令;
  • 插件加载后自动显示面板;
  • 整个流程:填写参数 → 预览/确定模板 → 生成图纸 → 保存,全部在 UI 中完成;
  • 命令行入口可以保留一个隐藏命令用于调试,但不要求普通用户使用

1. 技术选型与项目结构

1.1 环境 & 依赖

  • 操作系统Windows 7
  • AutoCADAutoCAD 2014x86 或 x64
  • .NET Framework建议 4.5
  • IDEVisual Studio 2012 / 2013+

AutoCAD 引用:

  • AcCoreMgd.dll
  • AcDbMgd.dll
  • AcMgd.dll

(从 AutoCAD 2014 安装目录或 ARX SDK 中引用)

1.2 解决方案结构(建议)

Solution: AutoCADParamDrawing
 ├─ AutoCADParamDrawing.Plugin   // 插件宿主 + UI + CAD 操作
 ├─ AutoCADParamDrawing.Domain   // 业务模型 + 参数校验 + 出图算法
 ├─ AutoCADParamDrawing.Data     // 模板配置、系统配置等数据访问
 ├─ AutoCADParamDrawing.Common   // 日志、配置工具、通用扩展方法
  • Plugin:与 AutoCAD、UI 直接打交道;
  • Domain:只关心“参数”和“图形逻辑”,不关心 UI/配置文件细节;
  • Data:负责加载模板配置、系统参数(从 config/JSON/数据库等);
  • Common:基础设施。

2. 用户业务流程 & UI 设计

2.1 用户操作流程(从用户视角)

  1. 打开 AutoCAD新建一个空白图纸(或默认新建图);

  2. AutoCAD 启动时插件自动加载,右侧弹出**“参数化出图”面板**

  3. 用户在面板中完成三步:

    • 步骤 1填写模板参数

      • 项目类型(结构 / 给排水 / …)
      • 图纸类型(基础平面 / 楼层平面 / 剖面等)
      • 图幅A1 / A2 / A3 …)
      • 比例1:50 / 1:100…
      • 其他模板选型相关参数(开发时定)

      点击【匹配模板】按钮,面板显示匹配到的模板名称与路径。

    • 步骤 2填写出图参数

      • 构件类别 / 数量
      • 尺寸参数(长宽高、标高、层数……)
      • 出图规则选项(是否生成某些视图/明细等)

      具体参数由开发阶段根据业务确定。

    • 步骤 3生成图纸 & 保存

      • 点击【生成图纸】按钮:
        • 插件根据模板参数,找到模板文件;
        • 根据出图参数计算几何布置;
        • 调用 AutoCAD API 在图中生成图形(可选:自动基于模板新建一个新图窗体);
        • (新特性) 参数保存:生成图纸的同时,系统会将当前界面的所有参数自动保存到 DWG 的内部扩展字典中。
        • 出图完成后弹出提示,并提供【保存为…】按钮:
          • 打开文件保存对话框,让用户选择 DWG 名称和目录;
          • 插件内部调用 Database.SaveAs() 完成保存,参数数据会随文件一起保存
  4. 用户后续可手工调整图纸或继续用插件对同一模板重复生成。

2.2 插件主面板结构

ParamDrawingPanelWinForms UserControl建议布局

  1. 区域一模板参数Template Parameters

    • ComboBox项目类型ProjectType
    • ComboBox图纸类型DrawingType
    • ComboBox图幅SheetSize
    • ComboBox / TextBox比例Scale
    • 预留若干 TextBox/ComboBox 用于其它模板判断参数
    • 按钮:匹配模板Match Template
    • Label显示“已选模板XXX.dwt”或“未找到匹配模板”
  2. 区域二出图参数Drawing Parameters

    • 若干 TextBox/ComboBox具体字段开发时确定比如
      • 轴线数量、层数、构件高度等
    • 可以采用简单表格控件展示不同构件列表(可选)
  3. 区域三:操作按钮

    • 生成图纸Generate Drawing
    • 保存当前图纸…Save Drawing As…
    • 打开配置(打开模板配置/系统配置窗口)
  4. 区域四:日志/提示

    • 多行 TextBox 或 ListBox 用于显示:
      • 模板匹配结果;
      • 参数校验信息;
      • 出图进度、错误提示等。

3. 模块划分与职责

3.1 Plugin 层

主要命名空间(示例):

  • AutoCADParamDrawing.Plugin.Entry

    • 插件入口,实现 IExtensionApplication
    • 初始化 PaletteSet & Panel
  • AutoCADParamDrawing.Plugin.UI

    • ParamDrawingPanel:主面板
    • 可选其它对话框,如“配置窗口”
  • AutoCADParamDrawing.Plugin.Cad

    • CadContext:封装 Transaction / Document
    • CadDrawingService:封装 AutoCAD 绘图操作(画线、插块、文字、图层、布局等)
    • CadDrawingService:封装 AutoCAD 绘图操作(画线、插块、文字、图层、布局等)
    • TemplateDrawingService:处理“基于模板新建图纸”的逻辑
    • DictionaryHelper:封装 Extension Dictionary (NOD) 的读写操作,用于保存参数

职责总结:

  • 与 AutoCAD 交互Document、Database、锁定、事务
  • 与用户交互UI 事件);
  • 将 UI 输入转为 Domain 模型;
  • 调用 Domain 层完成校验和绘图。

3.2 Domain 层

建议基础模型结构如下(字段仅示意):

public class TemplateParams
{
    public string ProjectType { get; set; }
    public string DrawingType { get; set; }
    public string SheetSize { get; set; }
    public string Scale { get; set; }
    // 其他用于模板选择的参数,开发时补充
}

public class DrawingParams
{
    // 出图相关参数(构件、尺寸等),开发时定义
    // 示例:
    // public int FloorCount { get; set; }
    // public double ColumnWidth { get; set; }
    // ...
}

public class TemplateInfo
{
    public string Name { get; set; }
    public string FilePath { get; set; }
    public string Description { get; set; }
}

Domain 入口类(示例):

public static class DomainFacade
{
    public static TemplateInfo SelectTemplate(TemplateParams tplParams)
    {
        // 调用 Data 层TemplateRepository.FindTemplate(tplParams)
        // 并对结果做业务校验(是否唯一等)
    }

    public static void ValidateParameters(TemplateParams tplParams, DrawingParams drawParams)
    {
        // 对必填项、数值范围等进行校验
        // 可抛出 BusinessException 反馈给 UI
    }

    public static void DrawByParams(
        TemplateInfo template,
        DrawingParams drawParams,
        CadDrawingService cadService)
    {
        // 真正的业务绘图逻辑:
        // 1. 根据模板信息,配置图层/样式(如需要)
        // 2. 根据 drawParams 计算几何位置
        // 3. 调用 cadService 画线、插块、标注、文字等
        // 4. 可封装不同图纸类型的策略类BeamDrawingStrategy、ColumnDrawingStrategy 等
    }
}

职责:

  • 参数模型和校验;
  • 模板选择规则(+ Data 层配置);
  • 绘图算法与布置规则。

3.3 Data 层

Data 层主要处理 模板配置 & 系统配置,例如:

public class TemplateDefinition
{
    public string Id { get; set; }           // 内部唯一 ID
    public string ProjectType { get; set; }
    public string DrawingType { get; set; }
    public string SheetSize { get; set; }
    public string Scale { get; set; }
    public string FilePath { get; set; }     // 模板文件路径
    public string Description { get; set; }
}

模板仓储接口:

public interface ITemplateRepository
{
    TemplateDefinition FindTemplate(TemplateParams tplParams);
    IEnumerable<TemplateDefinition> GetAll();
}

实现可以是:

  • 读取 app.config / JSON 文件 / XML 文件等;
  • 配置格式示例JSON 形式,具体由开发时确定):
[
  {
    "ProjectType": "结构",
    "DrawingType": "基础平面",
    "SheetSize": "A1",
    "Scale": "1:50",
    "FilePath": "C:\\CadTemplates\\Stru_Base_A1_50.dwt",
    "Description": "结构基础平面 A1 1:50"
  }
]

具体字段和匹配策略可以开发时再细化,这里只定义架构和职责。


3.4 Common 层

  • 日志工具:Logger.Info/Error(写文本或者 log4net 等);
  • 配置读取:读取 app.config 或 JSON 路径;
  • 通用异常类型:BusinessException 用于业务错误提示用户。

4. 核心技术实现示意

4.1 插件入口 & PaletteSet 创建

using Autodesk.AutoCAD.Runtime;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.Windows;

namespace AutoCADParamDrawing.Plugin.Entry
{
    public class PluginEntry : IExtensionApplication
    {
        private static PaletteSet _palette;

        public void Initialize()
        {
            CreateAndShowPalette();
        }

        public void Terminate()
        {
            // 可记录日志等
        }

        private void CreateAndShowPalette()
        {
            if (_palette == null)
            {
                _palette = new PaletteSet("参数化出图")
                {
                    Style = PaletteSetStyles.ShowCloseButton |
                            PaletteSetStyles.ShowAutoHideButton |
                            PaletteSetStyles.Snappable
                };

                var panel = new UI.ParamDrawingPanel();
                _palette.Add("主面板", panel);
                _palette.MinimumSize = new System.Drawing.Size(320, 400);
            }

            _palette.Visible = true;
        }

        // 可选:用于调试/恢复面板
        [CommandMethod("PARAM_PANEL")]
        public void ShowPanelCommand()
        {
            CreateAndShowPalette();
        }
    }
}

4.2 CadContext & CadDrawingService

using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;

namespace AutoCADParamDrawing.Plugin.Cad
{
    public class CadContext : IDisposable
    {
        public Document Document { get; }
        public Database Database => Document.Database;
        public Transaction Transaction { get; private set; }

        public CadContext(Document doc)
        {
            Document = doc;
            Transaction = Database.TransactionManager.StartTransaction();
        }

        public void Commit()
        {
            Transaction?.Commit();
        }

        public void Dispose()
        {
            Transaction?.Dispose();
            Transaction = null;
        }
    }

    public class CadDrawingService
    {
        private readonly CadContext _ctx;

        public CadDrawingService(CadContext ctx)
        {
            _ctx = ctx;
        }

        // 示例:画线
        public ObjectId DrawLine(Point3d start, Point3d end)
        {
            var db = _ctx.Database;
            var tr = _ctx.Transaction;
            var bt = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead);
            var btr = (BlockTableRecord)tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite);

            var line = new Line(start, end);
            var id = btr.AppendEntity(line);
            tr.AddNewlyCreatedDBObject(line, true);
            return id;
        }

        // TODO: 插块、文字、标注、图层等方法开发时补充
    }
}

4.3 基于模板新建图纸(可选方案)

两种方式,二选一:

  1. 直接在当前新建图中绘图
    • 只用模板来参考图层/样式规则,但不真正打开模板文件;
  2. 真正基于模板新建一个图纸 Document(推荐):

示例(在 UI 的“生成图纸”里调用):

public Document CreateDocumentFromTemplate(TemplateInfo tpl)
{
    // template.FilePath 来自 Data 层配置
    var newDoc = Autodesk.AutoCAD.ApplicationServices.Application
                    .DocumentManager.Add(tpl.FilePath);

    // 设为当前活动文档
    Autodesk.AutoCAD.ApplicationServices.Application
        .DocumentManager.MdiActiveDocument = newDoc;

    return newDoc;
}

之后:

var tplInfo = DomainFacade.SelectTemplate(templateParams);
DomainFacade.ValidateParameters(templateParams, drawingParams);

var newDoc = TemplateDrawingService.CreateDocumentFromTemplate(tplInfo);

using (newDoc.LockDocument())
using (var ctx = new CadContext(newDoc))
{
    var cadService = new CadDrawingService(ctx);
    DomainFacade.DrawByParams(tplInfo, drawingParams, cadService);
    ctx.Commit();
}

4.4 UI 面板核心逻辑示意ParamDrawingPanel

public partial class ParamDrawingPanel : UserControl
{
    private TemplateInfo _selectedTemplate;

    public ParamDrawingPanel()
    {
        InitializeComponent();
    }

    private TemplateParams CollectTemplateParamsFromUI()
    {
        return new TemplateParams
        {
            ProjectType = cbProjectType.Text,
            DrawingType = cbDrawingType.Text,
            SheetSize   = cbSheetSize.Text,
            Scale       = cbScale.Text
            // 更多字段开发时补充
        };
    }

    private DrawingParams CollectDrawingParamsFromUI()
    {
        var p = new DrawingParams();
        // 从文本框/下拉框收集各类出图参数
        return p;
    }

    private void btnMatchTemplate_Click(object sender, EventArgs e)
    {
        try
        {
            var tplParams = CollectTemplateParamsFromUI();
            _selectedTemplate = DomainFacade.SelectTemplate(tplParams);

            lblTemplateInfo.Text = $"已匹配模板: {_selectedTemplate.Name}";
            AppendLog($"模板: {_selectedTemplate.FilePath}");
        }
        catch (BusinessException bex)
        {
            AppendLog($"模板选择错误: {bex.Message}");
        }
        catch (Exception ex)
        {
            AppendLog($"异常: {ex.Message}");
            Logger.Error("MatchTemplate", ex);
        }
    }

    private void btnGenerate_Click(object sender, EventArgs e)
    {
        if (_selectedTemplate == null)
        {
            AppendLog("请先匹配模板。");
            return;
        }

        try
        {
            var tplParams   = CollectTemplateParamsFromUI();
            var drawingParams = CollectDrawingParamsFromUI();

            DomainFacade.ValidateParameters(tplParams, drawingParams);

            // 创建基于模板的新图纸并绘图
            var newDoc = TemplateDrawingService.CreateDocumentFromTemplate(_selectedTemplate);

            using (newDoc.LockDocument())
            using (var ctx = new CadContext(newDoc))
            {
                var cadService = new CadDrawingService(ctx);
                DomainFacade.DrawByParams(_selectedTemplate, drawingParams, cadService);
                ctx.Commit();
            }

            AppendLog("图纸生成完成。");
        }
        catch (BusinessException bex)
        {
            AppendLog($"参数错误: {bex.Message}");
        }
        catch (Exception ex)
        {
            AppendLog($"生成失败: {ex.Message}");
            Logger.Error("GenerateDrawing", ex);
        }
    }

    private void btnSaveAs_Click(object sender, EventArgs e)
    {
        var doc = Autodesk.AutoCAD.ApplicationServices.Application
                  .DocumentManager.MdiActiveDocument;

        using var dlg = new SaveFileDialog
        {
            Filter = "AutoCAD Drawing (*.dwg)|*.dwg",
            FileName = "新图纸.dwg"
        };
        if (dlg.ShowDialog() == DialogResult.OK)
        {
            doc.Database.SaveAs(dlg.FileName, true, DwgVersion.Current, doc.Database.SecurityParameters);
            AppendLog($"图纸已保存到: {dlg.FileName}");
        }
    }

    private void AppendLog(string msg)
    {
        txtLog.AppendText(msg + Environment.NewLine);
    }
}

4.5 新模板出图逻辑隔离(新增模板开发流程)

为保证每个模板的生成图纸逻辑隔离,出图逻辑按模板拆分为独立生成器:

核心机制

  • 每个模板由 TemplateKey 唯一标识(由 TemplateKeyBuilder.Build(ProjectType, DrawingType, SheetSize, Scale) 生成)。
  • 出图时根据 TemplateKeyTemplateDrawingRegistry 解析到对应生成器;
  • 公共流程(清理模板、附注/表格替换、标题栏更新、参数保存)仍在 ParamDrawingPanel 中执行, 只有“图形绘制 + 预期尺寸计算”由各生成器负责

新增模板流程(开发者指引)

  1. 新增生成器类

    • 目录:Cad/Drawers/
    • 实现 ITemplateDrawingGenerator 或继承 TemplateDrawingGeneratorBase
    • 指定 TemplateKey,与模板参数绑定配置完全一致。
    public sealed class NewTemplateGenerator : TemplateDrawingGeneratorBase
    {
        public static readonly string Key = TemplateKeyBuilder.Build("交付状态", "工艺方法", "结构特征", "特殊条件");
        public override string TemplateKey => Key;
    
        // 如需特殊尺寸预估,重写此方法
        public override FeatureDrivenDrawer.ExpectedDrawingSize CalculateExpectedSize(ParamBag bag, TemplateParams templateParams)
        {
            return base.CalculateExpectedSize(bag, templateParams);
        }
    
        // 如需自定义出图逻辑,重写此方法
        public override void Draw(CadContext ctx, ParamBag bag, TemplateParams templateParams, Point3d center, double scaleFactor)
        {
            // 自定义绘图逻辑
        }
    }
    
  2. 注册生成器

    • TemplateDrawingRegistry 的静态构造函数中注册:
    Register(new NewTemplateGenerator());
    
  3. 配置模板参数绑定

    • 模板参数绑定 界面新增模板定义(或在 TemplateSchemaDefaults 中加入默认项)。
    • 确保 ProjectType / DrawingType / SheetSize / Scale 与生成器 TemplateKey 完全一致。
  4. 参数与附注

    • 在模板绑定里选择该模板需要的参数;
    • 配置附注模板文本与占位符绑定(若需要)。

说明

  • 现有模板生成器示例位于 Cad/Drawers/,可直接参考扩展;
  • 若某模板需要完全不同的绘图算法,可在生成器中自行实现,不影响其他模板。

具体 UI 控件命名、字段等开发时根据实际参数调整。


5. 开发步骤(执行指引)

步骤 1创建解决方案 & 项目

  1. 新建 VS 解决方案 AutoCADParamDrawing
  2. 创建四个项目Plugin / Domain / Data / Common
  3. Plugin 项目引用 AutoCAD DLL
  4. Common 项目实现基础配置/日志工具类。

步骤 2定义参数模型Domain

  1. 定义 TemplateParams, DrawingParams, TemplateInfo 等类;
  2. 类上用注释说明这些属性将对应到 UI 控件;
  3. 定义 DomainFacade 入口方法:
    • SelectTemplate
    • ValidateParameters
    • DrawByParams

步骤 3实现模板配置Data 层)

  1. 确定模板配置文件格式(建议 JSON / XML方便非程序员维护
  2. 实现 TemplateRepository
    • 从配置文件加载所有模板定义;
    • 提供按 TemplateParams 匹配模板的方法;
  3. DomainFacade.SelectTemplate 中调用 TemplateRepository 并处理找不到/多条等情况。

步骤 4实现 Domain 的基本绘图算法

  1. 先实现简单版本
    • 根据一两个简单参数(比如构件数量/长度)画出一些线条/框,验证流程;
  2. 后续逐步细化:
    • 按不同图纸类型拆分策略类;
    • 完善图层、标注、文字等。

步骤 5实现 Plugin 层的 CadContext & CadDrawingService

  1. 封装事务和 Document 操作;
  2. 实现画线/插块/文字/标注等基础方法;
  3. 后续根据业务增加更多方法。

步骤 6实现 UI 面板ParamDrawingPanel

  1. 设计界面布局(模板参数区 + 出图参数区 + 操作区 + 日志区);
  2. 编写事件处理逻辑:
    • 参数收集 → 模板匹配 → 参数校验 → 调用生成图纸;
  3. 实现 btnSaveAs 保存功能。

步骤 7实现插件入口IExtensionApplication

  1. PluginEntry.Initialize 中创建 PaletteSet添加 ParamDrawingPanel
  2. 编译后在 AutoCAD 中 NETLOAD 测试:
    • 确认启动时自动出现面板;
    • 按步骤能生成一张简单测试图。

步骤 8迭代完善业务细节

  • 与业务方确认参数列表 & 模板规则;
  • 丰富模板配置;
  • 封装真实业务绘图算法;
  • 扩展功能:
    • 多图纸批量生成;
    • 一键生成并保存到指定目录等。

6. 测试要点(开发自测参考)

  1. 模板匹配

    • 输入各种模板参数组合;
    • 检查模板是否正确匹配,找不到/多条时提示是否合理。
  2. 参数校<EFBFBD><EFBFBD>

    • 有必填项为空时,能在 UI 上提示具体字段;
    • 数值异常(负数、格式错误)能被拦截。
  3. 绘图结果

    • 图形是否根据参数变化;
    • 图层/文字/标注是否按模板和规则创建。
  4. 保存

    • “保存为…”是否成功输出 DWG 文件;
    • 再次打开是否正常显示。

7. 部署与使用说明(给实施/最终用户)

  1. 将编译后的 AutoCADParamDrawing.Plugin.dll 及其它依赖拷贝至指定目录(如:C:\CadPlugins\ParamDrawing\)。
  2. 建议做成 AutoCAD .bundle 插件,实现自动加载;或者由实施人员在启动脚本中设置 NETLOAD
  3. 用户启动 AutoCAD 后:
    • 看到右侧“参数化出图”面板;
    • 按“模板参数 → 匹配模板 → 出图参数 → 生成图纸 → 保存”流程使用即可。