利用反射加载注册表和添加菜单
程序的注册表写到HKLM下,所以第一次加载需要用管理员权限打开cad。主要函数:
1# ====
''' <summary>
''' 提取当前程序集所有注册的AutoCAD命令信息
''' </summary>
''' <returns></returns>
Private Shared Function GetCueentAssemblyCmd() As Dictionary(Of String, List(Of String()))
Dim listCmd As Dictionary(Of String, List(Of String())) = New Dictionary(Of String, List(Of String()))
Dim currentAss = Assembly.GetExecutingAssembly()
Dim ed As Editor = Application.DocumentManager.MdiActiveDocument.Editor
'ed.WriteMessage(currentAss.FullName + Environment.NewLine)
For Each typeItem As Type In currentAss.GetTypes()
If typeItem.IsClass And typeItem.IsPublic Then
For Each method As MethodInfo In typeItem.GetMethods()
If method.IsPublic And method.GetCustomAttributes(True).Length > 0 Then
For Each att As Object In method.GetCustomAttributes(True)
If att.GetType().Name = GetType(CommandMethodAttribute).Name Then
Dim att_CommandMethod As CommandMethodAttribute = att
If listCmd.ContainsKey(typeItem.Name) Then
Dim dicTemp = listCmd(typeItem.Name)
dicTemp.Add(New String() {method.Name, att_CommandMethod.GlobalName})
listCmd(typeItem.Name) = dicTemp
Else
Dim listTemp As List(Of String()) = New List(Of String())
listTemp.Add(New String() {method.Name, att_CommandMethod.GlobalName})
listCmd(typeItem.Name) = listTemp
End If
End If
Next
End If
Next
End If
Next
Return listCmd
End Function
2#
''' <summary>
''' 将自定义的命令组合成菜单的形式
''' </summary>
''' <param name="listCmd"></param>
Private Shared Sub AddMenuBartoAutoCAD(listCmd As Dictionary(Of String, List(Of String())))
Dim acadApp As AcadApplication = Application.AcadApplication
Dim currentAssName = Assembly.GetExecutingAssembly().ManifestModule.Name.Substring(0, Assembly.GetExecutingAssembly().ManifestModule.Name.Length - 4)
For index = 0 To acadApp.MenuGroups.Item(0).Menus.Count - 1
Dim mg As AcadPopupMenu = acadApp.MenuGroups.Item(0).Menus.Item(index)
If mg.Name = currentAssName Then acadApp.MenuGroups.Item(0).Menus.Item(index).RemoveFromMenuBar()
Next
Dim mg_menuBar As AcadPopupMenu = acadApp.MenuGroups.Item(0).Menus.Add(currentAssName)
For Each item As KeyValuePair(Of String, List(Of String())) In listCmd
Dim submenu = mg_menuBar.AddSubMenu(mg_menuBar.Count + 1, item.Key)
For Each cmd As String() In item.Value
submenu.AddMenuItem(submenu.Count + 1, cmd(0), cmd(1) + " ")
Next
Next
mg_menuBar.InsertInMenuBar(acadApp.MenuBar.Count + 1)
End Sub
3#
''' <summary>
''' 写入注册表到HKLM
''' </summary>
Private Shared Sub DllAutoLoader()
Dim regPath As String = HostApplicationServices.Current.RegistryProductRootKey.Replace("Software", "SOFTWARE") 'Software\Autodesk\AutoCAD\R18.0\ACAD-8001:804
Dim ed As Editor = Application.DocumentManager.MdiActiveDocument.Editor
Dim assName = Assembly.GetExecutingAssembly().CodeBase
Dim apps_Acad = Registry.LocalMachine.OpenSubKey(Path.Combine(regPath, "Applications"), False)
Dim counts = apps_Acad.SubKeyCount, flag As Boolean = False
For Each item As String In apps_Acad.GetSubKeyNames()
If item = Path.GetFileNameWithoutExtension(assName) Then flag = True
Next
If flag = False Then
Dim autocad_App As RegistryKey
autocad_App = Registry.LocalMachine.OpenSubKey(Path.Combine(regPath, "Applications"), True) 'RegistryKeyPermissionCheck.ReadWriteSubTree, RegistryRights.FullControl
Dim myNerLoader = autocad_App.CreateSubKey(Path.GetFileNameWithoutExtension(assName), RegistryKeyPermissionCheck.Default)
myNerLoader.SetValue("DESCRIPTION", "加载自定义dll文件", Microsoft.Win32.RegistryValueKind.String)
myNerLoader.SetValue("LOADCTRLS", 2, Microsoft.Win32.RegistryValueKind.DWord)
myNerLoader.SetValue("LOADER", assName, Microsoft.Win32.RegistryValueKind.String)
myNerLoader.SetValue("MANAGED", 1, Microsoft.Win32.RegistryValueKind.DWord)
Application.ShowAlertDialog(Path.GetFileNameWithoutExtension(assName) + "程序自动加载完成,重启AutoCAD 生效!")
Else
Application.ShowAlertDialog(Path.GetFileNameWithoutExtension(assName) + "程序已经启动!欢迎使用")
End If
End Sub
4# 利用初始
<Assembly: ExtensionApplication(GetType(MainClass))>
Public Class MainClass
Implements IExtensionApplication
Public Sub Initialize() Implements IExtensionApplication.Initialize
Dim listCmd As Dictionary(Of String, List(Of String())) = GetCueentAssemblyCmd()
Call DllAutoLoader() 'Dll自动加载设置
Call AddMenuBartoAutoCAD(listCmd) '利用反射插入菜单
End Sub
end class
之前的menubar菜单对跨版本还是有限制,主要是com对象的前期绑定导致的。后期绑定有好麻烦。
采用ribbon选项卡和面板可以实现跨版本使用。大家不惜勿喷,主要为了适应跨版本,目前公司有买了2017,2019等,原来的2015也有保留。
1# 先定义一个特性
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace AutoCADRibbon
{
public class CmdHelperAttribute : Attribute
{
public string HelpContent { get; set; }
public string IcoFileName { get; set; }
// This is a positional argument
public CmdHelperAttribute(string _HelpString,string imageFilePath)
{
this.HelpContent = _HelpString;
this.IcoFileName = imageFilePath;
}
}
}2# 在autocad 注册命令的是否添加图标和帮助信息中
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.Runtime;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
namespace AutoCADRibbon
{
publicclass classFunction1
{
public void mto套料()
{
Application.ShowAlertDialog("mto套料程序");
}
public void mto套料2()
{
Application.ShowAlertDialog("mto套料程序8");
}
public void mto套料8()
{
Application.ShowAlertDialog("mto套料程序8");
}
}
public class classFunction2
{
public void mto套料3()
{
Application.ShowAlertDialog("mto套料程序3");
}
public void mto套料4()
{
Application.ShowAlertDialog("mto套料程序4");
}
}
public class classFunction3
{
public void mto套料5()
{
Application.ShowAlertDialog("mto套料程序5");
}
public void mto套料6()
{
Application.ShowAlertDialog("mto套料程序6");
}
}
}
3# 在程序启动是检测riibon的受否打开以及是否加载完毕
public class MainClass : IExtensionApplication
{
public void Initialize()
{
helper.Register2HKCR();
Autodesk.Windows.ComponentManager.ItemInitialized += ComponentManager_ItemInitialized;
}
private void ComponentManager_ItemInitialized(object sender, RibbonItemEventArgs e)
{
if (Autodesk.Windows.ComponentManager.Ribbon == null)
{//如果Ribbon没有打开,直接操作命令行打开
Application.DocumentManager.MdiActiveDocument.SendStringToExecute("_.ribbon\r", true, false, false);
}
else
{
var cmd = helper.GetDllCmds(Assembly.GetExecutingAssembly().Location);
helper.AddCmdtoRibbon(cmd);
Autodesk.Windows.ComponentManager.ItemInitialized -= ComponentManager_ItemInitialized;
}
}
public void Terminate()
{
throw new NotImplementedException();
}
}
4#创建一些帮助类
//为ribbon菜单指派事件
public class AdskCommonHandler : System.Windows.Input.ICommand
{
public event EventHandler CanExecuteChanged;
public bool CanExecute(object parameter)
{
return true;
}
public void Execute(object parameter)
{
RibbonButton button = parameter as RibbonButton;
if (button == null || button.CommandParameter == null) return;
Application.DocumentManager.MdiActiveDocument.SendStringToExecute((string)button.CommandParameter + " ", true, false, true);
}
}
public static class helper
{/// <summary>
///提取所有的命令
/// </summary>
/// <param name="dllFiles">dll的路径</param>
/// <returns></returns>
public static List<gcadDllcmd> GetDllCmds(params string[] dllFiles)
{
List<gcadDllcmd> res = new List<gcadDllcmd>();
List<gcadCmds> cmds = new List<gcadCmds>();
#region 提取所以的命令
for (int i = 0; i < dllFiles.Length; i++)
{
Assembly ass = Assembly.LoadFile(dllFiles);//反射加载dll程序集
var clsCollection = ass.GetTypes().Where(t => t.IsClass && t.IsPublic).ToList();
if (clsCollection.Count > 0)
{
foreach (var cls in clsCollection)
{
var methods = cls.GetMethods().Where(m => m.IsPublic && m.GetCustomAttributes(true).Length > 0).ToList();
if (methods.Count > 0)
{
foreach (MethodInfo mi in methods)
{
var atts_CmdString = mi.GetCustomAttributes(true).Where(c => c is CommandMethodAttribute).ToList();
var atts_HelpString = mi.GetCustomAttributes(true).Where(c => c is CmdHelperAttribute).ToList();
if (atts_CmdString.Count == 1 && atts_HelpString.Count == 1)
{
gcadCmds cmd = new gcadCmds(cls.Name, mi.Name, (atts_CmdString as CommandMethodAttribute).GlobalName,
ass.ManifestModule.Name.Substring(0, ass.ManifestModule.Name.Length - 4), (atts_HelpString as CmdHelperAttribute).HelpContent, (atts_HelpString as CmdHelperAttribute).IcoFileName);
cmds.Add(cmd);
}
}
}
}
}
}
#endregion
if (cmds.Count > 0)
{
List<string> dllName = new List<string>();
foreach (var item in cmds) if (!dllName.Contains(item.dllName)) dllName.Add(item.dllName);
foreach (var item in dllName) res.Add(new gcadDllcmd(item, cmds));
}
return res;
//
}
public static void AddCmdtoRibbon(List<gcadDllcmd> cmds)
{
RibbonControl ribbon = ComponentManager.Ribbon;
if (ribbon != null)
{
foreach (var dll in cmds)
{
RibbonTab rtab = ribbon.FindTab(dll.DllName);
if (rtab != null) ribbon.Tabs.Remove(rtab);
rtab = new RibbonTab()
{
Title = dll.DllName,
Id = dll.DllName,
IsVisible = true
};
//Add the Tab
ribbon.Tabs.Add(rtab);
//added the panels
foreach (var item in dll.clsCmds)
{
RibbonPanelSource rps = new RibbonPanelSource() { Title = item.clsName };
RibbonPanel rp = new RibbonPanel()
{
Source = rps,
IsVisible = true,
ResizeStyle = RibbonResizeStyles.NeverHideText,
AnimationMode = Autodesk.Internal.Windows.RibbonPanelAnimationMode.None
};
RibbonSubPanelSource psps = new RibbonSubPanelSource() { Name = item.clsName, Id = item.clsName };
RibbonRowPanel rrp = new RibbonRowPanel()
{
Source = psps,
IsEnabled = true,
IsVisible = true,
SubPanelResizeStyle = RibbonRowPanelResizeStyle.NeverHideText,
ResizeStyle = RibbonItemResizeStyles.ResizeWidth
};
//int i = 0;
foreach (var clsCmd in item.curClscmds)
{
RibbonButton rb = new RibbonButton()
{
Text = clsCmd.cmdName,
ShowText = true,
ShowImage = true,
AllowInToolBar = true,
AllowInStatusBar = true,
Description = clsCmd.HelpeText,
Orientation = System.Windows.Controls.Orientation.Vertical,
CommandParameter = clsCmd.cmdMacro
};
if (File.Exists(clsCmd.IcnoName))
{
rb.Image = Images.getBitmap(new Bitmap(clsCmd.IcnoName));
rb.Size = RibbonItemSize.Large;
rb.LargeImage = Images.getBitmap(new Bitmap(clsCmd.IcnoName));
}
rb.CommandHandler = new AdskCommonHandler();
psps.Items.Add(rb);
//i++;
//if (i >= 2)
//{
// rps.Items.Add(new RibbonPanelBreak() { IsVisible = true });
// i = 0;
//}
}
rps.Items.Add(rrp);
rtab.Panels.Add(rp);
}
}
}
}
/// <summary>
/// 将菜单加载到AutoCAD
/// </summary>
public static void Register2HKCR()
{
string hkcrKey = HostApplicationServices.Current.UserRegistryProductRootKey;
var assName = Assembly.GetExecutingAssembly().CodeBase;
var apps_Acad = Microsoft.Win32.Registry.CurrentUser.CreateSubKey(Path.Combine(hkcrKey, "Applications"));
if (apps_Acad.GetSubKeyNames().Count(c => c == Path.GetFileNameWithoutExtension(assName)) == 0)
{
var myNetLoader = apps_Acad.CreateSubKey(Path.GetFileNameWithoutExtension(assName), RegistryKeyPermissionCheck.Default);
myNetLoader.SetValue("DESCRIPTION", "加载自定义dll文件", Microsoft.Win32.RegistryValueKind.String);
myNetLoader.SetValue("LOADCTRLS", 2, Microsoft.Win32.RegistryValueKind.DWord);
myNetLoader.SetValue("LOADER", assName, Microsoft.Win32.RegistryValueKind.String);
myNetLoader.SetValue("MANAGED", 1, Microsoft.Win32.RegistryValueKind.DWord);
Application.ShowAlertDialog(Path.GetFileNameWithoutExtension(assName) + "程序加载成功!欢迎使用");
}
}
public class gcadCmds
{
public string clsName { get; set; }
public string cmdName { get; set; }
public string cmdMacro { get; set; }
public string dllName { get; set; }
public string HelpeText { get; set; }
public string IcnoName { get; set; }
public gcadCmds(string _clsName, string _cmdName, string _macro, string _dllName, string _helperText, string _iamgeName)
{
this.dllName = _dllName;
this.clsName = _clsName;
this.cmdMacro = _macro;
this.cmdName = _cmdName;
this.HelpeText = _helperText;
this.IcnoName = _iamgeName;
}
}
/// <summary>
/// 储存包含自定命令的类
/// </summary>
public class gcadClscmd
{
public string clsName { get; set; }
public string dllName { get; set; }
public bool HasGcadcmds { get; set; }
public List<gcadCmds> curClscmds { get; set; }
public gcadClscmd(string _clsName, List<gcadCmds> cmds)
{
this.clsName = _clsName;
this.dllName = cmds.First().dllName;
var clsCmds = cmds.Where(c => c.clsName == this.clsName).ToList();
if (clsCmds.Count > 0)
{
this.HasGcadcmds = true;
this.curClscmds = new List<gcadCmds>();
foreach (var item in clsCmds)
{
if (item.clsName == this.clsName) this.curClscmds.Add(item);
}
}
else this.HasGcadcmds = false;
}
}
/// <summary>
/// 储存每个dll类的
/// </summary>
public class gcadDllcmd
{
public string DllName { get; set; }
public bool HasGcadcls { get; set; }
public List<gcadClscmd> clsCmds { get; set; }
public List<gcadCmds> curDllcmds { get; set; }
public gcadDllcmd(string _dllname, List<gcadCmds> cmds)
{
this.DllName = _dllname;
var curDllcmds = cmds.Where(c => c.dllName == this.DllName).ToList();
if (curDllcmds.Count > 0)
{
this.HasGcadcls = true;
this.curDllcmds = curDllcmds;
List<string> listClsName = new List<string>();
foreach (gcadCmds item in this.curDllcmds)
{
if (!listClsName.Contains(item.clsName)) listClsName.Add(item.clsName);
}
this.clsCmds = new List<gcadClscmd>();
foreach (var item in listClsName)
{
gcadClscmd clsCmds = new gcadClscmd(item, this.curDllcmds.Where(c => c.clsName == item).ToList());
this.clsCmds.Add(clsCmds);
}
}
else this.HasGcadcls = false;
}
}
public class Images
{
public static BitmapImage getBitmap(Bitmap image)
{
MemoryStream stream = new MemoryStream();
image.Save(stream, ImageFormat.Png);
BitmapImage bmp = new BitmapImage();
bmp.BeginInit();
bmp.StreamSource = stream;
bmp.EndInit();
return bmp;
}
}
}
页:
[1]