乐筑天下

搜索
欢迎各位开发者和用户入驻本平台 尊重版权,从我做起,拒绝盗版,拒绝倒卖 签到、发布资源、邀请好友注册,可以获得银币 请注意保管好自己的密码,避免账户资金被盗
查看: 128|回复: 9

为.net程序集实现Com接口

[复制链接]

72

主题

2726

帖子

9

银币

社区元老

Rank: 75Rank: 75Rank: 75

铜币
3014
发表于 2009-12-12 20:55:00 | 显示全部楼层 |阅读模式
下面是一个简单的示例,
详细见
7楼
一、
新建一个类库项目:TlsCad.Curve
在AssemblyInfo.cs文件中修改:
[assembly: ComVisible(true)]
二、
添加引用:acdbmgd.dll,acmgd.dll
在Class1.cs中加入下列代码
  1. using Autodesk..ApplicationServices;
  2. using Autodesk.AutoCAD.EditorInput;
  3. using AcDb = Autodesk.AutoCAD.DatabaseServices;
  4. using Autodesk.AutoCAD.Runtime;
  5. using Autodesk.AutoCAD.Geometry;
  6. using System.Runtime.InteropServices;
  7. using System;
  8. using System.Collections.Generic;
  9. namespace TlsCad
  10. {
  11.     [ProgId("TlsCad.Curve")]
  12.     public class Curve
  13.     {
  14.         AcDb.ObjectId _id;
  15.         public void Set(object acadObj)
  16.         {
  17.             _id = AcDb.Entity.FromAcadObject(acadObj);
  18.         }
  19.         private AcDb.Curve acCurve
  20.         {
  21.             get
  22.             {
  23.                 AcDb.Database db = _id.Database;
  24.                 using (AcDb.Transaction tr = db.TransactionManager.StartTransaction())
  25.                 {
  26.                     return tr.GetObject(_id, AcDb.OpenMode.ForRead) as AcDb.Curve;
  27.                 }
  28.             }
  29.         }
  30.         public double StartParam
  31.         {
  32.             get
  33.             {
  34.                 return acCurve.StartParam;
  35.             }
  36.         }
  37.         public double EndParam
  38.         {
  39.             get
  40.             {
  41.                 return acCurve.EndParam;
  42.             }
  43.         }
  44.         public object GetClosestPointTo(object pnt, bool extend)
  45.         {
  46.             return acCurve.GetClosestPointTo(new Point3d((double[])pnt), extend).ToArray();
  47.         }
  48.         public double GetDistAtParam(double param)
  49.         {
  50.             return acCurve.GetDistanceAtParameter(param);
  51.         }
  52.         public double GetParamAtDist(double dist)
  53.         {
  54.             return acCurve.GetParameterAtDistance(dist);
  55.         }
  56.         public double GetParamAtPoint(object pnt)
  57.         {
  58.             return acCurve.GetParameterAtPoint(new Point3d((double[])pnt));
  59.         }
  60.         public double GetDistAtPoint(object pnt)
  61.         {
  62.             return acCurve.GetDistAtPoint(new Point3d((double[])pnt));
  63.         }
  64.         public object GetParamsByPoints(object pnts)
  65.         {
  66.             AcDb.Curve c = acCurve;
  67.             List pars = new List();
  68.             foreach (object pnt in (object[])pnts)
  69.             {
  70.                 pars.Add(c.GetParameterAtPoint(new Point3d((double[])pnt)));
  71.             }
  72.             return pars.ToArray();
  73.         }
  74.         public object SplitByParams(object pars)
  75.         {
  76.             AcDb.Database db = _id.Database;
  77.             List objs = new List();
  78.             using (Application.DocumentManager.MdiActiveDocument.LockDocument())
  79.             {
  80.                 using (AcDb.Transaction tr = db.TransactionManager.StartTransaction())
  81.                 {
  82.                     AcDb.Curve c = tr.GetObject(_id, AcDb.OpenMode.ForRead) as AcDb.Curve;
  83.                     AcDb.BlockTableRecord btr = tr.GetObject(c.OwnerId, AcDb.OpenMode.ForWrite) as AcDb.BlockTableRecord;
  84.                     double[] parrs = (double[])pars;
  85.                     Array.Sort(parrs);
  86.                     foreach (AcDb.Curve cc in c.GetSplitCurves(new DoubleCollection(parrs)))
  87.                     {
  88.                         btr.AppendEntity(cc);
  89.                         tr.AddNewlyCreatedDBObject(cc, true);
  90.                         objs.Add(cc.AcadObject);
  91.                     }
  92.                     tr.Commit();
  93.                 }
  94.             }
  95.             return objs.ToArray();
  96.         }
  97.     }
  98. }
生成解决方案,将TlsCad.Curve.dll复制到AutoCad目录下
三、

diz5i4j2jhu.JPG

diz5i4j2jhu.JPG


切换到AutoCad目录下,在命令行键入
regasm TlsCad.Curve.dll /regfile /codebase
运行生成的reg文件,为.Net类库注册Com
四、
在Cad中绘制一条曲线,然后打开VB编辑器,加入下列代码调用
  1. Sub tt()
  2.     Dim tCuve As Object
  3.     Dim obj As Object, pnts(0)
  4.     Set tCuve = Application.GetInterfaceObject("TlsCad.Curve")
  5.     ThisDrawing.Utility.GetEntity obj, pnts(0)
  6.     tCuve.Set obj
  7.     pnts(0) = tCuve.GetClosestPointTo(pnts(0), False)
  8.     tCuve.SplitByParams tCuve.GetParamsByPoints(pnts)
  9. End Sub

回复

使用道具 举报

16

主题

53

帖子

1

银币

初露锋芒

Rank: 3Rank: 3Rank: 3

铜币
117
发表于 2009-12-12 22:02:00 | 显示全部楼层
老大,我照你的方法做了一遍,但是注册的时候的消息不知道是不是注册成功了,在添加com引用的时候找不到TlsCad.Curve。
在执行VBA代码的时候,Set tCuve = Application.GetInterfaceObject("TlsCad.Curve") 这一句出错:运行时错误
'-2147221005(800401f3)' 加载应用程序时出现问题。
回复

使用道具 举报

72

主题

2726

帖子

9

银币

社区元老

Rank: 75Rank: 75Rank: 75

铜币
3014
发表于 2009-12-12 22:28:00 | 显示全部楼层
添加com引用的时候确实找不到TlsCad.Curve
你运行生成的reg文件么?
把下面的rar解压到d:/tlscad/bin目录下试试
上面的VBA代码改动了一下
请点击此处下载

请先注册会员后在进行下载

已注册会员,请先登录后下载

文件名称:aigfgsbmpln.rar 
下载次数:0  文件大小:3.32 KB  售价:2银币 [记录]
下载权限: 不限 以上或 Vip会员   [开通Vip]   [签到领银币]  [免费赚银币]

回复

使用道具 举报

16

主题

53

帖子

1

银币

初露锋芒

Rank: 3Rank: 3Rank: 3

铜币
117
发表于 2009-12-13 15:20:00 | 显示全部楼层
老大,我按照你说的帖子的7楼的方法实现了com和ObjectAPI的调用,那8楼的方法和7楼却完全不一样,是不是7楼的方法有时候会碰到问题?
回复

使用道具 举报

18

主题

174

帖子

11

银币

后起之秀

Rank: 20Rank: 20Rank: 20Rank: 20

铜币
244
发表于 2009-12-13 19:31:00 | 显示全部楼层
本人轻易不灌水,灌水只为顶狐哥!~
回复

使用道具 举报

72

主题

2726

帖子

9

银币

社区元老

Rank: 75Rank: 75Rank: 75

铜币
3014
发表于 2009-12-13 21:31:00 | 显示全部楼层
奇怪的问题是:上面的方法在VB或C#却不能使用,只能VBA?
有时间按8楼的代码试下
回复

使用道具 举报

72

主题

2726

帖子

9

银币

社区元老

Rank: 75Rank: 75Rank: 75

铜币
3014
发表于 2009-12-13 23:39:00 | 显示全部楼层

代码更改了一下,这样可以了
结论是:
1、不要在NetApi中使用DBObject.FromAcadObject函数
2、注意当前文档加锁的方法
3、C#做Com反射真的好累!
C#代码:
  1. using Autodesk.AutoCAD.ApplicationServices;
  2. using Autodesk.AutoCAD.EditorInput;
  3. using AcDb = Autodesk.AutoCAD.DatabaseServices;
  4. using Autodesk.AutoCAD.Runtime;
  5. using Autodesk.AutoCAD.Geometry;
  6. using System.Runtime.InteropServices;
  7. using System;
  8. using System.Collections.Generic;
  9. namespace TlsCad.Common
  10. {
  11.     [ProgId("TlsCad.Common.Curve")]
  12.     public class Curve
  13.     {
  14.         AcDb.ObjectId _id;
  15.         public void Set(int id)
  16.         {
  17.             _id = new Autodesk.AutoCAD.DatabaseServices.ObjectId(new IntPtr(id));
  18.         }
  19.         private AcDb.Curve acCurve
  20.         {
  21.             get
  22.             {
  23.                 AcDb.Database db = _id.Database;
  24.                 using (AcDb.Transaction tr = db.TransactionManager.StartTransaction())
  25.                 {
  26.                     return tr.GetObject(_id, AcDb.OpenMode.ForRead) as AcDb.Curve;
  27.                 }
  28.             }
  29.         }
  30.         public double StartParam
  31.         {
  32.             get
  33.             {
  34.                 return acCurve.StartParam;
  35.             }
  36.         }
  37.         public double EndParam
  38.         {
  39.             get
  40.             {
  41.                 return acCurve.EndParam;
  42.             }
  43.         }
  44.         public object GetClosestPointTo(object pnt, bool extend)
  45.         {
  46.             return acCurve.GetClosestPointTo(new Point3d((double[])pnt), extend).ToArray();
  47.         }
  48.         public double GetDistAtParam(double param)
  49.         {
  50.             return acCurve.GetDistanceAtParameter(param);
  51.         }
  52.         public double GetParamAtDist(double dist)
  53.         {
  54.             return acCurve.GetParameterAtDistance(dist);
  55.         }
  56.         public double GetParamAtPoint(object pnt)
  57.         {
  58.             return acCurve.GetParameterAtPoint(new Point3d((double[])pnt));
  59.         }
  60.         public double GetDistAtPoint(object pnt)
  61.         {
  62.             return acCurve.GetDistAtPoint(new Point3d((double[])pnt));
  63.         }
  64.         private object GetParamsByPoints(object pnts)
  65.         {
  66.             List pars = new List();
  67.             AcDb.Database db = _id.Database;
  68.             using (AcDb.Transaction tr = db.TransactionManager.StartTransaction())
  69.             {
  70.                 AcDb.Curve c = tr.GetObject(_id, AcDb.OpenMode.ForRead) as AcDb.Curve;
  71.                 foreach (object pnt in (object[])pnts)
  72.                 {
  73.                     pars.Add(c.GetParameterAtPoint(new Point3d((double[])pnt)));
  74.                 }
  75.             }
  76.             return pars.ToArray();
  77.         }
  78.         public void SplitByPoints(object pnts)
  79.         {
  80.             SplitByParams(GetParamsByPoints(pnts));
  81.         }
  82.         public object SplitByParams(object pars)
  83.         {
  84.             AcDb.Database db = _id.Database;
  85.             List objs = new List();
  86.             Document doc = Application.DocumentManager.GetDocument(AcDb.HostApplicationServices.WorkingDatabase);
  87.             using (doc.LockDocument())
  88.             {
  89.                 using (AcDb.Transaction tr = db.TransactionManager.StartTransaction())
  90.                 {
  91.                     AcDb.Curve c = tr.GetObject(_id, AcDb.OpenMode.ForRead) as AcDb.Curve;
  92.                     AcDb.BlockTableRecord btr = tr.GetObject(c.OwnerId, AcDb.OpenMode.ForWrite) as AcDb.BlockTableRecord;
  93.                     double[] parrs = (double[])pars;
  94.                     Array.Sort(parrs);
  95.                     foreach (AcDb.Curve cc in c.GetSplitCurves(new DoubleCollection(parrs)))
  96.                     {
  97.                         btr.AppendEntity(cc);
  98.                         tr.AddNewlyCreatedDBObject(cc, true);
  99.                         objs.Add(cc.AcadObject);
  100.                     }
  101.                     tr.Commit();
  102.                 }
  103.             }
  104.             return objs.ToArray();
  105.         }
  106.     }
  107. }
VBA调用的代码
  1. Sub tt()
  2.     Dim tc As Object
  3.     Set tc = Application.GetInterfaceObject("TlsCad.Common.Curve")
  4.    
  5.     Dim obj As Object, pnts(1)
  6.     ThisDrawing.Utility.GetEntity obj, pnts(0)
  7.     tc.Set obj.ObjectID
  8.    
  9.     pnts(0) = tc.GetClosestPointTo(pnts(0), False)
  10.     pnts(1) = ThisDrawing.Utility.GetPoint()
  11.     pnts(1) = tc.GetClosestPointTo(pnts(1), False)
  12.    
  13.     tc.SplitByPoints (pnts)
  14.    
  15. End Sub
VB调用的代码
  1. Private Sub Command1_Click()
  2. Dim app As Object
  3. Set app = GetObject(, "AutoCad.Application")
  4. Dim tc  As Object
  5. Set tc = app.GetInterfaceObject("TlsCad.Common.Curve")
  6.     Dim obj As Object, pnts(1)
  7.     app.ActiveDocument.Utility.GetEntity obj, pnts(0)
  8.     tc.Set obj.ObjectID
  9.    
  10.     pnts(0) = tc.GetClosestPointTo(pnts(0), False)
  11.     pnts(1) = app.ActiveDocument.Utility.GetPoint()
  12.     pnts(1) = tc.GetClosestPointTo(pnts(1), False)
  13.    
  14.     tc.SplitByPoints (pnts)
  15. End Sub
C#调用的代码
  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 Autodesk.AutoCAD.Interop;
  10. using Autodesk.AutoCAD.Interop.Common;
  11. using System.Runtime.InteropServices;
  12. using System.Reflection;
  13. namespace ComTest
  14. {
  15.     public partial class Form1 : Form
  16.     {
  17.         public Form1()
  18.         {
  19.             InitializeComponent();
  20.         }
  21.         private void button1_Click(object sender, EventArgs e)
  22.         {
  23.             AcadApplication acApp = GetAcApp();
  24.             object tc = acApp.GetInterfaceObject("TlsCad.Common.Curve");
  25.             object acCurve;
  26.             object[] pnts = new object[2];
  27.             AcadDocument acDoc = acApp.ActiveDocument;
  28.             acDoc.Utility.GetEntity(out acCurve, out pnts[0], "");
  29.             InvokeMethod(tc, "Set", ((AcadEntity)acCurve).ObjectID);
  30.             pnts[0] = InvokeMethod(tc, "GetClosestPointTo", pnts[0], false);
  31.             pnts[1] = acDoc.Utility.GetPoint(pnts[0], "");
  32.             pnts[1] = InvokeMethod(tc, "GetClosestPointTo", pnts[1], false);
  33.             InvokeMethod(tc, "SplitByPoints", new object[1]{pnts});
  34.         }
  35.         public object InvokeMethod(object obj, string methodName, params object[] args)
  36.         {
  37.             Type t = obj.GetType();
  38.             object res =
  39.                 t.InvokeMember(
  40.                     methodName,
  41.                     BindingFlags.Public | BindingFlags.InvokeMethod,
  42.                     null,
  43.                     obj,
  44.                     args);
  45.             return res;
  46.         }        public AcadApplication GetAcApp()
  47.         {
  48.             const string progID = "AutoCAD.Application.18";
  49.             AcadApplication acApp = null;
  50.             try
  51.             {
  52.                 acApp =
  53.                   (AcadApplication)Marshal.GetActiveObject(progID);
  54.             }
  55.             catch
  56.             {
  57.                 try
  58.                 {
  59.                     Type acType =
  60.                       Type.GetTypeFromProgID(progID);
  61.                     acApp =
  62.                       (AcadApplication)Activator.CreateInstance(
  63.                         acType,
  64.                         true
  65.                       );
  66.                 }
  67.                 catch
  68.                 {
  69.                     MessageBox.Show(
  70.                       "Cannot create object of type "" +
  71.                       progID + """
  72.                     );
  73.                 }
  74.             }
  75.             return acApp;
  76.         }
  77.     }
  78. }
回复

使用道具 举报

16

主题

53

帖子

1

银币

初露锋芒

Rank: 3Rank: 3Rank: 3

铜币
117
发表于 2009-12-15 21:56:00 | 显示全部楼层
老大,问个简单的问题哈:
api.net编好dll之后,应该把这个dll放到cad安装目录下注册吧?
注册成功之后这个到cad安装目录下的dll能删除吗?
然后新建的应用程序在引用这个dll的时候是否复制本地呢?
回复

使用道具 举报

72

主题

2726

帖子

9

银币

社区元老

Rank: 75Rank: 75Rank: 75

铜币
3014
发表于 2009-12-16 07:45:00 | 显示全部楼层
regasm TlsCad.Curve.dll /regfile /codebase
生成reg文件
如果不在安装目录注册,要更改reg文件中的目录信息
然后再运行注册
不需要引用dll的
回复

使用道具 举报

16

主题

53

帖子

1

银币

初露锋芒

Rank: 3Rank: 3Rank: 3

铜币
117
发表于 2009-12-17 19:53:00 | 显示全部楼层
但是kean的帖子里面的7楼和8楼都引用了dll,都有这一句using LoadableComponent;
不知道引用和不引用到底有什么区别,很困惑啊
另外他8楼的方法很难看懂,主要是他写了[Guid("5B5B731C-B37A-4aa2-8E50-42192BD51B17")]
不知道这是干什么用的
回复

使用道具 举报

发表回复

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

本版积分规则

  • 微信公众平台

  • 扫描访问手机版

  • 点击图片下载手机App

QQ|关于我们|小黑屋|乐筑天下 繁体中文

GMT+8, 2025-6-28 23:18 , Processed in 1.109347 second(s), 78 queries .

© 2020-2025 乐筑天下

联系客服 关注微信 帮助中心 下载APP 返回顶部 返回列表