nslove44202489 发表于 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

nslove44202489 发表于 2019-4-27 09:12:42

之前的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;
            }
      }

    }








mycad 发表于 2019-6-12 17:17:27

页: [1]
查看完整版本: 利用反射加载注册表和添加菜单