OLE(对象链接与嵌入)剪贴板内容插入到 CAD 图形中——CAD c# 二次开发
在 AutoCAD 的 C# 二次开发里,借助 OLE(对象链接与嵌入)技术把剪贴板内容插入到 CAD 图形中,是一种常用的方法。下面将对其概念、原理和实现方式进行详细介绍:
一、OLE 技术概述
OLE(对象链接与嵌入)是微软提出的一项技术,它能够让不同应用程序之间实现数据共享与交互。在 AutoCAD 二次开发中,OLE 技术主要有以下两种应用场景:
- 链接对象:被插入到 AutoCAD 中的内容依旧和源应用程序保持关联。当源文件发生更改时,AutoCAD 中的对象也会随之更新。
- 嵌入对象:将剪贴板中的内容完整地复制到 AutoCAD 图形中,此时它与源应用程序不再有联系。
二、实现 OLE 插入的关键步骤
1. 引用必要的命名空间
csharp
using System.Runtime.InteropServices; // 用于COM互操作
using Autodesk.AutoCAD.Runtime;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.EditorInput;
2. 实现插入剪贴板 OLE 对象的命令
[CommandMethod("PasteFromClipboard")]
public void PasteFromClipboard()
{// 获取当前文档和数据库Document doc = Application.DocumentManager.MdiActiveDocument;Database db = doc.Database;Editor ed = doc.Editor;// 检查剪贴板中是否有OLE对象if (!System.Windows.Forms.Clipboard.ContainsData(System.Windows.Forms.DataFormats.EnhancedMetafile) &&!System.Windows.Forms.Clipboard.ContainsData(System.Windows.Forms.DataFormats.Bitmap) &&!System.Windows.Forms.Clipboard.ContainsData("ObjectLink")){ed.WriteMessage("\n剪贴板中没有可插入的OLE对象!");return;}// 提示用户选择插入点PromptPointOptions ppo = new PromptPointOptions("\n请选择插入点: ");PromptPointResult ppr = ed.GetPoint(ppo);if (ppr.Status != PromptStatus.OK)return;Point3d insertionPoint = ppr.Value;// 开始事务处理using (Transaction tr = db.TransactionManager.StartTransaction()){try{// 打开块表以进行读取BlockTable bt = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead);// 打开当前空间以进行写入BlockTableRecord btr = (BlockTableRecord)tr.GetObject(doc.Database.CurrentSpaceId, OpenMode.ForWrite);// 创建OLE2Frame对象Ole2Frame oleFrame = new Ole2Frame();// 设置插入点和比例oleFrame.Position = insertionPoint;oleFrame.ScaleFactors = new Scale3d(1, 1, 1);// 从剪贴板获取数据System.Windows.Forms.IDataObject dataObj = System.Windows.Forms.Clipboard.GetDataObject();// 尝试处理不同格式的数据if (dataObj.GetDataPresent(System.Windows.Forms.DataFormats.EnhancedMetafile)){// 处理EMF格式System.Drawing.Imaging.Metafile emf = (System.Drawing.Imaging.Metafile)dataObj.GetData(System.Windows.Forms.DataFormats.EnhancedMetafile);// 将EMF转换为临时文件string tempFilePath = System.IO.Path.GetTempPath() + "temp_emf.emf";emf.Save(tempFilePath);// 设置OLE对象属性oleFrame.ClassId = RXClass.GetClass(typeof(Ole2Frame)).DxfName;oleFrame.Contents = "Enhanced Metafile";oleFrame.Link = false; // 设为false表示嵌入对象oleFrame.SourceFullName = tempFilePath;// 计算OLE对象的大小double width = emf.Width / 300.0; // 转换为CAD单位(英寸)double height = emf.Height / 300.0;// 设置OLE对象的大小oleFrame.Size = new Size2d(width, height);}else if (dataObj.GetDataPresent(System.Windows.Forms.DataFormats.Bitmap)){// 处理位图格式System.Drawing.Bitmap bmp = (System.Drawing.Bitmap)dataObj.GetData(System.Windows.Forms.DataFormats.Bitmap);// 将位图转换为临时文件string tempFilePath = System.IO.Path.GetTempPath() + "temp_bmp.bmp";bmp.Save(tempFilePath);// 设置OLE对象属性oleFrame.ClassId = RXClass.GetClass(typeof(Ole2Frame)).DxfName;oleFrame.Contents = "Bitmap Image";oleFrame.Link = false;oleFrame.SourceFullName = tempFilePath;// 计算OLE对象的大小double width = bmp.Width / 300.0;double height = bmp.Height / 300.0;// 设置OLE对象的大小oleFrame.Size = new Size2d(width, height);}else if (dataObj.GetDataPresent("ObjectLink")){// 处理其他OLE对象类型// 这里需要根据具体的对象类型进行处理ed.WriteMessage("\n检测到OLE对象链接,但可能需要特殊处理。");// 示例: 尝试获取对象数据object oleData = dataObj.GetData("ObjectLink");// 根据具体类型进行处理...}// 将OLE对象添加到块表记录中btr.AppendEntity(oleFrame);tr.AddNewlyCreatedDBObject(oleFrame, true);// 提交事务tr.Commit();ed.WriteMessage("\n已成功插入OLE对象!");}catch (System.Exception ex){ed.WriteMessage("\n错误: " + ex.Message);tr.Abort();}}
}
三、代码解析
上述代码主要实现了以下功能:
- 剪贴板检查:查看剪贴板中是否存在 OLE 兼容的数据格式,像增强图元文件、位图等。
- 插入点选择:让用户在 CAD 绘图区域选择 OLE 对象的插入位置。
- OLE 对象创建:创建
Ole2Frame
对象,并对其属性(如位置、比例、内容类型等)进行设置。 - 数据处理:
- 把剪贴板数据转换为临时文件。
- 设置 OLE 对象的源文件路径和显示大小。
- 事务管理:保证数据库操作的一致性,若出现错误则进行回滚。
四、注意事项
- 临时文件管理:示例代码中创建的临时文件不会被自动清理,在实际应用中,你需要添加文件清理逻辑。
- OLE 类型支持:不同的应用程序可能会以不同的格式将数据放在剪贴板中,你可能需要针对特定的源应用程序(如 Word、Excel 等)编写专门的处理代码。
- 比例与单位:要确保 OLE 对象的尺寸和比例与 CAD 图形单位相匹配。
- 错误处理:实际开发中,你需要更全面地处理各种可能出现的异常情况。
通过这种方式,你就可以在 AutoCAD 的 C# 二次开发中利用 OLE 技术插入剪贴板内容了。