AutoCAD.NET二次开发注意事项
AutoCAD.NET二次开发注意事项与开发技巧
1、如果要在Winform中打开DWG图形文件,这个Form必须用Application.ShowModelessDialog方式显示,不然会报错(执行环境无效)。
2、在非模态窗口中修改实体时,需要将图层锁定,否则会报错;模态窗口则无此情况。
3、写块克隆:WblockCloneObjects第二个参数为块表记录模型空间的ObjectID,此方法会将一个对象集(实体集)完全克隆到另一个DWG文件中,包括图层名、图层设置、坐标位置、扩展数据等。
4、在CAD中用后台打开方式打开DWG图形文件,并进行修改后,要用SaveAs保存,用Save会出错。
5、使用模态窗口时,如果需要与CAD主窗体进行交互,则用using (EditorUserInteraction edUI = ed.StartUserInteraction(this));使用非模态窗口时,会出现焦点切换问题 (如:当在非模态窗口中点击按钮后要去CAD中选择一个实体,但是应用程序的焦点还在非模态窗口中,此时需要在CAD主窗口中点击一下让CAD获取焦点,才能正常进行实体选取),此时可以用WinAPI中的SetFocus将焦点移到CAD主窗口即可:
[DllImport("user32.dll", EntryPoint = "SetFocus")] public static extern int SetFocus(IntPtr hWnd);
调用:
SetFocus(Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument.Window.Handle);
要注意的是:需要配合窗体的MouseEnter、MouseLeave事件使用,但效果并不太理想,如果鼠标移动较快的时候,事件来不及触发。暂时还没有找到其他更好的方法,C++中可以接收一个KeepFocus消息,来监视和设置程序焦点,使焦点转换更灵活,C#中也可以收到CAD发来的这个消息,但是这个消息的Msg值不是固定的,C++中使用的时候不需要管这个值,因为是由CAD已经提供了,所以可以准确地方监听这个消息;但是在C#中CAD并没有提供这个Msg值,所以并不能使用监听Windows消息的方法来实现焦点的切换功能。
6、AutoCAD.NET获取CAD当前图层代码:
Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument.Database.Clayer;
7、AutoCAD 注册表项在32位与64系统中的不同
AutoCAD注册表信息读取,如获取电脑上已安装的所有CAD版本、安装路径等注册表信息。在32位Windows系统中,这些信息保存在:HKEY_LOCAL_MACHINE\SOFTWARE\Autodesk\AutoCAD 中;而64位Windows系统中,32位的CAD软件信息保存在 HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Autodesk\AutoCAD 中,64位CAD软件信息保存在 HKEY_LOCAL_MACHINE\SOFTWARE\Autodesk\AutoCAD 中。
在64位系统中,安装的CAD版本可能是32位,也可能是64位。如果在32位的CAD中调用我们的DLL,此DLL读取 HKEY_LOCAL_MACHINE\SOFTWARE 时,实际读到的是 HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node;如果在64位的CAD中调用我们的DLL,则此时DLL读取 HKEY_LOCAL_MACHINE\SOFTWARE 时,会得到真正的HKEY_LOCAL_MACHINE\SOFTWARE 对象。
上述情况是因为,为了做到64位系统兼容32位程序,同时又为了防止注册表项冲突,所以32位应用程序在64位Windows系统中操作 HKEY_LOCAL_MACHINE\SOFTWARE 键时会被自动转到 HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node。(具体说明可见:http://www.cnblogs.com/mingmingruyuedlut/archive/2011/01/20/1940371.html)
这种问题的解决方法参考:http://www.cnblogs.com/mingmingruyuedlut/archive/2011/01/21/1941225.html(C# 32位程序访问64位系统注册表)
但是还有一点要注意:在CAD二次开发中,由于我们的DLL最终是要被CAD调用的,所以我们程序集的位数是由CAD的位数来决定的。
8、修改命令快捷键并立即生效
在CAD中点击:工具-》自定义-》编辑程序参数(acad.pgp),在打开的文件中找到“Command alias format”,在其下方可以看到命令别名定义列表,定义的格式为:“别名,*命令”,每行只能定义一个,定义完成之后,重启CAD即可生效。如果不想重启CAD,还有两种方式可以让你的定义生效:
1)、在命令文本中输入reinit,回车,在弹窗中选中“PGP文件”,然后确定,如下图:
2)、在命令文本中输入re-init,回车,然后输入16,再回车即可。
第二种方法应该可以在程序中进行实现,不知道AutoCAD.NET中有没有提供现成的方法,不过可以用sendcommand实现。这样可以为用户提供快捷键的自定义功能,并且在用户定义完之后,可以立即生效。acad.pgp文件位置在:CAD安装目录\UserDataCache\Support中,是一个隐藏文件。
9、eInvalidOpenState错误问题
当在事务A中调用GetObject方法获取了对象E,在事务A结束之后,如果在另一个事务B中调用E的UpgradeOpen时,会出现错误提示:eInvalidOpenState,这时候需要在事务B中用GetObject根据E.ObjectId重新获取E才行。
10、eWasNotOpenForWrite错误问题
同问题情况类似,在事务A中调用GetObject方法获取了对象E,在事务A结束之后,如果在另一个事务B中调用E的DowngradeOpen方法,则会出现错误提示:eWasNotOpenForWrite,这时候需要在事务B中用GetObject根据E.ObjectId重新获取E。
11、SelectionFilter 根据XData扩展数据过滤选择集问题
使用根据对象的扩展数据XData进行过滤选择时,如果过滤条件仅为DxfCode.ExtendedDataRegAppName(即注册的应用程序名)时,可以过滤所有类型的对象,但是如果要用DxfCode.ExtendedDataAsciiString、DxfCode.ExtendedDataInteger16等具体数据内容进行过滤时,则仅能选取到部分类型的对象,如:Line、PolyLine、Ellipse、Region,而像DBText、MText、Circle等类型的实体则会被忽略掉。
12、SelectionFilter过滤选择单行文本对象问题
用SelectionFilter过滤选择文本时,切记单行文本必须写成TypedValue((int)DxfCode.Start,"Text"),要写成"Text",而不是"DBText"。
13、用Hatch填充时的问题
用Hatch填充Region时,如果面域对象是由多个面域合并而来,会填充失败,此时可以调用Region对象的Explode方法将Region炸散,得到多个Region,然后将这些Region一一填充。
对于Hatch.AppendLoop第二个参数:ObjectIdCollection 类型,传入的是一个或多个实体对象的ID,这些实体必须满足以下几个条件:
1)、如果只传入一个对象,那么这个对象必须是一个非“回”字型闭合对象,如闭合的pline、单个的Region、Circle、Ellipse等;如果传入的对象是回字型,即中间是空心的,那么将会报错,填充将失败。
2)、如果传入的是多个对象,那么这些对象必须正好可以首尾相接地组成一个闭合图形,且没有富余的对象,这样才能成功填充;如果组成的图形不能闭合,或者闭合后还剩余一些无用处的线、弧等,又或者组成了多个闭合图形,那么将会报错,填充将失败。
14、嵌套事务问题
使用嵌套事务时,好像如果外层的事务不提交,即使里面的事务提交了,最终也会失效,不知道这种说法对不对,因为今天我在里层的事务里创建了一个Hatch并且提交了事务,在代码里看Hatch已经完全创建成功了,但是外层的事务没有提交,结果执行结束后在CAD中完全找不到Hatch的影子。
15、Autodesk.AutoCAD.DatabaseServices.DataTable 扩展数据表使用时要注意
当对象实体的扩展字典中还没有这个表时,DBDictionary.SetAt 和 Transaction.AddNewlyCreatedDBObject 将扩展数据表添加到实体对象,但是修改时就不能再这样了,只需要获取DataTable对象,然后用 DataTable.SetCellAt 方法修改数据表的值,最后提交事务即可。
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。