明经CAD社区

 找回密码
 注册

QQ登录

只需一步,快速开始

搜索
查看: 4271|回复: 14

[运行时] .C#4.0 实现晚绑定来调用Com库

[复制链接]
发表于 2015-4-4 18:09 | 显示全部楼层 |阅读模式
本帖最后由 雪山飞狐_lzh 于 2015-4-4 18:45 编辑

  1. using System;
  2. using System.Collections.Generic;
  3. using System.ComponentModel;
  4. using System.Data;
  5. using System.Drawing;
  6. using System.Linq;
  7. using System.Text;
  8. using System.Windows.Forms;
  9. using System.Runtime.InteropServices;
  10. using System.Reflection;
  11. using stdole;

  12. namespace TlsCad.RunTime
  13. {
  14.     public partial class Form1 : Form
  15.     {
  16.         public Form1()
  17.         {

  18.             //获取当前AutoCAD实例
  19.             string pid = "AutoCad.Application";
  20.             dynamic app;
  21.             try
  22.             {
  23.                 app = Marshal.GetActiveObject(pid);
  24.             }
  25.             catch
  26.             {
  27.                 //如果没有就创建之
  28.                 Type t = Type.GetTypeFromProgID(pid);
  29.                 app = Activator.CreateInstance(t);
  30.                 app.Visible = true;
  31.             }

  32.             //获取当前文档
  33.             dynamic doc = app.ActiveDocument;

  34.             double[] p1 = { 0, 0, 0 };
  35.             double[] p2 = { 0, 10, 0 };
  36.             double[] p3 = { 10, 10, 0 };
  37.             double[] p4 = { 10, 0, 0 };

  38.             //Com对象数组必须封装为IDispatch数组
  39.             //注意应引用stdole.dll
  40.             IDispatch[] ents =
  41.             {
  42.                 doc.ModelSpace.AddLine(p1, p2),
  43.                 doc.ModelSpace.AddLine(p2, p3),
  44.                 doc.ModelSpace.AddLine(p3, p4),
  45.                 doc.ModelSpace.AddLine(p4, p1)
  46.             };

  47.             //测试生成面域
  48.             dynamic r = doc.ModelSpace.AddRegion(ents);
  49.             double[] min, max;
  50.             r[0].GetBoundingBox(out min, out max);
  51.             app.ZoomWindow(min, max);

  52.             InitializeComponent();

  53.         }
  54.     }
  55. }



 楼主| 发表于 2015-4-5 15:33 | 显示全部楼层
本帖最后由 雪山飞狐_lzh 于 2015-4-5 16:13 编辑


调试结果

ps:有没有朋友按4楼的方法 把其他版本cad的这两个dll贴上。。。

本帖子中包含更多资源

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

x
回复 支持 1 反对 0

使用道具 举报

发表于 2016-10-16 18:52 | 显示全部楼层
雪山飞狐_lzh 发表于 2015-4-5 14:53
变体参数的反射

Utiility类中大量的函数使用了变体。。。

能否帮忙将这个单个CAD版本的应用程序修改为适合多个CAD版本的应用程序,如2010,2013等版本,本人愿意支付一定的费用,联系QQ:1067426844。程序码如下:
  1. using System;
  2. using System.Collections.Generic;
  3. using System.ComponentModel;
  4. using System.Data;
  5. using System.Drawing;
  6. using System.Linq;
  7. using System.Text;
  8. using System.Windows.Forms;
  9. using Microsoft.VisualBasic;
  10. using Autodesk.AutoCAD.Interop;
  11. using Autodesk.AutoCAD.Interop.Common;

  12. namespace CAD二次开发
  13. {
  14.     public partial class Form1 : Form
  15.     {
  16.         public static Autodesk.AutoCAD.Interop.AcadApplication AcadApp;
  17.         public static Autodesk.AutoCAD.Interop.AcadDocument AcadDoc;
  18.         public Form1()
  19.         {
  20.             InitializeComponent();
  21.         }
  22.         public static void 启动CAD()
  23.         {
  24.             try
  25.             {
  26.                 AcadApp = (AcadApplication)System.Runtime.InteropServices.Marshal.GetActiveObject("AutoCAD.Application");
  27.                 AcadDoc = AcadApp.ActiveDocument;
  28.             }
  29.             catch
  30.             {
  31.                 AcadApp = new AcadApplication();
  32.                 AcadDoc = AcadApp.ActiveDocument;
  33.             }
  34.             AcadApp.Application.Visible = true;
  35.             Microsoft.VisualBasic.Interaction.AppActivate(AcadApp.Caption);
  36.         }

  37.         private void button1_Click(object sender, EventArgs e)
  38.         {
  39.             启动CAD();

  40.             double Ks =0;
  41.             double Ke = 2000;
  42.             double Dmax = 150;
  43.             double Dmin = -150;

  44.             string VerCAD = (AcadApp.Version.ToString()).Substring(0, 2);//获取AutoCAD版本号,从左边截取2位字符
  45.             AcadAcCmColor color1 = (AcadAcCmColor)AcadDoc.Application.GetInterfaceObject("AutoCAD.AcCmColor." + VerCAD);//新建一AcadAcCmColor对象,该对象用来给图形对象的颜色属性赋值
  46.             AcadLayer acLayer;
  47.             AcadText TextObj;

  48.             acLayer = AcadDoc.Layers.Add("中心线");
  49.             acLayer.color = AcColor.acYellow;
  50.             acLayer.Lineweight = ACAD_LWEIGHT.acLnWt025;

  51.             acLayer = AcadDoc.Layers.Add("文字标注");
  52.             acLayer.color = AcColor.acGreen;

  53.             acLayer = AcadDoc.Layers.Add("主网格");
  54.             color1.SetRGB(66, 112, 138);
  55.             acLayer.TrueColor = color1;
  56.             acLayer.Lineweight = ACAD_LWEIGHT.acLnWt015;

  57.             acLayer = AcadDoc.Layers.Add("副网格");
  58.             color1.SetRGB(95, 58, 69);
  59.             acLayer.TrueColor = color1;
  60.             acLayer.Lineweight = ACAD_LWEIGHT.acLnWt005;

  61.             double[] lineStartPoint = new Double[3];
  62.             double[] lineEndPoint = new Double[3];
  63.             double[] TextPoint = new Double[3];

  64.             //水平网格线
  65.             for (int i = Convert.ToInt32(Math.Ceiling(Dmin / 10)) * 10; i <= Math.Floor(Dmax / 10) * 10; i = i + 10)
  66.             {
  67.                 lineStartPoint[0] = Ks ; lineStartPoint[1] = i;
  68.                 lineEndPoint[0] = Ke ; lineEndPoint[1] = i;

  69.                 if (i % 50 == 0)
  70.                 {
  71.                     if (i == 0)
  72.                     {
  73.                         AcadDoc.ModelSpace.AddLine(lineStartPoint, lineEndPoint).Layer = "中心线";
  74.                     }
  75.                     else
  76.                     {
  77.                         AcadDoc.ModelSpace.AddLine(lineStartPoint, lineEndPoint).Layer = "主网格";
  78.                     }
  79.                 }
  80.                 else
  81.                 {
  82.                     AcadDoc.ModelSpace.AddLine(lineStartPoint, lineEndPoint).Layer = "副网格";
  83.                 }
  84.             }

  85.             //竖向网格线
  86.             for (int i = Convert.ToInt32(Math.Ceiling(Ks / 10)) * 10; i <= Math.Floor(Ke / 10) * 10; i = i + 10)
  87.             {
  88.                 lineStartPoint[0] = i ; lineStartPoint[1] = Math.Ceiling(Dmin / 10) * 10;
  89.                 lineEndPoint[0] = i ; lineEndPoint[1] = Math.Floor(Dmax / 10) * 10;

  90.                 if (i % 50 == 0)
  91.                 {
  92.                     AcadDoc.ModelSpace.AddLine(lineStartPoint, lineEndPoint).Layer = "主网格";
  93.                     if (i % 100 == 0)
  94.                     {
  95.                         //标注里程
  96.                         TextPoint[0] = i ; TextPoint[1] = Math.Ceiling(Dmin / 10) * 10 - 10;
  97.                         string strText;
  98.                         if (i % 1000 == 0)
  99.                         {
  100.                             strText = "K" + (i / 1000).ToString();
  101.                         }
  102.                         else
  103.                         {
  104.                             strText = ((i / 100) % 10).ToString();
  105.                         }
  106.                         TextObj = AcadDoc.ModelSpace.AddText(strText, TextPoint, 7.5);
  107.                         TextObj.Alignment = AcAlignment.acAlignmentMiddleCenter;//文本对齐方式
  108.                         TextObj.TextAlignmentPoint = TextPoint;
  109.                         TextObj.Layer = "文字标注";

  110.                         //标注拨量
  111.                         if (i % 1000 == 0)
  112.                         {
  113.                             for (int j = Convert.ToInt32(Math.Ceiling(Dmin / 50)) * 50; j <= Math.Floor(Dmax / 50) * 50; j = j + 50)
  114.                             {
  115.                                 TextPoint[0] = i  - 5; TextPoint[1] = j;
  116.                                 TextObj = AcadDoc.ModelSpace.AddText(j.ToString(), TextPoint, 7.5);
  117.                                 TextObj.Alignment = AcAlignment.acAlignmentMiddleRight;//文本对齐方式
  118.                                 TextObj.TextAlignmentPoint = TextPoint;                //文本对齐点
  119.                                 TextObj.Layer = "文字标注";
  120.                             }
  121.                         }
  122.                     }
  123.                 }

  124.             }

  125.             AcadDoc.ActiveLayer = AcadDoc.Layers.Add("0");//恢复0图层
  126.             AcadDoc.SendCommand("_z\ne\n");
  127.             AcadDoc.SendCommand("_regenall\n");//全部重生成模型

  128.             Microsoft.VisualBasic.Interaction.AppActivate(AcadApp.Caption);

  129.         }
  130.     }
  131. }
发表于 2018-5-1 09:17 | 显示全部楼层
飞狐大侠,你好。从你的帖子中学到了很多,非常感谢。
有一个问题请教 一下:使用C# COM,怎么调用sendcommand命令,实现两条直线trim的功能?(在sendcommand命令中,可以使用handent,但是无法使用list()),或者不用调用sendcommand,有无其它命令。
非常期待能获得你的指点。
 楼主| 发表于 2015-4-4 18:14 | 显示全部楼层
4.0使用dynamic确实大大的简化了反射的难度,唯一的问题是没有智能提示 O(∩_∩)O~
发表于 2015-4-4 20:52 | 显示全部楼层
不错,C#在com方面的介绍比起VB太少了,面域的示例正好参考
 楼主| 发表于 2015-4-5 14:53 | 显示全部楼层
本帖最后由 雪山飞狐_lzh 于 2015-4-5 15:20 编辑


变体参数的反射

Utiility类中大量的函数使用了变体。。。
比如GetEntity
如果直接使用下面的代码
dynamic util = doc.Utility;
util.GetEntity(out obj, out pt);
始终调用不了
下面的办法不知道是不是最好的,以AutoCad2008/2010为例
首先在项目中引用AutoCad Type和ObjuectDBX两个Com类型库
修改引用项目中两个dll的
嵌入互操作为false
复制本地为True
生成一次项目 在应用程序目录下出现这两个dll

Autodesk.AutoCAD.Interop.dll
Autodesk.AutoCAD.Interop.Common.dll
把它们Copy到相应的版本目录下
最后去除这两个引用,

  1.             string path = Assembly.GetExecutingAssembly().Location;
  2.             path = path.Substring(0, path.LastIndexOf("\\"));
  3.             string id = app.Version.Substring(0, 4);
  4.             Dictionary<string, string> vers =
  5.                 new Dictionary<string,string>
  6.                 {
  7.                     {"17.1", "2008"},
  8.                     {"18.0", "2010"},
  9.                 };

  10.             string file =
  11.                 string.Format(
  12.                     "{0}\\{1}\\Autodesk.AutoCAD.Interop.dll",
  13.                     path,
  14.                     vers[id]);
  15.             Assembly ass = Assembly.LoadFile(file);

  16.             dynamic util = doc.Utility;
  17.             Type utilType = ass.GetType("Autodesk.AutoCAD.Interop.IAcadUtility");
  18.             Object[] myArgs = new Object[3];
  19.             myArgs[2] = Type.Missing;
  20.             MethodInfo m = utilType.GetMethod("GetEntity");
  21.             m.Invoke(util, myArgs);

本帖子中包含更多资源

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

x
 楼主| 发表于 2015-4-5 18:10 | 显示全部楼层
本帖最后由 雪山飞狐_lzh 于 2015-4-5 21:17 编辑

可能的更好方法

  1. using System;
  2. using System.Collections.Generic;
  3. using System.ComponentModel;
  4. using System.Data;
  5. using System.Drawing;
  6. using System.Linq;
  7. using System.Text;
  8. using System.Windows.Forms;
  9. using System.Runtime.InteropServices;
  10. using System.Reflection;
  11. using System.IO;
  12. using stdole;
  13. using System.Text.RegularExpressions;
  14. using System.Collections;

  15. namespace TlsCad.RunTime
  16. {
  17.     public partial class Form1 : Form
  18.     {

  19.         [DllImport("user32.dll")]
  20.         static extern IntPtr SetActiveWindow(IntPtr hWnd);

  21.         [DllImport("user32.dll")]
  22.         static extern bool SetForegroundWindow(IntPtr hWnd);

  23.         public Form1()
  24.         {

  25.             InitializeComponent();

  26.             AcadX.Connection();
  27.             dynamic app = AcadX.Application;

  28.             //获取当前文档
  29.             dynamic doc = app.ActiveDocument;

  30.             double[] p1 = { 0, 0, 0 };
  31.             double[] p2 = { 0, 10, 0 };
  32.             double[] p3 = { 10, 10, 0 };
  33.             double[] p4 = { 10, 0, 0 };

  34.             //Com对象数组必须封装为IDispatch数组
  35.             //注意应引用stdole.dll
  36.             IDispatch[] ents =
  37.             {
  38.                 doc.ModelSpace.AddLine(p1, p2),
  39.                 doc.ModelSpace.AddLine(p2, p3),
  40.                 doc.ModelSpace.AddLine(p3, p4),
  41.                 doc.ModelSpace.AddLine(p4, p1)
  42.             };

  43.             //测试生成面域
  44.             dynamic r = doc.ModelSpace.AddRegion(ents);
  45.             double[] min, max;
  46.             r[0].GetBoundingBox(out min, out max);
  47.             app.ZoomWindow(min, max);

  48.             //测试Utility,或者var util = new AcadUtility(doc);
  49.             var util = new AcadX(".IAcadUtility", doc.Utility);
  50.             object[] args = new object[]{ null, null, Type.Missing };
  51.             if (util.Invoke("GetEntity", ref args))
  52.             {
  53.                
  54.                 dynamic obj = args[1];
  55.                 var pt = args[2] as double[];

  56.                 string info = string.Format("你选择了{0}实体", obj.ObjectName);
  57.                 info += string.Format("\n在{0},{1},{2}", pt.Cast<object>().ToArray());
  58.                 MessageBox.Show(info);

  59.             }

  60.         }

  61.     }

  62.     public class AcadX
  63.     {

  64.         public static dynamic Application
  65.         { private set; get; }

  66.         virtual protected string TypeName
  67.         {
  68.             get { return "Autodesk.AutoCAD.Interop"; }
  69.         }

  70.         protected static Assembly _assem
  71.         { private set; get; }

  72.         protected Type _type;
  73.         protected object _obj;

  74.         protected AcadX()
  75.         {
  76.            _type = _assem.GetType(TypeName);
  77.         }

  78.         public AcadX(string typeName, object obj)
  79.         {
  80.             _type = _assem.GetType(TypeName + typeName);
  81.             _obj = obj;
  82.         }

  83.         public bool Invoke(string methodName, ref object[] args)
  84.         {
  85.             
  86.             try
  87.             {

  88.                 MethodInfo mi = _type.GetMethod(methodName);
  89.                 List<object> lst = new List<object> { mi.Invoke(_obj, args) };

  90.                 var pars = mi.GetParameters();
  91.                 for(int i = 0; i< pars.Count(); i++)
  92.                 {
  93.                     if (pars.IsOut)
  94.                         lst.Add(args);
  95.                 }

  96.                 args = lst.ToArray();
  97.                 return true;

  98.             }
  99.             catch
  100.             {

  101.                 args = new object[0];
  102.                 return false;

  103.             }

  104.         }

  105.         public static void Connection()
  106.         {
  107.             //获取当前AutoCad实例
  108.             string pid = "AutoCad.Application";
  109.             try
  110.             {
  111.                 Application = Marshal.GetActiveObject(pid);
  112.             }
  113.             catch
  114.             {
  115.                 //如果没有就创建之
  116.                 Type t = Type.GetTypeFromProgID(pid);
  117.                 Application = Activator.CreateInstance(t);
  118.                 Application.Visible = true;
  119.             }

  120.             GetComAssembly(Application);

  121.         }

  122.         private static void GetComAssembly(dynamic app)
  123.         {
  124.             string id = app.Version.Substring(0, 4);
  125.             Dictionary<string, string> vers = new Dictionary<string, string>();

  126.             string vername = null;
  127.             DirectoryInfo di = new DirectoryInfo("C:\\windows\\assembly\\gac_msil\\Autodesk.AutoCAD.Interop");
  128.             var sdis = di.GetDirectories();
  129.             foreach (var sdi in sdis)
  130.             {
  131.                 if (sdi.Name.Contains(id))
  132.                 {
  133.                     vername = sdi.Name;
  134.                     break;
  135.                 }
  136.             }

  137.             var verinfos = Regex.Split(vername, "__");

  138.             _assem =
  139.                 Assembly.Load(
  140.                     string.Format(
  141.                         "Autodesk.AutoCAD.Interop, Version={0}, Culture=neutral, PublicKeyToken={1}",
  142.                         verinfos));
  143.         }

  144.     }

  145.     public class AcadUtility : AcadX
  146.     {

  147.         protected override string TypeName
  148.         {
  149.             get { return base.TypeName + ".IAcadUtility"; }
  150.         }

  151.         public AcadUtility(dynamic doc)
  152.         {
  153.             _obj = doc.Utility;
  154.         }

  155.         public dynamic Document
  156.         {
  157.             set { _obj = value.Utility; }
  158.         }

  159.     }


  160. }
发表于 2015-4-5 18:40 | 显示全部楼层
学习了
 楼主| 发表于 2015-4-5 21:01 | 显示全部楼层
优化代码 6楼已更新
发表于 2016-4-7 09:55 | 显示全部楼层
我把你的代码原样拷贝到一个新项目,执行的时候没有错误提示,但是只是画了一个正方形,并没有成功创建一个面域,请问是什么原因呢?
发表于 2016-4-9 16:40 | 显示全部楼层
有帮助学习一下
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

GMT+8, 2024-3-29 15:14 , Processed in 0.235582 second(s), 26 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

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