明经CAD社区

 找回密码
 注册

QQ登录

只需一步,快速开始

搜索
查看: 1949|回复: 2

[运行时] 利用反射加载注册表和添加菜单

[复制链接]
发表于 2019-3-17 13:43:57 | 显示全部楼层 |阅读模式
程序的注册表写到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

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?注册

x
 楼主| 发表于 2019-4-27 09:12:42 | 显示全部楼层
之前的menubar菜单对跨版本还是有限制,主要是com对象的前期绑定导致的。后期绑定有好麻烦。
采用ribbon选项卡和面板可以实现跨版本使用。大家不惜勿喷,主要为了适应跨版本,目前公司有买了2017,2019等,原来的2015也有保留。

1# 先定义一个特性

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Threading.Tasks;

  6. namespace AutoCADRibbon
  7. {
  8.     public class CmdHelperAttribute : Attribute
  9.     {
  10.         public string HelpContent { get; set; }
  11.         public string IcoFileName { get; set; }

  12.         // This is a positional argument
  13.         public CmdHelperAttribute(string _HelpString,string imageFilePath)
  14.         {
  15.             this.HelpContent = _HelpString;
  16.             this.IcoFileName = imageFilePath;
  17.         }
  18.     }
  19. }
2# 在autocad 注册命令的是否添加图标和帮助信息中
  1. using Autodesk.AutoCAD.ApplicationServices;
  2. using Autodesk.AutoCAD.Runtime;
  3. using System;
  4. using System.Collections.Generic;
  5. using System.IO;
  6. using System.Linq;
  7. using System.Reflection;
  8. using System.Text;
  9. using System.Threading.Tasks;

  10. namespace AutoCADRibbon
  11. {
  12.    public  class classFunction1
  13.     {
  14.         [CmdHelper("mto套料程序kkkkkkk","1.ico")]
  15.         [CommandMethod("mymto")]
  16.         public void mto套料()
  17.         {
  18.             Application.ShowAlertDialog("mto套料程序");
  19.         }
  20.         [CmdHelper("mto套料程序2jjjjjj", "3.ico")]
  21.         [CommandMethod("mymto2")]
  22.         public void mto套料2()
  23.         {
  24.             Application.ShowAlertDialog("mto套料程序8");
  25.         }
  26.         [CmdHelper("mto套料程序8jjjjjj", "3.ico")]
  27.         [CommandMethod("mymto8")]
  28.         public void mto套料8()
  29.         {
  30.             Application.ShowAlertDialog("mto套料程序8");
  31.         }
  32.     }
  33.     public class classFunction2
  34.     {
  35.         [CmdHelper("mto套料程序3jjjjjjj", "3.ico")]
  36.         [CommandMethod("mymto3")]
  37.         public void mto套料3()
  38.         {
  39.             Application.ShowAlertDialog("mto套料程序3");
  40.         }
  41.         [CmdHelper("mto套料程序41111111", "2.ico")]
  42.         [CommandMethod("mymto4")]
  43.         public void mto套料4()
  44.         {
  45.             Application.ShowAlertDialog("mto套料程序4");
  46.         }
  47.     }
  48.     public class classFunction3
  49.     {
  50.         [CmdHelper("mto套料程序5jjjjjjj", "1.ico")]
  51.         [CommandMethod("mymto5")]
  52.         public void mto套料5()
  53.         {
  54.             Application.ShowAlertDialog("mto套料程序5");
  55.         }
  56.         [CmdHelper("mto套料程序61111111", "2.ico")]
  57.         [CommandMethod("mymto6")]
  58.         public void mto套料6()
  59.         {
  60.             Application.ShowAlertDialog("mto套料程序6");
  61.         }
  62.     }
  63. }

3# 在程序启动是检测riibon的受否打开以及是否加载完毕
  1. public class MainClass : IExtensionApplication
  2.     {
  3.         public void Initialize()
  4.         {
  5.             helper.Register2HKCR();
  6.             Autodesk.Windows.ComponentManager.ItemInitialized += ComponentManager_ItemInitialized;
  7.         }

  8.         private void ComponentManager_ItemInitialized(object sender, RibbonItemEventArgs e)
  9.         {
  10.             if (Autodesk.Windows.ComponentManager.Ribbon == null)
  11.             {//如果Ribbon没有打开,直接操作命令行打开
  12.                 Application.DocumentManager.MdiActiveDocument.SendStringToExecute("_.ribbon\r", true, false, false);
  13.             }
  14.             else
  15.             {
  16.                 var cmd = helper.GetDllCmds(Assembly.GetExecutingAssembly().Location);
  17.                 helper.AddCmdtoRibbon(cmd);
  18.                 Autodesk.Windows.ComponentManager.ItemInitialized -= ComponentManager_ItemInitialized;
  19.             }
  20.         }

  21.         public void Terminate()
  22.         {
  23.             throw new NotImplementedException();
  24.         }
  25.     }

4#创建一些帮助类

  1. //为ribbon菜单指派事件
  2.     public class AdskCommonHandler : System.Windows.Input.ICommand
  3.     {
  4.         public event EventHandler CanExecuteChanged;

  5.         public bool CanExecute(object parameter)
  6.         {
  7.             return true;
  8.         }

  9.         public void Execute(object parameter)
  10.         {
  11.             RibbonButton button = parameter as RibbonButton;
  12.             if (button == null || button.CommandParameter == null) return;
  13.             Application.DocumentManager.MdiActiveDocument.SendStringToExecute((string)button.CommandParameter + " ", true, false, true);
  14.         }
  15.     }
  16.     public static class helper

  17.     {/// <summary>
  18.      ///提取所有的命令
  19.      /// </summary>
  20.      /// <param name="dllFiles">dll的路径</param>
  21.      /// <returns></returns>
  22.         public static List<gcadDllcmd> GetDllCmds(params string[] dllFiles)
  23.         {
  24.             List<gcadDllcmd> res = new List<gcadDllcmd>();
  25.             List<gcadCmds> cmds = new List<gcadCmds>();
  26.             #region 提取所以的命令
  27.             for (int i = 0; i < dllFiles.Length; i++)
  28.             {
  29.                 Assembly ass = Assembly.LoadFile(dllFiles[i]);//反射加载dll程序集
  30.                 var clsCollection = ass.GetTypes().Where(t => t.IsClass && t.IsPublic).ToList();
  31.                 if (clsCollection.Count > 0)
  32.                 {
  33.                     foreach (var cls in clsCollection)
  34.                     {
  35.                         var methods = cls.GetMethods().Where(m => m.IsPublic && m.GetCustomAttributes(true).Length > 0).ToList();
  36.                         if (methods.Count > 0)
  37.                         {
  38.                             foreach (MethodInfo mi in methods)
  39.                             {
  40.                                 var atts_CmdString = mi.GetCustomAttributes(true).Where(c => c is CommandMethodAttribute).ToList();
  41.                                 var atts_HelpString = mi.GetCustomAttributes(true).Where(c => c is CmdHelperAttribute).ToList();
  42.                                 if (atts_CmdString.Count == 1 && atts_HelpString.Count == 1)
  43.                                 {
  44.                                     gcadCmds cmd = new gcadCmds(cls.Name, mi.Name, (atts_CmdString[0] as CommandMethodAttribute).GlobalName,
  45.                                         ass.ManifestModule.Name.Substring(0, ass.ManifestModule.Name.Length - 4), (atts_HelpString[0] as CmdHelperAttribute).HelpContent, (atts_HelpString[0] as CmdHelperAttribute).IcoFileName);
  46.                                     cmds.Add(cmd);
  47.                                 }
  48.                             }
  49.                         }
  50.                     }
  51.                 }
  52.             }
  53.             #endregion
  54.             if (cmds.Count > 0)
  55.             {
  56.                 List<string> dllName = new List<string>();
  57.                 foreach (var item in cmds) if (!dllName.Contains(item.dllName)) dllName.Add(item.dllName);
  58.                 foreach (var item in dllName) res.Add(new gcadDllcmd(item, cmds));
  59.             }
  60.             return res;
  61.             //
  62.         }
  63.         public static void AddCmdtoRibbon(List<gcadDllcmd> cmds)
  64.         {
  65.             RibbonControl ribbon = ComponentManager.Ribbon;
  66.             if (ribbon != null)
  67.             {
  68.                 foreach (var dll in cmds)
  69.                 {
  70.                     RibbonTab rtab = ribbon.FindTab(dll.DllName);
  71.                     if (rtab != null) ribbon.Tabs.Remove(rtab);
  72.                     rtab = new RibbonTab()
  73.                     {
  74.                         Title = dll.DllName,
  75.                         Id = dll.DllName,
  76.                         IsVisible = true
  77.                     };
  78.                     //Add the Tab
  79.                     ribbon.Tabs.Add(rtab);
  80.                     //added the panels
  81.                     foreach (var item in dll.clsCmds)
  82.                     {
  83.                         RibbonPanelSource rps = new RibbonPanelSource() { Title = item.clsName };
  84.                         RibbonPanel rp = new RibbonPanel()
  85.                         {
  86.                             Source = rps,
  87.                             IsVisible = true,
  88.                             ResizeStyle = RibbonResizeStyles.NeverHideText,
  89.                             AnimationMode = Autodesk.Internal.Windows.RibbonPanelAnimationMode.None
  90.                         };
  91.                         RibbonSubPanelSource psps = new RibbonSubPanelSource() { Name = item.clsName, Id = item.clsName };
  92.                         RibbonRowPanel rrp = new RibbonRowPanel()
  93.                         {
  94.                             Source = psps,
  95.                             IsEnabled = true,
  96.                             IsVisible = true,
  97.                             SubPanelResizeStyle = RibbonRowPanelResizeStyle.NeverHideText,
  98.                             ResizeStyle = RibbonItemResizeStyles.ResizeWidth
  99.                         };
  100.                         //int i = 0;
  101.                         foreach (var clsCmd in item.curClscmds)
  102.                         {
  103.                             RibbonButton rb = new RibbonButton()
  104.                             {
  105.                                 Text = clsCmd.cmdName,
  106.                                 ShowText = true,
  107.                                 ShowImage = true,
  108.                                 AllowInToolBar = true,
  109.                                 AllowInStatusBar = true,
  110.                                 Description = clsCmd.HelpeText,
  111.                                 Orientation = System.Windows.Controls.Orientation.Vertical,
  112.                                 CommandParameter = clsCmd.cmdMacro
  113.                             };
  114.                             if (File.Exists(clsCmd.IcnoName))
  115.                             {
  116.                                 rb.Image = Images.getBitmap(new Bitmap(clsCmd.IcnoName));
  117.                                 rb.Size = RibbonItemSize.Large;
  118.                                 rb.LargeImage = Images.getBitmap(new Bitmap(clsCmd.IcnoName));
  119.                             }
  120.                             rb.CommandHandler = new AdskCommonHandler();
  121.                             psps.Items.Add(rb);
  122.                             //i++;
  123.                             //if (i >= 2)
  124.                             //{
  125.                             //    rps.Items.Add(new RibbonPanelBreak() { IsVisible = true });
  126.                             //    i = 0;
  127.                             //}
  128.                         }
  129.                         rps.Items.Add(rrp);
  130.                         rtab.Panels.Add(rp);
  131.                     }

  132.                 }
  133.             }

  134.         }

  135.         /// <summary>
  136.         /// 将菜单加载到AutoCAD
  137.         /// </summary>
  138.         public static void Register2HKCR()
  139.         {
  140.             string hkcrKey = HostApplicationServices.Current.UserRegistryProductRootKey;
  141.             var assName = Assembly.GetExecutingAssembly().CodeBase;
  142.             var apps_Acad = Microsoft.Win32.Registry.CurrentUser.CreateSubKey(Path.Combine(hkcrKey, "Applications"));
  143.             if (apps_Acad.GetSubKeyNames().Count(c => c == Path.GetFileNameWithoutExtension(assName)) == 0)
  144.             {
  145.                 var myNetLoader = apps_Acad.CreateSubKey(Path.GetFileNameWithoutExtension(assName), RegistryKeyPermissionCheck.Default);
  146.                 myNetLoader.SetValue("DESCRIPTION", "加载自定义dll文件", Microsoft.Win32.RegistryValueKind.String);
  147.                 myNetLoader.SetValue("LOADCTRLS", 2, Microsoft.Win32.RegistryValueKind.DWord);
  148.                 myNetLoader.SetValue("LOADER", assName, Microsoft.Win32.RegistryValueKind.String);
  149.                 myNetLoader.SetValue("MANAGED", 1, Microsoft.Win32.RegistryValueKind.DWord);
  150.                 Application.ShowAlertDialog(Path.GetFileNameWithoutExtension(assName) + "程序加载成功!欢迎使用");
  151.             }

  152.         }
  153.         public class gcadCmds
  154.         {
  155.             public string clsName { get; set; }
  156.             public string cmdName { get; set; }
  157.             public string cmdMacro { get; set; }
  158.             public string dllName { get; set; }
  159.             public string HelpeText { get; set; }

  160.             public string IcnoName { get; set; }

  161.             public gcadCmds(string _clsName, string _cmdName, string _macro, string _dllName, string _helperText, string _iamgeName)
  162.             {
  163.                 this.dllName = _dllName;
  164.                 this.clsName = _clsName;
  165.                 this.cmdMacro = _macro;
  166.                 this.cmdName = _cmdName;
  167.                 this.HelpeText = _helperText;
  168.                 this.IcnoName = _iamgeName;
  169.             }

  170.         }
  171.         /// <summary>
  172.         /// 储存包含自定命令的类
  173.         /// </summary>
  174.         public class gcadClscmd
  175.         {
  176.             public string clsName { get; set; }

  177.             public string dllName { get; set; }

  178.             public bool HasGcadcmds { get; set; }

  179.             public List<gcadCmds> curClscmds { get; set; }

  180.             public gcadClscmd(string _clsName, List<gcadCmds> cmds)
  181.             {
  182.                 this.clsName = _clsName;
  183.                 this.dllName = cmds.First().dllName;
  184.                 var clsCmds = cmds.Where(c => c.clsName == this.clsName).ToList();
  185.                 if (clsCmds.Count > 0)
  186.                 {
  187.                     this.HasGcadcmds = true;
  188.                     this.curClscmds = new List<gcadCmds>();
  189.                     foreach (var item in clsCmds)
  190.                     {
  191.                         if (item.clsName == this.clsName) this.curClscmds.Add(item);
  192.                     }

  193.                 }
  194.                 else this.HasGcadcmds = false;
  195.             }
  196.         }
  197.         /// <summary>
  198.         /// 储存每个dll类的
  199.         /// </summary>
  200.         public class gcadDllcmd
  201.         {
  202.             public string DllName { get; set; }
  203.             public bool HasGcadcls { get; set; }
  204.             public List<gcadClscmd> clsCmds { get; set; }
  205.             public List<gcadCmds> curDllcmds { get; set; }
  206.             public gcadDllcmd(string _dllname, List<gcadCmds> cmds)
  207.             {
  208.                 this.DllName = _dllname;
  209.                 var curDllcmds = cmds.Where(c => c.dllName == this.DllName).ToList();
  210.                 if (curDllcmds.Count > 0)
  211.                 {
  212.                     this.HasGcadcls = true;
  213.                     this.curDllcmds = curDllcmds;
  214.                     List<string> listClsName = new List<string>();
  215.                     foreach (gcadCmds item in this.curDllcmds)
  216.                     {
  217.                         if (!listClsName.Contains(item.clsName)) listClsName.Add(item.clsName);
  218.                     }
  219.                     this.clsCmds = new List<gcadClscmd>();
  220.                     foreach (var item in listClsName)
  221.                     {
  222.                         gcadClscmd clsCmds = new gcadClscmd(item, this.curDllcmds.Where(c => c.clsName == item).ToList());
  223.                         this.clsCmds.Add(clsCmds);
  224.                     }

  225.                 }
  226.                 else this.HasGcadcls = false;
  227.             }


  228.         }

  229.         public class Images
  230.         {
  231.             public static BitmapImage getBitmap(Bitmap image)
  232.             {
  233.                 MemoryStream stream = new MemoryStream();
  234.                 image.Save(stream, ImageFormat.Png);
  235.                 BitmapImage bmp = new BitmapImage();
  236.                 bmp.BeginInit();
  237.                 bmp.StreamSource = stream;
  238.                 bmp.EndInit();
  239.                 return bmp;
  240.             }
  241.         }

  242.     }









您需要登录后才可以回帖 登录 | 注册

本版积分规则

小黑屋|手机版|CAD论坛|CAD教程|CAD下载|联系我们|关于明经|明经通道 ( 粤ICP备05003914号 )  
©2000-2023 明经通道 版权所有 本站代码,在未取得本站及作者授权的情况下,不得用于商业用途

GMT+8, 2024-11-25 06:40 , Processed in 0.162895 second(s), 23 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表