背景

因工作需要,想尝试一下从autoCAD读取图纸数据,并直接在Tekla Structures建模。之前有使用过VS2010,用vb.net和c#.net开发过一点程序,这次想继续用VS2010进行开发。由于将要从0开始学习CAD和Tekla两款软件的二次开发,等完成后,对其他人也有些参考价值,所以本文将记录下整个的摸索过程。
目前的大致思路是:
- 通过CAD插件读取数据
- 储存原始数据
- 原始数据经过计算后,生成模型参数数据
- 通过Tekla插件将模型绘制出来


尝试过程

2016.08.23

第1步目标:外部程序调用Tekla的API,在模型里绘制简单图形(已实现)

目前已实现,稍后补上。

第2步目标:外部程序调用autoCAD的API,在图纸上绘制简单图形(已实现)

经过搜索,发现CAD二次开发主分为:VBA、Lisp、ObjectARX和.Net。从我的开发经历看,.Net应该是最满足项目需求的——操作体验与保密,所以首先尝试.Net的方案。
我用的是autoCAD2014,找到这篇文章AutoCAD .NET API二次开发学习指南
去到autoCAD官网的资料区,里面有各种文档和安装程序,可惜没有找到中文网页。
之前搜索ObjectARX时,有下载2014版的SDK,是在新浪博客找到的,链接也是官网的。
从资料区看,autoCAD2014支持VS2010和VS2012,看来运气还不错。
安装完ObjectARX SDK,确切地说是解压了之后,在VS2010里并没有出现ObjectARX的模板。于是按照学习指南的步骤,又安装了.NET Wizards,程序是直接在官网下载的。在安装.NET Wizards之前,我还安装了ObjectARX Wizards,同样是在官网找到的。ObjectARX Wizards安装了之后,在VS2010里C++下出现了AutoCAD的模板,安装.NET Wizards之后,才在C#下出AutoCAD的模板。

新建了一个工程,里面已经添加了autoCAD的一些引用,直接编译,没有报错。

生成的是.dll文件,不能直接运行,我又另外新建了一个普通工程TestModel,想添加引用,看能不能编译通过。因为dll的插件里是空的,我想起了之前在github下载的一个cad 插件工程,当时已经编译通过生成了dll文件。于是,我用它来测试引用,顺便看看能不能操作autoCAD。
我先是只添加了dll的引用和using声明,编译通过,但运行时报错:”未能加载文件或程序集“Acdbmgd.dll”或它的某一个依赖项。找不到指定的模块。“。添加对Acdbmgd.dll等几个文件的引用,还是报错。

还是看文档吧,下载了AutoCAD 2014 .Net Training,里面有个PPT,英文的。看了几页,惊呆了!居然是用netload加载dll到autoCAD!试了一下,顺利地运行了一个画直线的命令,果然是打开的方式不对。可是,这种用法,真的不符合我的预期啊!

但我不死心,继续找。终于找到《外部.NET程序与AutoCAD交互》,在TestModel中添加了“AutoCAD 2014 Type Library”引用,但添加”using Autodesk.AutoCAD.Interop;“时提示错误。搜索“”,找到一个帖子,以下一个回答。

晕,还没有人回答你噢,我来说一下吧,首先第一步你要添加两个COM引用:
AutoCAD 2010 Type Library //我的机子里装的是CAD2010版
AutoCAD/ObiectDBX Common 18.0 Type Library
把这两个引用的命名空间引进来
using Autodesk.AutoCAD.Interop;
using Autodesk.AutoCAD.Interop.Common;
//就可以写代码了
AcadApplication CadApp; //定义一个CAD应用程序对像
AcadDocument CadDoc; //定义一个CAD文档
AcadModelSpace CadSpace; //这是CAD的模型空间
//然后就先一个CAD应用程序
CadApp = new AcadApplication();
CadApp.Visible = true; //如果你想把CAD显示到前台来,就设为true
CadDoc = CadApp.ActiveDocument; //获取CAD当前活动的文档
CadSpace = (AcadModelSpace)CadDoc.ModelSpace; //获得命名空间
double[] c = new double[6]; //我随便定义一个要画线的点数组,记得点这个数组里是按XYZ坐标顺序存放的噢
c[0] = 34; c[1] = 98; c[2] = 67; c[3] = 956; c[4] = 655; c[5] = 322; //随便输的
CadSpace.Add3DPoly(c); //我这里画的是三维多段线,你要画其它的线型的话,到找一下对应的方法即可。
别忘了记得给分噢!

但还是提示错误,我用Everything搜索“Autodesk.AutoCAD.Interop.dll”,在ObjectARX SDK里找到了这个文件,有32位、64位两种,还看到了Autodesk.AutoCAD.Interop.Common.dll,我引用了64位的这两个文件,错误消除了。直接编译运行,成功打开了一个新autoCAD进程,画出了一条线。


在《外部.NET程序与AutoCAD交互》找到调用已打开autoCAD的代码,修改后如下,也成功地在autoCAD里画了一条线。后来发现,只添加两个dll,不添加COM引用,也是可以的。

        private void button2_Click(object sender, EventArgs e){const string progID = "AutoCAD.Application.19.1"; AcadApplication acApp = null; try { acApp = (AcadApplication)Marshal.GetActiveObject(progID); }catch{try { Type acType = Type.GetTypeFromProgID(progID); acApp = (AcadApplication)Activator.CreateInstance(acType, true); } catch { MessageBox.Show("Cannot create object of type \"" + progID + "\""); } }if (acApp != null){ // By the time this is reached AutoCAD is fully  // functional and can be interacted with through code   acApp.Visible = true;AcadDocument CadDoc;  //定义一个CAD文档AcadModelSpace CadSpace;  //这是CAD的模型空间//然后就先一个CAD应用程序acApp.Visible = true;  //如果你想把CAD显示到前台来,就设为trueCadDoc = acApp.ActiveDocument;  //获取CAD当前活动的文档CadSpace = (AcadModelSpace)CadDoc.ModelSpace; //获得命名空间double[] c = new double[6];  //我随便定义一个要画线的点数组,记得点这个数组里是按XYZ坐标顺序存放的噢c[0] = 34; c[1] = 98; c[2] = 67; c[3] = 956; c[4] = 655; c[5] = 322;  //随便输的CadSpace.Add3DPoly(c);MessageBox.Show("hello");}}

现在能启动autoCAD了,后面就是想办法把插件dll加载进去。

第3步目标:外部程序调用autoCAD .Net API(未实现)

第2步完成的,其实是通过COM方式操作的autoCAD。《外部.NET程序与AutoCAD交互》虽然写了怎样加载.Net程序集来调用.Net API,但一直出现应用程序加载失败。看来事情并不是那么简单。COM方式操作autoCAD难以得到返回值,而我的目标是读取数据。
看来这条路暂时不通,调整目标:用acad2014.lsp自动加载dll插件,通过插件与外部程序通讯。

C:\Program Files\Autodesk\AutoCAD 2014\Support\acad2014.lsp
(COMMAND "NetLoad" "D:\\test.dll")

2016.08.24

第4步目标:用.Net插件在图纸上画常用图形、标注等(部分实现)

先看《AutoCAD 2014 .Net Training》里的教程,把里面的示例工程都认真看了一遍。从1到8,每个示例添加一点功能,发现它把常用的功能都演示了下:画圆、画块、database、Jigs、PointMonitor、添加右键、添加窗体。可惜没说Ribbon,我找到AutoCAD中程序创建Ribbon界面执行AutoCAD命令,本想直接添加到示例8,但引用老是有问题。然后,我用Wizard新建了个工程,引用全部选中,把代码复制进去,又添加System.Xaml引用和using Autodesk.Windows;终于编译通过,创建出了一个空白Ribbon Tab。

using System;
using Autodesk.AutoCAD.Runtime;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.EditorInput;using Autodesk.Windows;private const string MY_TAB_ID = "MY_TAB_ID";[CommandMethod("addMyRibbon")]public void createRibbon(){Autodesk.Windows.RibbonControl ribCntrl =Autodesk.AutoCAD.Ribbon.RibbonServices.RibbonPaletteSet.RibbonControl;//can also be Autodesk.Windows.ComponentManager.Ribbon;     //add the tabRibbonTab ribTab = new RibbonTab();ribTab.Title = "My custom tab";ribTab.Id = MY_TAB_ID;ribCntrl.Tabs.Add(ribTab);//create and add both panelsaddPanel1(ribTab);addPanel2(ribTab);//set as active tabribTab.IsActive = true;}private void addPanel2(RibbonTab ribTab){}private void addPanel1(RibbonTab ribTab){//throw new NotImplementedException();}




当我想继续添加Panel和Button时,又出现引用问题了,有一个类的声明老找不到。

2016.08.25

折腾了半天,发现是自定义的。。。补上之后,终于添加上按钮了。

//添加按钮的代码private void addPanel2(RibbonTab ribTab){//create the panel sourceRibbonPanelSource ribPanelSource = new RibbonPanelSource();ribPanelSource.Title = "Edit Registry";//create the panelRibbonPanel ribPanel = new RibbonPanel();ribPanel.Source = ribPanelSource;ribTab.Panels.Add(ribPanel);//create button1RibbonButton ribButtonDrawCircle = new RibbonButton();ribButtonDrawCircle.Text = "My Draw Circle";ribButtonDrawCircle.ShowText = true;//pay attention to the SPACE after the command nameribButtonDrawCircle.CommandParameter = "DrawCircle ";ribButtonDrawCircle.CommandHandler = new AdskCommandHandler();ribPanelSource.Items.Add(ribButtonDrawCircle);}private void addPanel1(RibbonTab ribTab){//throw new NotImplementedException();}[CommandMethod("DrawCircle")]public void DrawCircle(){//画个圆,实现在此略去,这不是这篇blog的重点。Editor ed = Application.DocumentManager.MdiActiveDocument.Editor;PromptPointOptions getPointOptions = new PromptPointOptions("Pick Center Point : ");PromptPointResult getPointResult = ed.GetPoint(getPointOptions);if ((getPointResult.Status == PromptStatus.OK)){PromptDistanceOptions getRadiusOptions = new PromptDistanceOptions("Pick Radius : ");getRadiusOptions.BasePoint = getPointResult.Value;getRadiusOptions.UseBasePoint = true;PromptDoubleResult getRadiusResult = ed.GetDistance(getRadiusOptions);if ((getRadiusResult.Status == PromptStatus.OK)){Database dwg = ed.Document.Database;Transaction trans = dwg.TransactionManager.StartTransaction();try{Circle circle = new Circle(getPointResult.Value, Vector3d.ZAxis, getRadiusResult.Value);BlockTableRecord btr = (BlockTableRecord)trans.GetObject(dwg.CurrentSpaceId, OpenMode.ForWrite);btr.AppendEntity(circle);trans.AddNewlyCreatedDBObject(circle, true);trans.Commit();}catch (System.Exception ex){ed.WriteMessage("problem due to " + ex.Message);}finally{trans.Dispose();}}}}
//以下是响应按钮的自定义类class AdskCommandHandler : System.Windows.Input.ICommand{public bool CanExecute(object parameter){return true;}public event EventHandler CanExecuteChanged;public void Execute(object parameter){//is from Ribbon ButtonRibbonButton ribBtn = parameter as RibbonButton;if (ribBtn != null){//execute the command Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument.SendStringToExecute((string)ribBtn.CommandParameter, true, false, true);}}}


这一部分的工程代码到此处可下载。

第5步目标:把ribbon、窗体、右键整合到同一个插件工程(已实现)

2016.08.26
把Ribbon、palette、右键的代码整合到一起之后,可以通过命令来加载它们了。但为了方便,我想让CAD启动时,自动加载。

        void IExtensionApplication.Initialize(){AddContextMenu();createRibbon(); palette();}void IExtensionApplication.Terminate(){RemoveContextMenu();            }

按理说,上面的代码就能让CAD在启动时加载右键、Ribbon、窗体了,但Dll加载却出问题了。逐一测试后,发现是Ribbon加载有问题。在《 打开cad如何自动加载ribbon菜单》找到了答案,原来是要等待Ribbon启动。原样复制代码,却提示“No overload for ‘ComponentManager_ItemInitialized’ matches delegate ‘System.EventHandler’”。还好最后找到另一篇《获取Ribbon 选项卡(Tab)被点击的消息》,添加了一个“< RibbonItemEventArgs >”,错误消除。

        void IExtensionApplication.Initialize(){AddContextMenu();Autodesk.Windows.ComponentManager.ItemInitialized += new EventHandler<RibbonItemEventArgs>(ComponentManager_ItemInitialized); palette();}void IExtensionApplication.Terminate(){RemoveContextMenu();}void ComponentManager_ItemInitialized(object sender, RibbonItemEventArgs e){if (Autodesk.Windows.ComponentManager.Ribbon != null){createRibbon();Autodesk.Windows.ComponentManager.ItemInitialized -= new EventHandler<RibbonItemEventArgs>(ComponentManager_ItemInitialized);}}


自动加载使用的是注册表法,为了不让CAD提示警告,还把dll放在了CAD安装目录下。

Windows Registry Editor Version 5.00[HKEY_LOCAL_MACHINE\SOFTWARE\Autodesk\AutoCAD\R19.1\ACAD-D001\Applications\CadDataCapture]
"LOADCTRLS"=dword:0000000e
"LOADER"="C:\\Program Files\\Autodesk\\AutoCAD 2014\\CadDataCapture.dll"
"DESCRIPTION"="AutoCAD Data Capture"
"MANAGED"=dword:00000001[HKEY_LOCAL_MACHINE\SOFTWARE\Autodesk\AutoCAD\R19.1\ACAD-D001\Applications\CadDataCapture\Commands]
"palette"="CadDataCapture.resources.dll#palette"[HKEY_LOCAL_MACHINE\SOFTWARE\Autodesk\AutoCAD\R19.1\ACAD-D001\Applications\CadDataCapture\Groups]
"CadDataCapture_CMDS"="CadDataCapture_CMDS"

但还有一个问题,就是palette加载之后,重启CAD,会有两个palette。这个小问题就不纠结了,这个目标算是完成了。
这部分的工程代码可在此处下载。

暂告一段落

后面的开发研究就不具备普遍性了,所以文章就暂告一段落,一些工程代码随后上传。

从0开始——CAD与Tekla开发入门相关推荐

  1. 一文让你明白CAD开发基本结构框架(CAD二次开发入门)

    想对CAD进行二次开发的你一定有这样的困惑.那就是如何入手呢?怎么用代码画图呢?又或是CAD画一个简单的图形要遵循什么步骤呢? 我认为学习任何一个东西,从整体把握都是十分重要的,哪怕刚开始慢一点,花一 ...

  2. c# CAD二次开发入门学习二

    获取到一个图形对象 : AcadDocument oAcadDocument = oAcadApplication.Documents.Open(FileName, null, null); 有了图形 ...

  3. 图解VC++6.0和ACE 5.4 开发入门

    一 工具和下载 工具和环境: Win7, VC++6, ACE5.4 可在Win7下运行的VC6下载: http://blog.csdn.net/bcbobo21cn/article/details/ ...

  4. 职坐标 Android,IOS开发入门之MacOs安装Android Studio3.0的常见问题及解决方案

    本文将带你了解IOS开发入门MacOs安装Android Studio3.0的常见问题及解决方案,希望本文对大家学IOS有所帮助. MacOs安装Android   Studio3.0的常见问题及解决 ...

  5. C# Cad二次开发新手入门系列教程(二)Line对象

    目录 Line对象说明 创建一个Line对象 Line对象说明 Line对象为CAD中的直线,什么是直线,严格来说CAD中的直线并非数学中定义的直线,实际上CAD的直线只是一个线段而已!那么在数学上我 ...

  6. 【鸿蒙OS开发入门】16 - 重头搭建Ubuntu新环境编译OpenHarmony 3.0 LTS

    [鸿蒙OS开发入门]16 - 重头搭建Ubuntu新环境编译OpenHarmony 3.0 LTSv 一.配置Telnet 和 samba 二.下载code-v3.0-LTS.tar.gz源码 三.配 ...

  7. CAD二次开发--0.开发环境搭建及CAD层次结构

    本文章用于CAD二次开发学习工作总结,参考李冠艺著编的<深入浅出AutoCAD.NET二次开发>. 一.开发前准备: 首先开发前默认有一定的C#编程经验. 对CAD有一定的了解. 安装好V ...

  8. C# Cad二次开发新手入门系列教程(一)开发环境搭建

    目录 前言 开发需要做什么准备? 编写自己的第一个程序 前言 本课程主要针对刚接触Cad二次开发或者准备入门Cad二次开发的朋友,笔者是用的C#进行开发,在该系列教程内,笔者会带着大家从最基础的开发到 ...

  9. OCC-7.6.0 + MFC单文档应用入门教程

    OCC-7.6.0 + MFC单文档应用 入门教程 磨刀不误砍柴工,如果你对MFC没任何基础,请先读这篇MFC的入门基础,它会降低你对这篇文章的恐惧感 开发环境说明 win7+ opencascade ...

  10. ArcEngine C# GIS开发入门作业 (三)Ex04——实现地图的简单渲染和唯一值渲染

    文章评论 写评论 sinat_37432938: 可以说非常有参考的意义,谢谢分享 4周前 #2楼 举报回复查看回复(1) domen_dragon 回复 sinat_37432938: 哈哈,谢谢夸 ...

最新文章

  1. ASP.NET:为 AJAX 请求添加客户端事件
  2. The 2014 ACM-ICPC Asia Mudanjiang Regional First Round J
  3. 语义分析 文本矛盾点解析_关于解析文本的几点思考
  4. 基于swiper和Less的小米商城
  5. educoder第六章 关联挖掘 实验二:FP-growth
  6. 6425C-Lab5 管理计算机帐户
  7. Linux面试必备20个常用命令
  8. 资深ios开发工程师收藏的iOS干货文章、大神的blog博客
  9. virtualbox win10 共享文件夹
  10. 6 种老而不死的编程语言!
  11. TCP的三次握手和四次握手详解
  12. 普转题比赛2021/7/20
  13. 宽带拨号任何使用计算机,宽带拨号密码怎么查看【图解】
  14. weex 使用指南和坑
  15. 【转】GPS定位基本原理浅析
  16. 关于pytorch的upsample_bilinear2d的align_corners和half_pixel等参数确定
  17. nonlinear transformation
  18. linux 系统被入侵之后你要做什么
  19. 文心一言背后,百度还是那个百度
  20. three 天空球_ThreeJS 创建简单天空盒

热门文章

  1. 微信小程序(第二十六章)- json-server环境搭建
  2. ubuntu终端打开文件夹_如何在Ubuntu的文件浏览器中将终端打开到特定文件夹
  3. Java生成随机数的4种方式
  4. NetApp FAS 混合闪存阵列
  5. NetApp 存储阵列 AFF A 系列——可提供屡获殊荣的速度和响应能力,满足性能敏感性工作负载的需求
  6. DDR4 vs LPDDR4 vs LPDDR4x:有什么区别?
  7. Linux--DHCP 服务(了解 DHCP 服务、其工作过程、如何动态配置主机地址、安装 DHCP 服务器及配置步骤)
  8. 为 WSO2 ESB 5.0.0 集群配置 MySQL 数据库
  9. linux关闭防火墙时出现问号乱码,linux文件名乱码问题的解决方...-tcp_wrappers防火墙配置方法-su 与 su - 的比较_169IT.COM...
  10. Android 特效直播实现原理解析