.C#4.0 实现晚绑定来调用Com库
本帖最后由 雪山飞狐_lzh 于 2015-4-4 18:45 编辑using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.Reflection;
using stdole;
namespace TlsCad.RunTime
{
public partial class Form1 : Form
{
public Form1()
{
//获取当前AutoCad实例
string pid = "AutoCad.Application";
dynamic app;
try
{
app = Marshal.GetActiveObject(pid);
}
catch
{
//如果没有就创建之
Type t = Type.GetTypeFromProgID(pid);
app = Activator.CreateInstance(t);
app.Visible = true;
}
//获取当前文档
dynamic doc = app.ActiveDocument;
double[] p1 = { 0, 0, 0 };
double[] p2 = { 0, 10, 0 };
double[] p3 = { 10, 10, 0 };
double[] p4 = { 10, 0, 0 };
//Com对象数组必须封装为IDispatch数组
//注意应引用stdole.dll
IDispatch[] ents =
{
doc.ModelSpace.AddLine(p1, p2),
doc.ModelSpace.AddLine(p2, p3),
doc.ModelSpace.AddLine(p3, p4),
doc.ModelSpace.AddLine(p4, p1)
};
//测试生成面域
dynamic r = doc.ModelSpace.AddRegion(ents);
double[] min, max;
r.GetBoundingBox(out min, out max);
app.ZoomWindow(min, max);
InitializeComponent();
}
}
}
本帖最后由 雪山飞狐_lzh 于 2015-4-5 16:13 编辑
调试结果
ps:有没有朋友按4楼的方法 把其他版本cad的这两个dll贴上。。。
雪山飞狐_lzh 发表于 2015-4-5 14:53
变体参数的反射
Utiility类中大量的函数使用了变体。。。
能否帮忙将这个单个CAD版本的应用程序修改为适合多个CAD版本的应用程序,如2010,2013等版本,本人愿意支付一定的费用,联系QQ:1067426844。程序码如下:using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Microsoft.VisualBasic;
using Autodesk.AutoCAD.Interop;
using Autodesk.AutoCAD.Interop.Common;
namespace CAD二次开发
{
public partial class Form1 : Form
{
public static Autodesk.AutoCAD.Interop.AcadApplication AcadApp;
public static Autodesk.AutoCAD.Interop.AcadDocument AcadDoc;
public Form1()
{
InitializeComponent();
}
public static void 启动CAD()
{
try
{
AcadApp = (AcadApplication)System.Runtime.InteropServices.Marshal.GetActiveObject("AutoCAD.Application");
AcadDoc = AcadApp.ActiveDocument;
}
catch
{
AcadApp = new AcadApplication();
AcadDoc = AcadApp.ActiveDocument;
}
AcadApp.Application.Visible = true;
Microsoft.VisualBasic.Interaction.AppActivate(AcadApp.Caption);
}
private void button1_Click(object sender, EventArgs e)
{
启动CAD();
double Ks =0;
double Ke = 2000;
double Dmax = 150;
double Dmin = -150;
string VerCAD = (AcadApp.Version.ToString()).Substring(0, 2);//获取AutoCAD版本号,从左边截取2位字符
AcadAcCmColor color1 = (AcadAcCmColor)AcadDoc.Application.GetInterfaceObject("AutoCAD.AcCmColor." + VerCAD);//新建一AcadAcCmColor对象,该对象用来给图形对象的颜色属性赋值
AcadLayer acLayer;
AcadText TextObj;
acLayer = AcadDoc.Layers.Add("中心线");
acLayer.color = AcColor.acYellow;
acLayer.Lineweight = ACAD_LWEIGHT.acLnWt025;
acLayer = AcadDoc.Layers.Add("文字标注");
acLayer.color = AcColor.acGreen;
acLayer = AcadDoc.Layers.Add("主网格");
color1.SetRGB(66, 112, 138);
acLayer.TrueColor = color1;
acLayer.Lineweight = ACAD_LWEIGHT.acLnWt015;
acLayer = AcadDoc.Layers.Add("副网格");
color1.SetRGB(95, 58, 69);
acLayer.TrueColor = color1;
acLayer.Lineweight = ACAD_LWEIGHT.acLnWt005;
double[] lineStartPoint = new Double;
double[] lineEndPoint = new Double;
double[] TextPoint = new Double;
//水平网格线
for (int i = Convert.ToInt32(Math.Ceiling(Dmin / 10)) * 10; i <= Math.Floor(Dmax / 10) * 10; i = i + 10)
{
lineStartPoint = Ks ; lineStartPoint = i;
lineEndPoint = Ke ; lineEndPoint = i;
if (i % 50 == 0)
{
if (i == 0)
{
AcadDoc.ModelSpace.AddLine(lineStartPoint, lineEndPoint).Layer = "中心线";
}
else
{
AcadDoc.ModelSpace.AddLine(lineStartPoint, lineEndPoint).Layer = "主网格";
}
}
else
{
AcadDoc.ModelSpace.AddLine(lineStartPoint, lineEndPoint).Layer = "副网格";
}
}
//竖向网格线
for (int i = Convert.ToInt32(Math.Ceiling(Ks / 10)) * 10; i <= Math.Floor(Ke / 10) * 10; i = i + 10)
{
lineStartPoint = i ; lineStartPoint = Math.Ceiling(Dmin / 10) * 10;
lineEndPoint = i ; lineEndPoint = Math.Floor(Dmax / 10) * 10;
if (i % 50 == 0)
{
AcadDoc.ModelSpace.AddLine(lineStartPoint, lineEndPoint).Layer = "主网格";
if (i % 100 == 0)
{
//标注里程
TextPoint = i ; TextPoint = Math.Ceiling(Dmin / 10) * 10 - 10;
string strText;
if (i % 1000 == 0)
{
strText = "K" + (i / 1000).ToString();
}
else
{
strText = ((i / 100) % 10).ToString();
}
TextObj = AcadDoc.ModelSpace.AddText(strText, TextPoint, 7.5);
TextObj.Alignment = AcAlignment.acAlignmentMiddleCenter;//文本对齐方式
TextObj.TextAlignmentPoint = TextPoint;
TextObj.Layer = "文字标注";
//标注拨量
if (i % 1000 == 0)
{
for (int j = Convert.ToInt32(Math.Ceiling(Dmin / 50)) * 50; j <= Math.Floor(Dmax / 50) * 50; j = j + 50)
{
TextPoint = i- 5; TextPoint = j;
TextObj = AcadDoc.ModelSpace.AddText(j.ToString(), TextPoint, 7.5);
TextObj.Alignment = AcAlignment.acAlignmentMiddleRight;//文本对齐方式
TextObj.TextAlignmentPoint = TextPoint; //文本对齐点
TextObj.Layer = "文字标注";
}
}
}
}
}
AcadDoc.ActiveLayer = AcadDoc.Layers.Add("0");//恢复0图层
AcadDoc.SendCommand("_z\ne\n");
AcadDoc.SendCommand("_regenall\n");//全部重生成模型
Microsoft.VisualBasic.Interaction.AppActivate(AcadApp.Caption);
}
}
}
飞狐大侠,你好。从你的帖子中学到了很多,非常感谢。
有一个问题请教 一下:使用C# COM,怎么调用sendcommand命令,实现两条直线trim的功能?(在sendcommand命令中,可以使用handent,但是无法使用list()),或者不用调用sendcommand,有无其它命令。
非常期待能获得你的指点。 4.0使用dynamic确实大大的简化了反射的难度,唯一的问题是没有智能提示 O(∩_∩)O~ 不错,C#在com方面的介绍比起VB太少了,面域的示例正好参考 本帖最后由 雪山飞狐_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到相应的版本目录下
最后去除这两个引用,
string path = Assembly.GetExecutingAssembly().Location;
path = path.Substring(0, path.LastIndexOf("\\"));
string id = app.Version.Substring(0, 4);
Dictionary<string, string> vers =
new Dictionary<string,string>
{
{"17.1", "2008"},
{"18.0", "2010"},
};
string file =
string.Format(
"{0}\\{1}\\Autodesk.AutoCAD.Interop.dll",
path,
vers);
Assembly ass = Assembly.LoadFile(file);
dynamic util = doc.Utility;
Type utilType = ass.GetType("Autodesk.AutoCAD.Interop.IAcadUtility");
Object[] myArgs = new Object;
myArgs = Type.Missing;
MethodInfo m = utilType.GetMethod("GetEntity");
m.Invoke(util, myArgs);
本帖最后由 雪山飞狐_lzh 于 2015-4-5 21:17 编辑
可能的更好方法
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.Reflection;
using System.IO;
using stdole;
using System.Text.RegularExpressions;
using System.Collections;
namespace TlsCad.RunTime
{
public partial class Form1 : Form
{
static extern IntPtr SetActiveWindow(IntPtr hWnd);
static extern bool SetForegroundWindow(IntPtr hWnd);
public Form1()
{
InitializeComponent();
AcadX.Connection();
dynamic app = AcadX.Application;
//获取当前文档
dynamic doc = app.ActiveDocument;
double[] p1 = { 0, 0, 0 };
double[] p2 = { 0, 10, 0 };
double[] p3 = { 10, 10, 0 };
double[] p4 = { 10, 0, 0 };
//Com对象数组必须封装为IDispatch数组
//注意应引用stdole.dll
IDispatch[] ents =
{
doc.ModelSpace.AddLine(p1, p2),
doc.ModelSpace.AddLine(p2, p3),
doc.ModelSpace.AddLine(p3, p4),
doc.ModelSpace.AddLine(p4, p1)
};
//测试生成面域
dynamic r = doc.ModelSpace.AddRegion(ents);
double[] min, max;
r.GetBoundingBox(out min, out max);
app.ZoomWindow(min, max);
//测试Utility,或者var util = new AcadUtility(doc);
var util = new AcadX(".IAcadUtility", doc.Utility);
object[] args = new object[]{ null, null, Type.Missing };
if (util.Invoke("GetEntity", ref args))
{
dynamic obj = args;
var pt = args as double[];
string info = string.Format("你选择了{0}实体", obj.ObjectName);
info += string.Format("\n在{0},{1},{2}", pt.Cast<object>().ToArray());
MessageBox.Show(info);
}
}
}
public class AcadX
{
public static dynamic Application
{ private set; get; }
virtual protected string TypeName
{
get { return "Autodesk.AutoCAD.Interop"; }
}
protected static Assembly _assem
{ private set; get; }
protected Type _type;
protected object _obj;
protected AcadX()
{
_type = _assem.GetType(TypeName);
}
public AcadX(string typeName, object obj)
{
_type = _assem.GetType(TypeName + typeName);
_obj = obj;
}
public bool Invoke(string methodName, ref object[] args)
{
try
{
MethodInfo mi = _type.GetMethod(methodName);
List<object> lst = new List<object> { mi.Invoke(_obj, args) };
var pars = mi.GetParameters();
for(int i = 0; i< pars.Count(); i++)
{
if (pars.IsOut)
lst.Add(args);
}
args = lst.ToArray();
return true;
}
catch
{
args = new object;
return false;
}
}
public static void Connection()
{
//获取当前AutoCad实例
string pid = "AutoCad.Application";
try
{
Application = Marshal.GetActiveObject(pid);
}
catch
{
//如果没有就创建之
Type t = Type.GetTypeFromProgID(pid);
Application = Activator.CreateInstance(t);
Application.Visible = true;
}
GetComAssembly(Application);
}
private static void GetComAssembly(dynamic app)
{
string id = app.Version.Substring(0, 4);
Dictionary<string, string> vers = new Dictionary<string, string>();
string vername = null;
DirectoryInfo di = new DirectoryInfo("C:\\windows\\assembly\\gac_msil\\Autodesk.AutoCAD.Interop");
var sdis = di.GetDirectories();
foreach (var sdi in sdis)
{
if (sdi.Name.Contains(id))
{
vername = sdi.Name;
break;
}
}
var verinfos = Regex.Split(vername, "__");
_assem =
Assembly.Load(
string.Format(
"Autodesk.AutoCAD.Interop, Version={0}, Culture=neutral, PublicKeyToken={1}",
verinfos));
}
}
public class AcadUtility : AcadX
{
protected override string TypeName
{
get { return base.TypeName + ".IAcadUtility"; }
}
public AcadUtility(dynamic doc)
{
_obj = doc.Utility;
}
public dynamic Document
{
set { _obj = value.Utility; }
}
}
}
学习了 优化代码 6楼已更新 我把你的代码原样拷贝到一个新项目,执行的时候没有错误提示,但是只是画了一个正方形,并没有成功创建一个面域,请问是什么原因呢? 有帮助学习一下
页:
[1]
2