C#二次开发 AutoCAD 动态加载自定义菜单和命令 西域雪狼 2019 年 9 月 4 日
C#二次开发 AutoCAD 动态加载自定义菜单和命令
在 AutoCAD 二次开发过程中,一般都是开发自定义的命令,然后在菜单栏/工具栏/菜单面板中添加对应的菜单,通过点击菜单调用开发的命令。
对于实现以上问题,传统的做法就是在二次开发类库中开发一个命令方法,并且方法被标注为:[CommandMethod("XXX")],然后制作 CUIX 文件,在
AutoCAD 中加载命令所在的类库(dll)和 CUIX 文件,通过点击菜单调用命令。
当我们开发的命令较多,且需要根据场景显示不同的菜单的时候,传统的做法就非常麻烦了。且每次修改都要改代码,灵活性不高。所以我们就想
通过动态配置,CAD 每次启动时能动态的加载我们配置好的命令和菜单。
一,自动加载自定义菜单的实现方法:
1, 先在 CAD 中开发一个配置工具,配置好已开发的命令。如下图所示:
C#二次开发 AutoCAD 动态加载自定义菜单和命令 西域雪狼 2019 年 9 月 4 日
【命令标识】为 CAD 中执行当前命令的快捷命令;
【程序集】为实现当前命令的 dll,【命令类】为实现当前命令的类的全名称。在调用当前命令时可通过反射实现。(关于为什么使用反射来调用命令,
在后面说明)。
【图标】表示显示到 AutoCAD 界面上的的图标,可以选择本地的一个图片文件。
配置好后显示到 AutoCAD 中的效果如下图所示:
2, 实现读取已配置的命令的方法
private static Dictionary> readConfigCommands()
{
var dic = new Dictionary>();
/*
* 实现从配置文件中读取已配置命令的方法
*
* CommandModel为自定义的命令对象,对象中属性与配置界面的对应。
*
*/
C#二次开发 AutoCAD 动态加载自定义菜单和命令 西域雪狼 2019 年 9 月 4 日
return dic;
}
//自定义的命令对象类
public class CommandModel
{
public string Name { get; set; }
public string DisplayName { get; set; } = "";
public string Description { get; set; } = "";
public string AssemblyName { get; set; } = "";
public string ClassName { get; set; } = "";
public string MethodName { get; set; } = "";
///
/// 图标名称
///
public string ImageName { get; set; } = "";
///
/// 命令的显示方式
///
public CommandDisplayStyle DisplayStyle { get; set; } = CommandDisplayStyle.图标文本;
///
/// 指示是否显示为大图标
///
public bool ShowLargeImage { get; set; } = false;
///
/// 指示在当前命令之后是否显示分隔符
///
C#二次开发 AutoCAD 动态加载自定义菜单和命令 西域雪狼 2019 年 9 月 4 日
public bool ShowSeparator { get; set; } = false;
///
/// 指示当前命令是否可用
///
public bool Enabled { get; set; } = true;
public enum CommandDisplayStyle
{
仅文本 = 0,
仅图标 = 1,
图标文本 = 2
}
}
3, 实现加载界面中菜单的方法
额外需要引用的dll
AcWindows.dll(在AutoCAD安装目录下可找到)
AdWindows.dll(在AutoCAD安装目录下可找到)
PresentationFramework.dll(系统dll,可自动引用过来)
额外需要引用的命名空间
using System.Collections.Generic;
using Autodesk.Windows;
C#二次开发 AutoCAD 动态加载自定义菜单和命令 西域雪狼 2019 年 9 月 4 日
using Autodesk.AutoCAD.Ribbon;
using System.Drawing;
using System.Windows.Media.Imaging;
using System.Drawing.Imaging;
///
/// 加载菜单
///
private static void loadUserMenu()
{
var id = "MyCADMenu";//面板ID
var ribbonTab = RibbonServices.RibbonPaletteSet.RibbonControl.Tabs.FirstOrDefault(s => s.Id == id);//面板对象
if (ribbonTab == null)
{
}
ribbonTab = new RibbonTab() { Id = id };
RibbonServices.RibbonPaletteSet.RibbonControl.Tabs.Add(ribbonTab);
ribbonTab.Title = "CAD二次开发";//面板标题
ribbonTab.Panels.Clear();
var commands = readConfigCommands();//读取所有配置的命令
//过滤出所有的命令可用的命令,并根据类型分组
var groups = commands.Where(s => s.Value.Where(m => m.Enabled).Count() > 0).ToDictionary(s => s.Key, s => s.Value.Where(m => m.Enabled).ToList());
foreach (var group in groups)
{
var panelSrc = new RibbonPanelSource();//新建一个子面板
C#二次开发 AutoCAD 动态加载自定义菜单和命令 西域雪狼 2019 年 9 月 4 日
panelSrc.Title = group.Key;//将子面板名称设置为分类名称,也即界面上看到的‘通用’,‘系统’
var panlRow = new RibbonRowPanel();//菜单行
foreach (var cmd in group.Value)
{
var button = new RibbonButton();//新建一个命令菜单按钮
button.CommandHandler = new CADCommandHandler();//设置读取菜单的触发命令对象,命令对象见后面类
button.CommandParameter = cmd;//设置菜单触发命令传入的参数
button.Text = cmd.DisplayName;//设置当前菜单的显示名称
button.Description = cmd.Description;//设置当前菜单的描述
//通过配置的参数,设置是否显示文本
button.ShowText = cmd.DisplayStyle == CommandModel.CommandDisplayStyle.仅文本 || cmd.DisplayStyle == CommandModel.CommandDisplayStyle.图标文本;
//通过配置的参数,设置是否显示图标
button.ShowImage = cmd.DisplayStyle == CommandModel.CommandDisplayStyle.仅图标 || cmd.DisplayStyle == CommandModel.CommandDisplayStyle.图标文本;
button.Size = cmd.ShowLargeImage ? RibbonItemSize.Large : RibbonItemSize.Standard;//设置当前命令是显示大图标还是小图标
button.Orientation = cmd.ShowLargeImage ? System.Windows.Controls.Orientation.Vertical : System.Windows.Controls.Orientation.Horizontal;
button.LargeImage =getBitmapImage(cmd.ImageName, new Size(32, 32)) ;//读取并设置已配置的命令大图标
button.Image = getBitmapImage(cmd.ImageName, new Size(16, 16));//读取并设置已配置的命令大图标
//大图标按钮的处理
if (cmd.ShowLargeImage)
{
if (panlRow.Items.Count > 0)
{
//将小图标组不满三行的,需要补齐。
while (panlRow.Items.OfType().Count() < 3)
{
panlRow.Items.Add(new RibbonButton() { ShowImage = false, ShowText = true, IsEnabled = false });
C#二次开发 AutoCAD 动态加载自定义菜单和命令 西域雪狼 2019 年 9 月 4 日
panlRow.Items.Add(new RibbonRowBreak());
}
panelSrc.Items.Add(panlRow);
}
panelSrc.Items.Add(button);
if (cmd.ShowSeparator)//判断是否需要在后面显示分割线,这里也是配置的参数
panelSrc.Items.Add(new RibbonSeparator());
panlRow = new RibbonRowPanel();
continue;
}
panlRow.Items.Add(button);
if (cmd.ShowSeparator)
panlRow.Items.Add(new RibbonSeparator());
panlRow.Items.Add(new RibbonRowBreak());
var buttonCount = panlRow.Items.OfType().Count();
if (buttonCount >= 3)
{
}
panelSrc.Items.Add(panlRow);
panlRow = new RibbonRowPanel();
//最后一组不满三行的需要补齐
if (group.Value.IndexOf(cmd) == group.Value.Count - 1)
{
while (buttonCount < 3)
{
panlRow.Items.Add(new RibbonButton() { ShowImage = false, ShowText = true, IsEnabled = false });
C#二次开发 AutoCAD 动态加载自定义菜单和命令 西域雪狼 2019 年 9 月 4 日
panlRow.Items.Add(new RibbonRowBreak());
buttonCount++;
}
panelSrc.Items.Add(panlRow);
panlRow = new RibbonRowPanel();
}
}
var panel = new RibbonPanel();
panel.Source = panelSrc;
ribbonTab.Panels.Add(panel);//将已创建的命令加载到面板中
}
}
///
/// 读取图片
///
///
///
///
private static BitmapImage getBitmapImage(string imagePath, Size? size)
{
var image = readImageFile(imagePath);
if (image == null)
return null;
if (size != null)
image = ConventHelper.ToImage(image, size.Value);