CommandMethodAttribute 详解

这是 AutoCAD .NET API 中最重要的特性之一,用于将 C# 方法注册为 AutoCAD 命令。我来详细解释每个重载及其应用场景。


一、所有重载及参数说明

// 我画了一张表,帮你快速定位参数含义
参数 类型 必需 说明 示例
globalName string 命令的全局名称(CAD命令行中输入的名称) "DrawWall"
groupName string 命令组名(用于命令分组管理) "MyWallTools"
localizedNameId string 本地化名称ID(多语言支持) "IDS_CMD_DRAWWALL"
flags CommandFlags 命令行为标志(默认Modal) CommandFlags.Modal
contextMenuExtensionType Type 右键菜单扩展类型 typeof(MyContextMenu)
helpFileName string 帮助文件名 "MyAppHelp.chm"
helpTopic string 帮助主题ID "WallTools"

二、7个重载详解(按复杂度递增)

重载1:最简单的命令注册

public CommandMethodAttribute(string globalName)

意义: 最基础的命令注册,适合快速开发、测试阶段。

示例:

// 最简单的命令,在CAD中输入 "Hello" 即可执行
[CommandMethod("Hello")]
public void SayHello()
{
    Application.DocumentManager.MdiActiveDocument.Editor.WriteMessage("\nHello AutoCAD!");
}

// CAD命令行使用:
// 命令: Hello
// 输出: Hello AutoCAD!

使用场景:

  • 快速原型开发
  • 内部工具
  • 单一功能的简单命令

重载2:带命令标志

public CommandMethodAttribute(string globalName, CommandFlags flags)

意义: 控制命令的执行模式和行为。

示例:

// 只读命令,不会锁定文档
[CommandMethod("CheckDrawing", CommandFlags.Session)]
public void CheckDrawing()
{
    // 可以在不锁定文档的情况下检查图纸信息
    Document doc = Application.DocumentManager.MdiActiveDocument;
    Editor editor = doc.Editor;
    editor.WriteMessage($"\n{DateTime.Now}: 图纸检查完成");
}

// 透明命令(可以在其他命令执行期间调用)
[CommandMethod("ShowAngle", CommandFlags.Transparent)]
public void ShowAngle()
{
    Application.DocumentManager.MdiActiveDocument.Editor.WriteMessage("\n当前角度: 0°");
}

CommandFlags 枚举详解:

标志 说明 典型场景
Modal 0 模态命令(默认) 大部分绘图命令
Transparent 1 透明命令 辅助查询命令(如’ZOOM)
NoPerspective 2 禁止透视模式 3D特殊控制
Session 4 会话级命令 多文档操作
NoHistory 8 不记录命令历史 临时操作
NoUndoMarker 16 不创建撤销标记 批量操作优化

使用场景:

  • 需要在其他命令中执行的工具(Transparent)
  • 跨文档操作(Session)
  • 性能优化(NoHistory)

重载3:命令分组

public CommandMethodAttribute(string groupName, string globalName, CommandFlags flags)

意义: 将相关命令组织在一起,便于管理和查找。

示例:

public class WallCommands
{
    // 所有墙线相关命令都在 "WallTools" 组下
    [CommandMethod("WallTools", "DrawWall", CommandFlags.Modal)]
    public void DrawWall()
    {
        // 绘制墙线
    }

    [CommandMethod("WallTools", "EditWall", CommandFlags.Modal)]
    public void EditWall()
    {
        // 编辑墙线
    }

    [CommandMethod("WallTools", "DeleteWall", CommandFlags.Modal)]
    public void DeleteWall()
    {
        // 删除墙线
    }
}

// 在CAD中可以使用 ARX 命令查看分组
// 命令: ARX -> 命令组 -> WallTools

使用场景:

  • 大型插件系统
  • 功能模块化管理
  • 团队协作开发

重载4:支持本地化

public CommandMethodAttribute(string groupName, string globalName, string localizedNameId, CommandFlags flags)

意义: 支持多语言版本,通过资源文件提供本地化的命令名和提示。

示例:

// 定义本地化ID,支持中英文切换
[CommandMethod("WallTools", "DrawWall", "IDS_CMD_DRAWWALL_CN", CommandFlags.Modal)]
public void DrawWall()
{
    // 中文环境下显示: 绘制墙线
    // 英文环境下显示: Draw Wall
}

// 资源文件 (Resources.resx)
// IDS_CMD_DRAWWALL_CN = "绘制墙线"
// IDS_CMD_DRAWWALL_EN = "DrawWall"

使用场景:

  • 国际化应用程序
  • 面向不同语言用户的产品
  • 需要动态切换语言的CAD插件

重载5:右键菜单扩展

public CommandMethodAttribute(string groupName, string globalName, string localizedNameId, CommandFlags flags, Type contextMenuExtensionType)

意义: 将命令添加到CAD的右键快捷菜单中。

示例:

// 定义右键菜单扩展
public class WallContextMenu : ContextMenuExtension
{
    public WallContextMenu()
    {
        Title = "墙线工具";
        
        MenuItem item1 = new MenuItem("绘制墙线");
        item1.Click += (s, e) => {
            Application.DocumentManager.MdiActiveDocument.SendStringToExecute("DrawWall ", true, false, true);
        };
        MenuItems.Add(item1);
    }
}

// 使用右键菜单扩展
[CommandMethod("WallTools", "DrawWall", "IDS_CMD_DRAWWALL", CommandFlags.Modal, typeof(WallContextMenu))]
public void DrawWall()
{
    // 绘制墙线
    // 右键菜单中也会出现此命令
}

使用场景:

  • 提升用户体验
  • 快速访问常用命令
  • 专业工具软件

重载6:帮助主题

public CommandMethodAttribute(string groupName, string globalName, string localizedNameId, CommandFlags flags, string helpTopic)

意义: 为命令关联帮助文档,用户按F1时自动打开。

示例:

// 关联HTML帮助主题
[CommandMethod("WallTools", "DrawWall", "IDS_CMD_DRAWWALL", CommandFlags.Modal, "WallTools/DrawWall")]
public void DrawWall()
{
    try
    {
        // 绘制墙线逻辑
    }
    catch (Exception ex)
    {
        Application.DocumentManager.MdiActiveDocument.Editor.WriteMessage($"\n错误: {ex.Message}");
        // 按F1查看帮助
    }
}

// 在帮助文件中的锚点
// MyAppHelp.htm#WallTools/DrawWall

使用场景:

  • 商业软件产品
  • 复杂功能需要文档支持
  • 企业内部工具

重载7:完整参数(全部功能)

public CommandMethodAttribute(string groupName, string globalName, string localizedNameId, CommandFlags flags, Type contextMenuExtensionType, string helpFileName, string helpTopic)

意义: 功能最全的重载,包含所有扩展功能。

示例:

// 最完整的命令注册
[CommandMethod(
    "WallTools",                    // 命令组
    "DrawWall",                     // 命令名
    "IDS_CMD_DRAWWALL_CN",          // 本地化ID
    CommandFlags.Modal,             // 执行模式
    typeof(WallContextMenu),        // 右键菜单
    "ArchitectCAD.chm",             // 帮助文件
    "WallTools/DrawWall"            // 帮助主题
)]
public void DrawWall()
{
    // 最完整的命令实现
    Document doc = Application.DocumentManager.MdiActiveDocument;
    Editor editor = doc.Editor;
    
    editor.WriteMessage("\n开始绘制墙线...");
    
    // 实现逻辑...
}

三、开发中的实际意义

1. 组织管理

// 按模块分组
[CommandMethod("Architecture", "DrawWall", ...)]    // 建筑模块
[CommandMethod("Architecture", "EditWall", ...)]
[CommandMethod("MEP", "DrawPipe", ...)]              // 机电模块
[CommandMethod("MEP", "DrawDuct", ...)]
[CommandMethod("Structure", "DrawBeam", ...)]        // 结构模块

2. 权限控制

// 只读命令,不需要锁定文档
[CommandMethod("Viewer", "QuickView", CommandFlags.Session)]
public void QuickView() { ... }

// 可撤销的命令
[CommandMethod("Editor", "ModifyObject", CommandFlags.Modal)]
public void ModifyObject() { ... }

3. 用户体验优化

// 常用工具加入右键菜单
[CommandMethod("Tools", "QuickCopy", ..., typeof(QuickCopyMenu))]
public void QuickCopy() { ... }

// 带帮助文档
[CommandMethod("Tools", "AdvancedFilter", ..., "Tools/Filter")]
public void AdvancedFilter() { ... }

四、最佳实践

1. 命名规范

// 使用动词+名词命名
[CommandMethod("DrawRect", "DR")]     // 绘制矩形
[CommandMethod("CreateBlock", "CB")]  // 创建块
[CommandMethod("ExportPDF", "EP")]    // 导出PDF

// 避免模糊名称
// ❌ [CommandMethod("DoIt")]
// ✅ [CommandMethod("CalculateArea")]

2. 错误处理

[CommandMethod("SafeCommand")]
public void SafeCommand()
{
    try
    {
        // 业务逻辑
    }
    catch (Autodesk.AutoCAD.Runtime.Exception ex)
    {
        // AutoCAD异常
        Application.ShowAlertDialog($"AutoCAD错误: {ex.Message}");
    }
    catch (System.Exception ex)
    {
        // 其他异常
        Application.DocumentManager.MdiActiveDocument.Editor.WriteMessage($"\n系统错误: {ex.Message}");
    }
}

3. 版本兼容

#if ACAD2014
    [CommandMethod("DrawWall2014", CommandFlags.Modal)]
#elif ACAD2016
    [CommandMethod("DrawWall2016", CommandFlags.Modal)]
#endif
    public void DrawWall()
    {
        // 不同版本的实现
    }

我来给每个参数配上直观的Demo代码,让你一目了然。


完整Demo:一个"建筑墙线"命令的各种玩法

using System;
using System.Windows.Forms;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Runtime;
using Autodesk.AutoCAD.Windows;

namespace WallCommandDemo
{
    // ============================================
    // 1. globalName - 命令名
    // 作用:你在CAD命令行敲什么,命令就执行什么
    // ============================================
    
    /// <summary>
    /// 最简单的注册,只有一个globalName
    /// 在CAD命令行输入 "HelloCAD" 回车即可执行
    /// </summary>
    [CommandMethod("HelloCAD")]
    public void SayHello()
    {
        Application.DocumentManager.MdiActiveDocument.Editor.WriteMessage("\n✅ 你好!我执行了!因为我的globalName是HelloCAD");
    }


    // ============================================
    // 2. groupName - 命令组名
    // 作用:把相关命令打包,方便管理、卸载
    // ============================================
    
    /// <summary>
    /// 未分组 - 散兵游勇,不好管
    /// </summary>
    [CommandMethod("DrawWall1")]
    public void DrawWallUngrouped() { }

    /// <summary>
    /// 已分组 - 在ARX命令里能看到"WallTools"这个组
    /// 可以整体加载/卸载这组命令
    /// </summary>
    [CommandMethod("WallTools", "DrawWall2", CommandFlags.Modal)]
    public void DrawWallGrouped()
    {
        var ed = Application.DocumentManager.MdiActiveDocument.Editor;
        ed.WriteMessage("\n✅ 我在WallTools组里!用ARX命令可以看到我");
        ed.WriteMessage("\n   你也可以用 LISP 卸载整个组: (command \"ARX\" \"U\" \"WallTools\")");
    }

    [CommandMethod("WallTools", "EditWall", CommandFlags.Modal)]
    public void EditWall() { }

    [CommandMethod("WallTools", "DeleteWall", CommandFlags.Modal)]
    public void DeleteWall() { }


    // ============================================
    // 3. localizedNameId - 本地化ID
    // 作用:中英文切换时,命令名自动变
    // ============================================
    
    /// <summary>
    /// 你的资源文件 Resources.resx 里:
    /// IDS_DRAWWALL_CN → "绘制墙线"  (中文CAD显示这个)
    /// IDS_DRAWWALL_EN → "DrawWall"  (英文CAD显示这个)
    /// </summary>
    [CommandMethod("WallTools", "DrawWall", "IDS_DRAWWALL_CN", CommandFlags.Modal)]
    public void LocalizedDrawWall()
    {
        var ed = Application.DocumentManager.MdiActiveDocument.Editor;
        ed.WriteMessage("\n✅ 这个命令支持多语言!");
        ed.WriteMessage("\n   中文CAD里命令叫: 绘制墙线");
        ed.WriteMessage("\n   英文CAD里命令叫: DrawWall");
    }


    // ============================================
    // 4. flags - 命令行为标志
    // 作用:控制命令怎么执行
    // ============================================

    /// <summary>
    /// 默认 Modal 模式:执行时锁定文档,不能干别的
    /// </summary>
    [CommandMethod("DrawModal")]
    public void ModalCommand()
    {
        var ed = Application.DocumentManager.MdiActiveDocument.Editor;
        ed.WriteMessage("\n🔒 我是模态命令,执行期间你不能做其他操作");
        ed.WriteMessage("\n   这是默认行为,适合大部分绘图命令");
    }

    /// <summary>
    /// Transparent 透明命令:在其他命令执行期间也能调用
    /// 用法:执行DrawModal时,输入 'CheckInfo (前面加撇号)
    /// </summary>
    [CommandMethod("CheckInfo", CommandFlags.Transparent)]
    public void TransparentCommand()
    {
        var ed = Application.DocumentManager.MdiActiveDocument.Editor;
        ed.WriteMessage("\n👻 我是透明命令!前面加撇号'调用我");
        ed.WriteMessage("\n   比如你正在画线时输入 'CheckInfo 就能看到我");
    }

    /// <summary>
    /// Session 会话级:不锁定文档,可以在后台监控
    /// </summary>
    [CommandMethod("MonitorDrawing", CommandFlags.Session)]
    public void SessionCommand()
    {
        var doc = Application.DocumentManager.MdiActiveDocument;
        var ed = doc.Editor;
        ed.WriteMessage("\n🔓 我是会话级命令,不锁定文档");
        ed.WriteMessage($"\n   当前时间: {DateTime.Now}");
        ed.WriteMessage($"\n   当前图纸: {doc.Name}");
    }


    // ============================================
    // 5. contextMenuExtensionType - 右键菜单
    // 作用:选中对象点右键时,出现这个命令
    // ============================================

    /// <summary>
    /// 右键菜单类 - 必须继承 ContextMenuExtension
    /// </summary>
    public class WallRightClickMenu : ContextMenuExtension
    {
        public WallRightClickMenu()
        {
            Title = "🏗️ 墙线工具";

            // 菜单项1
            MenuItem createWallItem = new MenuItem("绘制墙线");
            createWallItem.Click += (sender, e) =>
            {
                // 发送命令到CAD命令行
                Application.DocumentManager.MdiActiveDocument
                    .SendStringToExecute("DrawWallFromMenu ", true, false, true);
            };
            MenuItems.Add(createWallItem);

            // 菜单项2
            MenuItem editWallItem = new MenuItem("编辑墙线");
            editWallItem.Click += (sender, e) =>
            {
                Application.ShowAlertDialog("编辑功能待实现");
            };
            MenuItems.Add(editWallItem);

            // 分隔线
            MenuItems.Add(new MenuItem("-"));

            // 菜单项3
            MenuItem deleteWallItem = new MenuItem("删除墙线");
            deleteWallItem.Click += (sender, e) =>
            {
                Application.ShowAlertDialog("删除功能待实现");
            };
            MenuItems.Add(deleteWallItem);
        }
    }

    /// <summary>
    /// 关联右键菜单的命令
    /// 用户选中对象 → 右键 → 会出现"墙线工具"菜单
    /// </summary>
    [CommandMethod("DrawWallFromMenu", CommandFlags.Modal, typeof(WallRightClickMenu))]
    public void DrawWallFromRightClick()
    {
        var ed = Application.DocumentManager.MdiActiveDocument.Editor;
        ed.WriteMessage("\n🖱️ 我是从右键菜单调用的!");
        ed.WriteMessage("\n   你也可以直接输入 DrawWallFromMenu 来执行");
    }


    // ============================================
    // 6. helpTopic - 帮助主题ID
    // 作用:用户按F1时,跳转到帮助文件的指定锚点
    // ============================================
    
    /// <summary>
    /// 帮助文件名 + 帮助主题
    /// 用户执行命令后按F1,就会打开 MyCADHelp.chm 并定位到 WallDraw 章节
    /// </summary>
    [CommandMethod("AdvancedDrawWall", CommandFlags.Modal, "WallDraw")]
    public void DrawWallWithHelp()
    {
        var ed = Application.DocumentManager.MdiActiveDocument.Editor;
        ed.WriteMessage("\n📖 如果你不会用,请按 F1 查看帮助!");
        ed.WriteMessage("\n   帮助文件定位到: WallDraw 章节");
        ed.WriteMessage("\n   帮助文件: MyCADHelp.chm");
        
        // 执行命令逻辑
        ed.WriteMessage("\n正在绘制高级墙线...");
    }


    // ============================================
    // 7. helpFileName - 帮助文件名
    // 作用:指定.chm帮助文件
    // ============================================
    
    /// <summary>
    /// 完整版:指定帮助文件 + 帮助主题
    /// F1会打开 "MyCADHelp.chm" 并跳到 "WallTools/DrawWall" 章节
    /// </summary>
    [CommandMethod("ProDrawWall", CommandFlags.Modal, "DrawWall", "ProWallGuide")]
    public void ProfessionalDrawWall()
    {
        var ed = Application.DocumentManager.MdiActiveDocument.Editor;
        ed.WriteMessage("\n📖 按 F1 查看专业帮助");
        ed.WriteMessage("\n   帮助文件: DrawWall.chm");
        ed.WriteMessage("\n   主题: ProWallGuide");
        
        ed.WriteMessage("\n专业墙线绘制中...");
    }


    // ============================================
    // 🎯 综合Demo:最完整的命令注册
    // ============================================
    
    /// <summary>
    /// 全部参数都用上!
    /// </summary>
    [CommandMethod(
        "WallTools",                    // 组名:在ARX里能看到
        "SuperDrawWall",               // 命令名:用户输入这个
        null,     // 本地化:可空
        CommandFlags.Modal,             // 模态执行
        typeof(WallRightClickMenu),     // 右键菜单
        "ArchitectWallHelp",            // 帮助文件
        "SuperDrawWall/Overview"        // 帮助主题
    )]
    public void SuperDrawWall()
    {
        var ed = Application.DocumentManager.MdiActiveDocument.Editor;
        
        ed.WriteMessage("\n━━━━━━━━━━━━━━━━━━━━━━━━━━");
        ed.WriteMessage("\n🌟 我是最完整的命令!");
        ed.WriteMessage("\n   1. 命令组: WallTools");
        ed.WriteMessage("\n   2. 命令名: SuperDrawWall");
        ed.WriteMessage("\n   3. 执行模式: Modal(锁定文档)");
        ed.WriteMessage("\n   4. 右键菜单: 已集成");
        ed.WriteMessage("\n   5. 帮助文件: ArchitectWallHelp.chm");
        ed.WriteMessage("\n   6. 帮助主题: SuperDrawWall/Overview");
        ed.WriteMessage("\n━━━━━━━━━━━━━━━━━━━━━━━━━━");
    }


    // ============================================
    // 🧪 测试命令(检验所有功能)
    // ============================================
    
    [CommandMethod("TestAllFeatures")]
    public void TestEverything()
    {
        var ed = Application.DocumentManager.MdiActiveDocument.Editor;
        
        ed.WriteMessage("\n\n╔══════════════════════════════════════╗");
        ed.WriteMessage("\n║   CommandMethod 参数完整测试         ║");
        ed.WriteMessage("\n╚══════════════════════════════════════╝");
        
        ed.WriteMessage("\n\n📋 以下命令可以测试:");
        ed.WriteMessage("\n   HelloCAD          → 测试 globalName");
        ed.WriteMessage("\n   DrawWall1         → 测试 无分组");
        ed.WriteMessage("\n   DrawWall2         → 测试 groupName");
        ed.WriteMessage("\n   DrawModal         → 测试 Modal 标志");
        ed.WriteMessage("\n   'CheckInfo        → 测试 Transparent(注意前面加撇号)");
        ed.WriteMessage("\n   MonitorDrawing    → 测试 Session");
        ed.WriteMessage("\n   DrawWallFromMenu  → 测试 右键菜单");
        ed.WriteMessage("\n   AdvancedDrawWall  → 测试 帮助主题(执行后按F1)");
        ed.WriteMessage("\n   ProDrawWall       → 测试 完整帮助文件");
        ed.WriteMessage("\n   SuperDrawWall     → 测试 全参数组合");
    }
}

🎬 使用演示

在CAD里分别测试:

命令: HelloCAD
输出: ✅ 你好!我执行了!因为我的globalName是HelloCAD

命令: DrawWall2
输出: ✅ 我在WallTools组里!用ARX命令可以看到我

命令: 'CheckInfo          ← 注意前面的撇号!
输出: 👻 我是透明命令!前面加撇号'调用我

命令: SuperDrawWall
输出: 🌟 我是最完整的命令!
      [此时选中实体右键 → 看到"墙线工具"菜单]
      [按F1 → 打开帮助文件 ArchitectWallHelp.chm]

📊 一图总结

[CommandMethod(
    "WallTools",          ← groupName     : 把命令装进叫"WallTools"的抽屉
    "SuperDrawWall",      ← globalName    : 用户喊"SuperDrawWall"我就动
    "IDS_DRAW",           ← localizedNameId : 老外喊"DrawWall"也行
    CommandFlags.Modal,   ← flags          : 我干活时别人别打扰(锁定文档)
    typeof(WallMenu),     ← contextMenu    : 右键菜单里有我
    "Help.chm",           ← helpFileName   : 不懂?看Help.chm
    "Topic123"            ← helpTopic      : 直接翻到Topic123这一页
)]

五、推荐文章

以下是一些关于 AutoCAD .NET 二次开发中 CommandMethod 的优质博文资源:

  1. AutoCAD .NET API 官方文档

  2. Kean Walmsley’s Through the Interface

  3. 中文资源推荐

    • CSDN 搜索"AutoCAD .NET CommandMethod"
    • 博客园搜索"AutoCAD 二次开发 命令注册"
    • 知乎搜索"AutoCAD .NET 开发"
  4. 书籍推荐

    • 《AutoCAD VBA & VB.NET开发基础与实例教程》
    • 《AutoCAD .NET 二次开发指南》

AutoCAD.EntityTools


更多推荐