明经CAD社区

 找回密码
 注册

QQ登录

只需一步,快速开始

搜索
查看: 5069|回复: 11

[界面] netload时注册dll并加载局部cui

[复制链接]
发表于 2015-4-2 16:47:28 | 显示全部楼层 |阅读模式
本帖最后由 雪山飞狐_lzh 于 2015-4-3 12:49 编辑

自2006版本以后,cad的用户界面变成了cui/cuix,使用局部cui可以简单的加载界面要素,比如菜单、工具
但cui的加载一直没有提供NetApi的版本,而Com库提供的该功能,问题是Com库通常要加载组件,使跨版本成为问题
那么有办法简单解决这个问题吗,显然反射可以,下面的代码就是基于这个想法的实现
AxObject类, Com对象代理类,封装了属性设置/读取和函数调用

  1. using System;using System.Collections.Generic;
  2. using System.Linq;
  3. using System.Text;
  4. using System.Reflection;
  5. using Autodesk.AutoCAD.ApplicationServices;
  6. using Autodesk.AutoCAD.DatabaseServices;

  7. namespace TlsCad.Runtime
  8. {
  9.     public class AxObject
  10.     {

  11.         public static AxObject AcadApplication
  12.         {
  13.             get { return new AxObject(Application.AcadApplication); }
  14.         }

  15.         public static AxObject Preferences
  16.         {
  17.             get { return new AxObject(Application.Preferences); }
  18.         }

  19.         public object Object
  20.         { protected set; get; }

  21.         protected Type _type;

  22.         protected AxObject()
  23.         { }

  24.         public AxObject(DBObject obj)
  25.             : this(obj.AcadObject)
  26.         { }

  27.         public AxObject(object value)
  28.         {
  29.             Object = value;
  30.             _type = Type.GetTypeFromHandle(Type.GetTypeHandle(Object));
  31.         }

  32.         public AxObjectList AsList()
  33.         {
  34.             return new AxObjectList(Object, _type);
  35.         }

  36.         public AxObject GetProperty(string propertyName)
  37.         {
  38.             try
  39.             {
  40.                 object obj =
  41.                     _type.InvokeMember(
  42.                     propertyName,
  43.                     BindingFlags.GetProperty,
  44.                     null,
  45.                     Object,
  46.                     new object[0]);
  47.                 if (obj != null)
  48.                     return new AxObject(obj);
  49.             }
  50.             catch
  51.             { }

  52.             return null;

  53.         }

  54.         public void SetProperty(string propertyName, object value)
  55.         {
  56.             try
  57.             {
  58.                 _type.InvokeMember(
  59.                     propertyName,
  60.                     BindingFlags.SetProperty,
  61.                     null,
  62.                     Object,
  63.                     new object[] { value });
  64.             }
  65.             catch
  66.             { }
  67.         }

  68.         public AxObject Invoke(string methodName, params object[] args)
  69.         {
  70.             try
  71.             {
  72.                 object obj = _type.InvokeMember(methodName, BindingFlags.InvokeMethod, null, Object, args);
  73.                 if (obj != null)
  74.                     return new AxObject(obj);
  75.             }
  76.             catch
  77.             { }

  78.             return null;

  79.         }

  80.         public override string ToString()
  81.         {
  82.             return Object.ToString();
  83.         }

  84.     }
  85. }


AxObjectList类
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Collections;

  6. namespace TlsCad.Runtime
  7. {
  8.     public class AxObjectList : AxObject,IEnumerable<AxObject>
  9.     {


  10.         internal AxObjectList(object value, Type type)
  11.         {
  12.             Object = value;
  13.             _type = type;
  14.         }

  15.         public AxObject this[int index]
  16.         {
  17.             get { return this.Invoke("Item", index); }
  18.         }

  19.         public AxObject this[string name]
  20.         {
  21.             get { return this.Invoke("Item", name); }
  22.         }

  23.         public int Count
  24.         {
  25.             get { return (int)this.GetProperty("Count").Object; }
  26.         }

  27.         public void ForEach(Action<AxObject> action)
  28.         {
  29.             for (int i = 0; i < Count; i++)
  30.                 action(this.Invoke("Item", i));
  31.         }

  32.         public IEnumerator<AxObject> GetEnumerator()
  33.         {
  34.             for (int i = 0; i < Count; i++)
  35.                 yield return this.Invoke("Item", i);
  36.         }

  37.         IEnumerator IEnumerable.GetEnumerator()
  38.         {
  39.             for (int i = 0; i < Count; i++)
  40.                 yield return this.Invoke("Item", i);
  41.         }

  42.     }
  43. }


AutoRegAessem类,自动注册dll的简化类,改写自kean
  1. using System;
  2. using System.IO;
  3. using System.Linq;
  4. using System.Reflection;

  5. using Autodesk.AutoCAD.DatabaseServices;
  6. using Autodesk.AutoCAD.Runtime;
  7. using Microsoft.Win32;


  8. namespace TlsCad.Runtime
  9. {


  10.     public enum AssemLoadType
  11.     {
  12.         Startting = 2,
  13.         ByCommand = 12,
  14.         Disabled = 20
  15.     }

  16.     [Serializable]
  17.     public struct AssemInfo
  18.     {
  19.         /// <summary>
  20.         /// 注册名
  21.         /// </summary>
  22.         public string Name;

  23.         /// <summary>
  24.         /// 程序集全名
  25.         /// </summary>
  26.         public string Fullname;

  27.         /// <summary>
  28.         /// 程序集路径
  29.         /// </summary>
  30.         public string Loader;

  31.         /// <summary>
  32.         /// 加载方式
  33.         /// </summary>
  34.         public AssemLoadType LoadType;

  35.         /// <summary>
  36.         /// 程序集说明
  37.         /// </summary>
  38.         public string Description;

  39.     }

  40.     [Serializable]
  41.     public class Command : IComparable<Command>
  42.     {

  43.         public string GlobalName;
  44.         public string LocalizedName;
  45.         public string GroupName;

  46.         public string TypeName;
  47.         public string MethodName;

  48.         public string Description;

  49.         public Command() { }

  50.         public Command(string globalName)
  51.         {
  52.             GlobalName = globalName;
  53.         }

  54.         #region IComparable<Command> 成员

  55.         int IComparable<Command>.CompareTo(Command other)
  56.         {
  57.             return this.GlobalName.CompareTo(other.GlobalName);
  58.         }

  59.         #endregion

  60.     }

  61.     public abstract class AutoRegAssem : IExtensionApplication
  62.     {

  63.         private AssemInfo _info = new AssemInfo();

  64.         public static Assembly CurrAssembly
  65.         {
  66.             get { return Assembly.GetCallingAssembly(); }
  67.         }

  68.         public static string Location
  69.         {
  70.             get { return CurrAssembly.Location; }
  71.         }

  72.         public static string Path
  73.         {
  74.             get
  75.             {
  76.                 DirectoryInfo di = new DirectoryInfo(Location).Parent;
  77.                 string path = di.FullName;
  78.                 if (path.LastIndexOf('\\') != path.Length - 1)
  79.                     path += '\\';
  80.                 return path;
  81.             }
  82.         }

  83.         public AutoRegAssem()
  84.         {

  85.             Assembly assem = Assembly.GetCallingAssembly();
  86.             _info.Loader = assem.Location;
  87.             _info.Fullname = assem.FullName;
  88.             _info.Name = assem.GetName().Name;
  89.             _info.LoadType = AssemLoadType.Startting;

  90.             if (!SearchForReg())
  91.             {
  92.                 RegApp();
  93.             }

  94.         }


  95.         #region Reg

  96.         private RegistryKey GetAcAppKey()
  97.         {

  98.             RegistryKey ackey =
  99.                 Registry.CurrentUser.OpenSubKey(
  100.                     HostApplicationServices.Current.RegistryProductRootKey, true);

  101.             return ackey.CreateSubKey("Applications");

  102.         }

  103.         private bool SearchForReg()
  104.         {

  105.             RegistryKey appkey = GetAcAppKey();
  106.             var regApps = appkey.GetSubKeyNames();
  107.             return regApps.Contains(_info.Name);

  108.         }

  109.         public void RegApp()
  110.         {

  111.             RegistryKey appkey = GetAcAppKey();
  112.             RegistryKey rk = appkey.CreateSubKey(_info.Name);
  113.             rk.SetValue("DESCRIPTION", _info.Fullname, RegistryValueKind.String);
  114.             rk.SetValue("LOADCTRLS", _info.LoadType, RegistryValueKind.DWord);
  115.             rk.SetValue("LOADER", _info.Loader, RegistryValueKind.String);
  116.             rk.SetValue("MANAGED", 1, RegistryValueKind.DWord);
  117.             appkey.Close();

  118.         }

  119.         #endregion

  120.         

  121.         #region IExtensionApplication 成员

  122.         public abstract void Initialize();

  123.         public abstract void Terminate();

  124.         #endregion

  125.     }
  126. }


调用方式
  1. [assembly: ExtensionApplication(typeof(TlsCad.Parts.MyArx))]
  2. [assembly: CommandClass(typeof(TlsCad.Parts.MyArx))]

  3. namespace TlsCad.Parts
  4. {
  5.     class MyArx : AutoRegAssem
  6.     {

  7.         public override void Initialize()
  8.         {

  9.             var files = AxObject.Preferences.GetProperty("Files");
  10.             var oldPath = files.GetProperty("SupportPath").ToString();
  11.             if (!oldPath.ToLower().Contains(Path.ToLower()))
  12.                 files.SetProperty("SupportPath", oldPath + ";" + Path);

  13.             var acapp = AxObject.AcadApplication;
  14.             var groups = acapp.GetProperty("MenuGroups").AsList();
  15.             var cui = groups["TlsCad"];

  16.             if (cui == null)
  17.             {
  18.                 cui = groups.Invoke("Load", "TlsCad.cui");
  19.                 var menus = cui.GetProperty("Menus").AsList();
  20.                 foreach (var menu in menus)
  21.                 {
  22.                     menus.Invoke(
  23.                         "InsertMenuInMenuBar",
  24.                         menu.GetProperty("Name"),
  25.                         "");
  26.                 }
  27.             }

  28.             SystemManager.Editor.WriteMessage("\nTlsPart Loading!......");

  29.         }

  30.         public override void Terminate()
  31.         {

  32.         }

 楼主| 发表于 2015-4-2 18:10:11 | 显示全部楼层
本帖最后由 雪山飞狐_lzh 于 2015-4-3 07:42 编辑

二、Com集合的处理
让AxObject类继承IEnumerable接口,可以实现集合的遍历
修改如下

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Reflection;
  6. using Autodesk.AutoCAD.ApplicationServices;
  7. using Autodesk.AutoCAD.DatabaseServices;
  8. using System.Collections;

  9. namespace TlsCad.Runtime
  10. {
  11.     public class AxObject: IEnumerable<AxObject>
  12.     {

  13.         public static AxObject AcadApplication
  14.         {
  15.             get { return new AxObject(Application.AcadApplication); }
  16.         }

  17.         public static AxObject Preferences
  18.         {
  19.             get { return new AxObject(Application.Preferences); }
  20.         }

  21.         public object Value
  22.         { private set; get; }

  23.         Type _type;

  24.         public AxObject(DBObject obj) :this(obj.AcadObject)
  25.         {   }

  26.         public AxObject(object value)
  27.         {
  28.             Value = value;
  29.             _type = Type.GetTypeFromHandle(Type.GetTypeHandle(Value));
  30.         }

  31.         public AxObject GetProperty(string propertyName)
  32.         {
  33.             try
  34.             {
  35.                 object obj =
  36.                     _type.InvokeMember(
  37.                         propertyName,
  38.                         BindingFlags.GetProperty,
  39.                         null,
  40.                         Value,
  41.                         new object[0]);
  42.                 if (obj != null)
  43.                     return new AxObject(obj);
  44.             }
  45.             catch
  46.             { }

  47.             return null;

  48.         }

  49.         public void SetProperty(string propertyName, object value)
  50.         {
  51.             try
  52.             {
  53.                 _type.InvokeMember(
  54.                     propertyName,
  55.                     BindingFlags.SetProperty,
  56.                     null,
  57.                     Value,
  58.                     new object[] { value });
  59.             }
  60.             catch
  61.             { }
  62.         }

  63.         public AxObject Invoke(string methodName, params object[] args)
  64.         {
  65.             try
  66.             {
  67.                 object obj =
  68.                     _type.InvokeMember(
  69.                         methodName,
  70.                         BindingFlags.InvokeMethod,
  71.                         null,
  72.                         Value,
  73.                         args);
  74.                 if (obj != null)
  75.                     return new AxObject(obj);
  76.             }
  77.             catch
  78.             { }

  79.             return null;

  80.         }

  81.         public void ForEach(Action<AxObject> action)
  82.         {
  83.             int count = (int)this.GetProperty("Count").Value;
  84.             for (int i = 0; i < count; i++)
  85.                 action(this.Invoke("Item", i));
  86.         }

  87.         public IEnumerator<AxObject> GetEnumerator()
  88.         {
  89.             int count = (int)this.GetProperty("Count").Value;
  90.             for (int i = 0; i < count; i++)
  91.                 yield return this.Invoke("Item", i);
  92.         }

  93.         IEnumerator IEnumerable.GetEnumerator()
  94.         {
  95.             int count = (int)this.GetProperty("Count").Value;
  96.             for (int i = 0; i < count; i++)
  97.                 yield return this.Invoke("Item", i);
  98.         }
  99.     }
  100. }

调用代码如下修改
  1.             if (cui == null)
  2.             {
  3.                 cui = groups.Invoke("Load", "TlsCad.cui");
  4.                 var menus = cui.GetProperty("Menus");
  5.                 foreach (var menu in menus)
  6.                 {
  7.                     menus.Invoke(
  8.                         "InsertMenuInMenuBar",
  9.                         menu.GetProperty("Name").Value,
  10.                         "");
  11.                 }
  12.             }
 楼主| 发表于 2015-4-3 12:51:51 | 显示全部楼层
添加AxObjectList类以支持集合类,一楼代码已更新
发表于 2015-4-6 20:06:35 | 显示全部楼层
帮版主顶帖,好像.net版人气也很凋零
发表于 2015-5-9 22:07:55 | 显示全部楼层
我也顶,老大威武!
发表于 2015-5-9 22:42:03 | 显示全部楼层
顶,老大威武!
发表于 2015-5-9 23:45:32 | 显示全部楼层
本帖最后由 cheng5276 于 2015-5-9 23:47 编辑

老大,现碰到个问题,采用您这种方法,CUI是加载了,工具栏显示了,但是菜单不显示
                    var acapp = AxObject.AcadApplication;
                    var groups = acapp.GetProperty("MenuGroups").AsList();
                    var cui = groups["我的工具"];
                    if (cui == null)
                    {
                        cui = groups.Invoke("Load", "MyTool.cuix");
                        var menus = cui.GetProperty("Menus").AsList();
                        foreach (var menu in menus)
                        {
                            menus.Invoke( "InsertMenuInMenuBar",menu.GetProperty("Name"),"");
                        }

                    }

//没办法,只好模拟LISP的语句 (menucmd "p99=+我的工具.POP1") ,再次设置菜单项

                    string loadmenu = "(menucmd \"p99=+我的工具.POP1\") ";
                    Application.DocumentManager.MdiActiveDocument.SendStringToExecute(loadmenu, true, false, false);
虽然目前能够显示菜单了,但这种发送命令行的方式总是不太保险,很可能会出现执行不了的情况(如CAD未完全启动好,调用会失败)

请问老大,能直接用.net方法解决这个问题么;

发表于 2015-5-9 23:48:47 | 显示全部楼层
还有请教老大,用这种COM方法,如何直接加载LISP文件?
 楼主| 发表于 2015-5-9 23:57:06 来自手机 | 显示全部楼层
我的示例菜单应该是可以显示的 08 10 12 我都测试过
发表于 2015-5-10 22:49:02 | 显示全部楼层
其实用Autolisp加载很简单的...
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

GMT+8, 2024-11-25 10:50 , Processed in 0.211520 second(s), 25 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

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