using System; using System.Collections.Generic; using System.Drawing; using System.IO; using System.Linq; using System.Threading; using Bricscad.ApplicationServices; using Bricscad.EditorInput; using SWS.Commons; using Teigha.DatabaseServices; using Teigha.Geometry; using Database = Teigha.DatabaseServices.Database; using Entity = Teigha.DatabaseServices.Entity; using Path = System.IO.Path; using Color = Teigha.Colors.Color; namespace SWS.CAD.Base { public static class General { static Document doc = null; static Bricscad.EditorInput.Editor ed = null; static Database db = null; /// /// 新建一个dwg /// /// 文件夹路径 /// 文件名,不需要后缀 public static bool CreateDwg(string folderPath, string Name) { // 创建一个新的数据库对象,该对象代表一个 DWG 文件 Database newDb = new Database(true, true); string fullPath = Path.Combine(folderPath, Name + ".dwg"); // 确保目标文件夹存在 if (!Directory.Exists(folderPath)) { Directory.CreateDirectory(folderPath); } try { // 保存数据库到指定路径 newDb.SaveAs(fullPath, DwgVersion.Current); // 关闭数据库 newDb.Dispose(); //EditorHelper.WriteInfo("新的 DWG 文件已成功创建:" + fullPath); return true; } catch (Exception) { return false; } } /// /// 新建图纸 /// /// public static bool NewDwgInApp(string newName) { Application.DocumentManager.Add(newName);//新建图纸 return true; } public static void InsertTest(string Test) { //插入文字 DBText dBText = new DBText(); dBText.TextString = Test; dBText.Height = 100; dBText.Normal = Vector3d.XAxis; dBText.HorizontalMode = TextHorizontalMode.TextMid; dBText.VerticalMode = TextVerticalMode.TextVerticalMid; dBText.AlignmentPoint = Point3d.Origin; var dBId = dBText.ToModelSpace(); } /// /// 添加实体到模型空间 /// /// 要添加的实体 /// 实体ObjectId public static ObjectId ToModelSpace(this Entity entity, Database db = null) { //if (entity.Id != ObjectId.Null|| entity.Id.ToInt() != 0) //{ // return entity.Id; //} if (db == null) { db = HostApplicationServices.WorkingDatabase; } ObjectId id; using (Transaction trans = db.TransactionManager.StartTransaction()) { BlockTable bt = (BlockTable)trans.GetObject(db.BlockTableId, OpenMode.ForRead); BlockTableRecord modelSpace = (BlockTableRecord)trans.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForWrite); id = modelSpace.AppendEntity(entity); trans.AddNewlyCreatedDBObject(entity, true); trans.Commit(); trans.Dispose(); } return id; } /// /// 读取图块图纸插入当前文档 /// /// public static ObjectId InsertBlock(string fileName, string blockName) { ObjectId entity = ObjectId.Null; if (!File.Exists(fileName)) return entity; Document doc = Application.DocumentManager.MdiActiveDocument; Database db = doc.Database; // 新建块文件数据库对象 读取块 using (Database blockDb = new Database(false, true)) { // 读取外部块 dwg blockDb.ReadDwgFile(fileName, System.IO.FileShare.ReadWrite, true, null); // 关闭文件 blockDb.CloseInput(true); // 先锁定文档 多文档的情况需要先锁定 using (DocumentLock lockDoc = doc.LockDocument()) { // 新建图层id ObjectId layId = ObjectId.Null; // 开启事务处理 using (Transaction trans = db.TransactionManager.StartTransaction()) { BlockTable bt = trans.GetObject(db.BlockTableId, OpenMode.ForRead) as BlockTable; ObjectId idBtr = doc.Database.Insert(blockName, blockName, blockDb, true); BlockTableRecord curBtr = trans.GetObject(db.CurrentSpaceId, OpenMode.ForWrite) as BlockTableRecord; var block = new BlockReference(Point3d.Origin, idBtr); curBtr.AppendEntity(block); trans.AddNewlyCreatedDBObject(block, true); entity = block.Id; trans.Commit(); trans.Dispose(); } } } return entity; } /// /// 从旧图纸复制 /// /// /// /// /// public static IdMapping CopyFormOldDoc(this Document oldODc, params ObjectId[] oldIds) { Document doc = Application.DocumentManager.MdiActiveDocument; Database db = doc.Database; IdMapping idMap = new IdMapping(); using (Transaction tr = db.TransactionManager.StartTransaction()) { using (Database srcDb = oldODc.Database) { ObjectIdCollection oids = new ObjectIdCollection(oldIds); if (oids.Count > 0) { srcDb.WblockCloneObjects(oids, db.CurrentSpaceId, idMap, DuplicateRecordCloning.Ignore, false); } } tr.Commit(); } return idMap; } /// /// 获得实体 /// /// /// /// /// public static T GetEntity(this ObjectId id, OpenMode openMode = OpenMode.ForWrite) where T : Entity { if (id == ObjectId.Null) { return null; } var db = HostApplicationServices.WorkingDatabase; T obj; using (Transaction trans = db.TransactionManager.StartTransaction()) { obj = trans.GetObject(id, openMode) as T; return obj; } } /// /// 打开一个dwg图纸文件 /// /// 文件路径 /// 是否只读模式,true为只读 public static string OpenDwg(string filePath, bool isReadOnly = false) { try { Application.DocumentManager.Open(filePath, isReadOnly); doc = Application.DocumentManager.MdiActiveDocument; ed = doc.Editor; db = doc.Database; if (isReadOnly) { ed.WriteMessage("\n 以只读模式打开图纸。\n"); } else { ed.WriteMessage("\n 已打开图纸,可继续编辑。\n"); } return ""; } catch (Exception ex) { string errorMsg = $"图纸:{filePath},打开失败,信息:{ex.Message}"; LoggerHelper.Current.Error(errorMsg); return errorMsg; } } #region 获取缩略图 /// /// 获取缩略图 /// /// /// public static Bitmap GetDwgThumbnail(string dwgPath) { try { Database dbb = new Database(false, true); dbb.ReadDwgFile(dwgPath, FileShare.Read, false, ""); System.Drawing.Bitmap preview = dbb.ThumbnailBitmap; if (preview != null) { preview.MakeTransparent(System.Drawing.Color.White); return preview; } else { return null; } } catch (Exception ex) { return null; } } #endregion #region 根据句柄获取图元 /// /// 根据句柄获取图元 /// /// /// public static ObjectId GetObjectIdByHandle(string handleId) { try { var id = long.Parse(handleId, System.Globalization.NumberStyles.HexNumber); Handle handle = new Handle(id); ObjectId objeId = HostApplicationServices.WorkingDatabase.GetObjectId(false, (Handle)handle, 0); return objeId; } catch (Exception ex) { string errorMsg = $"根据句柄获取图元GetObjectIdByHandle失败,信息:{ex.Message}"; LoggerHelper.Current.Error(errorMsg); return ObjectId.Null; } } #endregion #region 根据句柄选中图元并放大 /// /// 根据句柄选中图元 /// /// objectId public static string SelectEntityByHandle(string handleId) { try { var objId = GetObjectIdByHandle(handleId); if (objId == null) { return $"没找到【{handleId}】的图元!"; } Document doc = Application.DocumentManager.MdiActiveDocument; var ed = doc.Editor; Database db = doc.Database; using (Transaction tr = db.TransactionManager.StartTransaction()) { // 验证对象是否为图元 Entity ent = tr.GetObject(objId, OpenMode.ForRead) as Entity; if (ent != null) { // 创建包含该ObjectId的数组 ObjectId[] objIds = { objId }; // 清空当前选择集并添加新的ObjectId // 更新编辑器以显示选中效果 ed.SetImpliedSelection(objIds); ed.WriteMessage($"\n成功选中句柄为 {handleId} 的图元。\n"); //方法一 操作中间视图 ZoomToSelected(); //方法二 控制台命令:zoom ob //SendCommand("ZOOM\nob\n"); //ZOOM回车ob回车 } else { ed.WriteMessage("\n该句柄对应的对象不是图元。\n"); } tr.Commit(); return string.Empty; } } catch (Exception ex) { string errorMsg = $"根据句柄选中图元SelectEntityByHandle失败,信息:{ex.Message}"; LoggerHelper.Current.Error(errorMsg); return ex.Message; } } #endregion #region 选中图元 /// /// 选中图元 /// /// objectId public static void SelectEntity(ObjectId objId) { try { Document doc = Application.DocumentManager.MdiActiveDocument; var ed = doc.Editor; Database db = doc.Database; using (Transaction tr = db.TransactionManager.StartTransaction()) { // 验证对象是否为图元 Entity ent = tr.GetObject(objId, OpenMode.ForRead) as Entity; if (ent != null) { // 创建包含该ObjectId的数组 ObjectId[] objIds = { objId }; // 清空当前选择集并添加新的ObjectId // 更新编辑器以显示选中效果 ed.SetImpliedSelection(objIds); //ed.WriteMessage("\n成功选中图元。" ); } else { ed.WriteMessage("\n该句柄对应的对象不是图元。"); } tr.Commit(); } } catch (Exception ex) { throw; } } #endregion #region 图纸选中放大到视图中间 /// /// 图纸选中放大到视图中间 /// /// 文件路径 /// 是否只读模式,true为只读 public static void ZoomToSelected() { try { Document doc = Application.DocumentManager.MdiActiveDocument; var ed = doc.Editor; Database db = doc.Database; // 1. 获取当前选中对象 PromptSelectionResult selRes = ed.SelectImplied(); if (selRes.Status != PromptStatus.OK) { ed.WriteMessage("\n未选中任何图元。\n"); return; } SelectionSet selection = selRes.Value; if (selection.Count == 0) { ed.WriteMessage("\n选择集为空。\n"); return; } // 2. 计算所有选中图元的合并范围 Extents3d totalExtents = new Extents3d(); bool isFirst = true; using (Transaction tr = db.TransactionManager.StartTransaction()) { foreach (SelectedObject selObj in selection) { if (selObj == null) continue; Entity ent = tr.GetObject(selObj.ObjectId, OpenMode.ForRead) as Entity; if (ent == null) continue; // 获取图元几何范围(自动跳过无范围对象) try { Extents3d entExtents = ent.GeometricExtents; if (isFirst) { totalExtents = entExtents; isFirst = false; } else { totalExtents.AddExtents(entExtents); } } catch { /* 忽略无法获取范围的对象 */ } } tr.Commit(); } if (isFirst) // 表示没有有效范围 { ed.WriteMessage("\n选中的图元没有可计算的几何范围。\n"); return; } // 3. 创建视图变换矩阵 using (ViewTableRecord view = ed.GetCurrentView()) { // 计算范围中心点 Point2d center = new Point2d( (totalExtents.MinPoint.X + totalExtents.MaxPoint.X) / 2, (totalExtents.MinPoint.Y + totalExtents.MaxPoint.Y) / 2 ); // 计算范围尺寸 double width = totalExtents.MaxPoint.X - totalExtents.MinPoint.X; double height = totalExtents.MaxPoint.Y - totalExtents.MinPoint.Y; double margin = Math.Max(width, height) * 0.1; // 增加10%边距 // 设置视图参数 view.CenterPoint = center; view.Width = width + margin; view.Height = height + margin; // 应用视图变换 ed.SetCurrentView(view); ed.UpdateScreen(); } ed.WriteMessage("\n已缩放到选中图元范围。\n"); } catch (Exception ex) { } } #endregion #region 向控制台发送命令 public static void SendCommand(string command) { Document doc = Application.DocumentManager.MdiActiveDocument; using (Transaction tr = doc.TransactionManager.StartTransaction()) { // 操作数据库... doc.SendStringToExecute($"\n{command}\n", true, false, false); tr.Commit(); // 必须提交 } Thread.Sleep(500); } #endregion #region 向控制台发送信息 /// /// 向控制台发送信息 /// /// public static void SendMessage(string msg) { Document doc = Application.DocumentManager.MdiActiveDocument; var ed = Application.DocumentManager.MdiActiveDocument.Editor; ed.WriteMessage($"\n {msg} \n"); } #endregion #region 获取当前图纸名 /// /// 获取当前图纸名 /// public static string GetDwgName() { Document doc = Application.DocumentManager.MdiActiveDocument; return doc == null ? "" : doc.Name; } #endregion #region 读取图元,插入图纸 /// /// 读取图元,插入图纸 /// /// 图元文件路径 /// 传入的位号 /// 返回添加的位号 public static ObjectId InsertExternalDWG(string filePath, string tag, ref string tagNumber) { Document doc = Application.DocumentManager.MdiActiveDocument; var ed = doc.Editor; ObjectId oid = ObjectId.Null; if (!File.Exists(filePath)) { ed.WriteMessage("\n 错误:图元文件不存在!\n"); return oid; } // 获取当前数据库 Database destDb = HostApplicationServices.WorkingDatabase; using (Transaction tr = destDb.TransactionManager.StartTransaction()) { try { // 创建临时数据库读取外部DWG using (Database sourceDb = new Database(false, true)) { sourceDb.ReadDwgFile(filePath, FileOpenMode.OpenForReadAndAllShare, false, null); // 生成唯一块名(避免重名) string blockName = tagNumber = GetUniqueBlockName(destDb, tag); // 将外部DWG转换为块定义 ObjectId blockId = destDb.Insert(blockName, sourceDb, true); // 创建块参照 BlockReference br = new BlockReference( Point3d.Origin, // 插入点(可修改) blockId// bt[blockName] ); // 设置比例和旋转 br.ScaleFactors = new Scale3d(1.0); // 比例因子 br.Rotation = 0.0; // 旋转角度(弧度) // 获取实时鼠标位置 BlockDragJig jig = new BlockDragJig(br, ed); PromptResult dragResult = ed.Drag(jig); // 添加到当前模型空间 BlockTableRecord btr = (BlockTableRecord)tr.GetObject( SymbolUtilityServices.GetBlockModelSpaceId(destDb), OpenMode.ForWrite ); // 处理插入结果 if (dragResult.Status == PromptStatus.OK) { btr.AppendEntity(br); tr.AddNewlyCreatedDBObject(br, true); tr.Commit(); oid = br.Id; ed.WriteMessage($"\n 成功插入图元: {filePath} \n"); } else { tr.Abort(); ed.WriteMessage("\n 操作已取消 \n"); } } // 设置XData CreateRegApp(doc, tagNumber); using (Transaction transaction = destDb.TransactionManager.StartTransaction()) { Entity ent01 = transaction.GetObject(oid, OpenMode.ForWrite) as Entity; ResultBuffer rb = new ResultBuffer(); rb.Add(new TypedValue((int)DxfCode.ExtendedDataRegAppName, tagNumber)); rb.Add(new TypedValue((int)DxfCode.ExtendedDataAsciiString, "TEST")); ent01.XData = rb; transaction.Commit(); } } catch (Exception ex) { tr.Abort(); ed.WriteMessage($"\n错误: {ex.Message}\n"); } } return oid; } //生成唯一块名称 private static string GetUniqueBlockName(Database db, string baseName) { int count = 1; string testName = baseName; using (Transaction tr = db.TransactionManager.StartTransaction()) { BlockTable bt = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead); while (bt.Has(testName)) { testName = $"{baseName}_{count++}"; } tr.Commit(); } return testName; } /// /// 创建XData的注册名称APP /// /// /// public static void CreateRegApp(this Document doc, string appName) { try { using (var documentLock = doc.LockDocument()) { using (Transaction trans = doc.Database.TransactionManager.StartTransaction()) { RegAppTable table = (RegAppTable)trans.GetObject(doc.Database.RegAppTableId, OpenMode.ForWrite, false); if (!table.Has(appName)) { RegAppTableRecord regAppRec = new RegAppTableRecord(); regAppRec.Name = appName; table.Add(regAppRec); trans.AddNewlyCreatedDBObject(regAppRec, true); } trans.Commit(); } } } catch (Exception ex) { throw ex; } } #endregion #region 获取当前图纸选择集数量 /// /// 获取当前图纸选择集数量 /// /// 选择集数量 public static int SelectedCount() { Document doc = Application.DocumentManager.MdiActiveDocument; var ed = doc.Editor; // 获取当前用户选择的元素 PromptSelectionResult selResult = ed.GetSelection(); if (selResult.Status == PromptStatus.OK) { SelectionSet selection = selResult.Value; int count = selection.Count; return count; } else { return 0; } } #endregion #region 获取当前图纸选择集的句柄 /// /// 获取当前选中句柄 /// /// public static List GetSelectedHandles() { List handles = new List(); if (doc == null) { doc = Application.DocumentManager.MdiActiveDocument; } if (ed == null) { ed = doc.Editor; } if (db == null) { db = doc.Database; } // 获取用户选择的元素 PromptSelectionResult selResult = ed.GetSelection(); if (selResult.Status != PromptStatus.OK) { ed.WriteMessage("\n未选中任何元素。"); return handles; } SelectionSet selection = selResult.Value; // 开启事务以安全访问数据库 using (Transaction tr = db.TransactionManager.StartTransaction()) { try { foreach (SelectedObject selectedObj in selection) { ObjectId objId = selectedObj.ObjectId; if (!objId.IsValid) continue; // 跳过无效的 ObjectId // 通过 ObjectId 获取实体对象 Entity entity = tr.GetObject(objId, OpenMode.ForRead) as Entity; if (entity != null && entity.XData != null) { // 获取句柄(Handle 是字符串类型) handles.Add(entity.Handle.ToString()); } } tr.Commit(); } catch (System.Exception ex) { ed.WriteMessage($"\n错误: {ex.Message}"); tr.Abort(); } } if (!handles.Any()) { ed.WriteMessage("\n未找到有效句柄。"); } return handles; } #endregion #region 获取所有打开的图纸名称 /// /// 获取所有打开的图纸名称 /// public static List GetAllOpenDrawingNames() { List names = new List(); DocumentCollection docs = Application.DocumentManager; foreach (Document doc in docs) { // 提取文件名(不包含路径) //string fileName = Path.GetFileName(doc.Database.Filename); //if (!string.IsNullOrEmpty(fileName)) names.Add(doc.Database.Filename); } return names; } #endregion #region 保存图纸 /// /// 保存图纸 /// public static void SaveDwg(string filename) { Document doc = Application.DocumentManager.MdiActiveDocument; Database db = doc.Database; if (db.Filename.Equals(filename)) { using (Transaction tr = doc.TransactionManager.StartTransaction()) { // 操作数据库... tr.Commit(); // 必须提交 } doc.Database.Save(); } } #endregion #region 切换到指定名称的图纸 /// /// 切换到指定名称的图纸 /// public static bool SwitchToDocument(string fileName) { DocumentCollection docs = Application.DocumentManager; var flag = false; foreach (Document doc in docs) { if (doc.Name.Equals(fileName)) { try { // 激活指定的文档 docs.MdiActiveDocument = doc; } catch { } flag = true; break; } } return flag; } #endregion #region 把当前图纸改成只读模式 /// /// 把当前图纸改成只读模式 /// public static void SetDrawingReadOnly(string fileName, bool isReadOnly) { doc = Application.DocumentManager.MdiActiveDocument; ed = doc.Editor; // 检查当前文档是否已保存 db = doc.Database; if (string.IsNullOrEmpty(db.Filename)) { ed.WriteMessage("\n当前文档是未保存的新文件,无法以只读模式重新打开。"); return; } // 关闭当前文档,保存修改部分 string filePath = db.Filename; if (!doc.IsReadOnly) { doc.CloseAndSave(fileName); } else { doc.CloseAndDiscard(); } // 重新打开 Application.DocumentManager.Open(filePath, isReadOnly); doc = Application.DocumentManager.MdiActiveDocument; ed = doc.Editor; db = doc.Database; var msg = isReadOnly ? "只读" : "可编辑"; ed.WriteMessage($"\n当前图纸打开模式变更为:{msg}\n"); } #endregion #region 获取当前图纸所有句柄 /// /// 获取当前图纸XData不为空的所有句柄 /// /// public static List GetHandles() { doc = Application.DocumentManager.MdiActiveDocument; ed = doc.Editor; db = doc.Database; List handles = new List(); try { // 开启事务 using (Transaction tr = db.TransactionManager.StartTransaction()) { // 获取模型空间块表记录 BlockTable bt = tr.GetObject(db.BlockTableId, OpenMode.ForRead) as BlockTable; BlockTableRecord modelSpace = tr.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForRead) as BlockTableRecord; // 遍历模型空间中的所有实体 foreach (ObjectId objId in modelSpace) { Entity entity = tr.GetObject(objId, OpenMode.ForRead) as Entity; if (entity != null && entity.XData != null) { // 提取句柄(十六进制格式) handles.Add(entity.Handle.ToString()); } } tr.Commit(); } } catch (System.Exception ex) { ed.WriteMessage($"\n错误: {ex.Message}"); } return handles; } #endregion #region 关联云线 public static List SelectHandles = new List(); private static bool _isSelectionMode = false; /// /// 关联云线 /// /// public static List StartLineSelection() { List handles = new List(); if (doc == null) { doc = Application.DocumentManager.MdiActiveDocument; } if (ed == null) { ed = doc.Editor; } try { // 启用选择模式 _isSelectionMode = true; //ed.PointMonitor += OnPointMonitor; // 注册鼠标移动事件 // 设置选择过滤器 PromptSelectionOptions pso = new PromptSelectionOptions(); pso.MessageForAdding = "\n选择云线"; // 限制可选对象类型 SelectionFilter filter = new SelectionFilter(new[] { new TypedValue((int)DxfCode.Start, "POLYLINE") // 示例过滤类型 LINE,ARC,CIRCLE,POLYLINE }); // 持续选择模式 while (_isSelectionMode) { PromptSelectionResult res = ed.GetSelection(pso); if (res.Status == PromptStatus.OK) { handles = SelectHandles; break; } else { _isSelectionMode = false; } } } finally { // 清理事件注册 //ed.PointMonitor -= OnPointMonitor; ed.WriteMessage("\n已退出选择模式"); } return handles; } private static void OnPointMonitor(object sender, PointMonitorEventArgs e) { if (!_isSelectionMode) return; var ed = (Bricscad.EditorInput.Editor)sender; //实时显示选择提示 using (Transaction tr = ed.Document.TransactionManager.StartTransaction()) { // 获取当前光标下的对象 FullSubentityPath[] paths = e.Context.GetPickedEntities(); if (paths.Length > 0) { Entity ent = tr.GetObject(paths[0].GetObjectIds()[0], OpenMode.ForWrite) as Entity; if (ent != null) { // 显示动态提示 e.Context.DrawContext.Geometry.Draw(ent); //ent.ColorIndex = 1; } } else { // ed.SetCursor(SysCursor.Arrow); // 非可选区域显示箭头 } tr.Commit(); } } public static void WaitForConfirmation() { PromptPointOptions ptOpts = new PromptPointOptions("\n点击空白处确认或按ESC取消"); ptOpts.AllowNone = true; while (true) { PromptPointResult ptRes = ed.GetPoint(ptOpts); if (ptRes.Status == PromptStatus.Cancel) { _isSelectionMode = false; return; } if (IsClickOnEmptyArea(ptRes.Value)) { //handles = GetSelectedHandles(); //using (Transaction tr = db.TransactionManager.StartTransaction()) //{ // foreach (var kvp in _originalColors) // { // Entity line = tr.GetObject(kvp.Key, OpenMode.ForWrite) as Entity; // if (line != null) // { // line.ColorIndex = kvp.Value; // } // } // tr.Commit(); //} //_originalColors.Clear(); _isSelectionMode = false; return; } ed.WriteMessage("\n请点击空白区域确认选择!"); } } private static bool IsClickOnEmptyArea(Point3d clickPoint) { PromptSelectionResult res = ed.SelectCrossingWindow( clickPoint.TransformBy(ed.CurrentUserCoordinateSystem), clickPoint.TransformBy(ed.CurrentUserCoordinateSystem)); return res.Value == null || res.Value.Count == 0; } #endregion #region 元件关联图元 /// /// 元件关联图元 /// /// public static List StartObjectTypeSelection() { List handles = new List(); if (doc == null) { doc = Application.DocumentManager.MdiActiveDocument; } if (ed == null) { ed = doc.Editor; } try { // 启用选择模式 _isSelectionMode = true; //ed.PointMonitor += OnPointMonitor; // 注册鼠标移动事件 // 设置选择过滤器 PromptSelectionOptions pso = new PromptSelectionOptions(); pso.MessageForAdding = "\n选择图元"; // 持续选择模式 while (_isSelectionMode) { PromptSelectionResult res = ed.GetSelection(pso); if (res.Status == PromptStatus.OK) { handles = SelectHandles; break; } else { _isSelectionMode = false; } } } finally { // 清理事件注册 //ed.PointMonitor -= OnPointMonitor; ed.WriteMessage("\n已退出选择模式"); } return handles; } #endregion #region 设置XDATA /// /// 设置句柄的XData /// /// 句柄列表 /// 位号 public static void SetXdata(List hands, string tagNumber) { Document doc = Application.DocumentManager.MdiActiveDocument; Database db = doc.Database; var ed = doc.Editor; try { // 步骤2:通过句柄查找对象 using (Transaction tr = db.TransactionManager.StartTransaction()) { foreach (var targetHandle in hands) { // 在模型空间查找对象 BlockTableRecord modelSpace = (BlockTableRecord)tr.GetObject( SymbolUtilityServices.GetBlockModelSpaceId(db), OpenMode.ForRead); ObjectId objId = ObjectId.Null; foreach (ObjectId id in modelSpace) { Entity ent = (Entity)tr.GetObject(id, OpenMode.ForRead); if (ent.Handle.ToString() == targetHandle) { objId = id; break; } } if (!objId.IsValid) { //ed.WriteMessage("\n未找到匹配的图元"); return; } Entity entity = (Entity)tr.GetObject(objId, OpenMode.ForWrite); if (entity.XData != null) { continue; } // 步骤3:准备XData ResultBuffer xdata = new ResultBuffer(); xdata.Add(new TypedValue(1001, tagNumber)); // 注册应用名 xdata.Add(new TypedValue(1000, "TEST")); // 字符串 xdata.Add(new TypedValue(1070, 2025)); // 短整型 xdata.Add(new TypedValue(1040, 3.1415)); // 双精度 // 步骤4:写入XData RegAppTable rat = (RegAppTable)tr.GetObject( db.RegAppTableId, OpenMode.ForRead); // 注册应用程序(必须) if (!rat.Has(tagNumber)) { rat.UpgradeOpen(); RegAppTableRecord ratr = new RegAppTableRecord(); ratr.Name = tagNumber; rat.Add(ratr); tr.AddNewlyCreatedDBObject(ratr, true); } entity.XData = xdata; } tr.Commit(); ed.WriteMessage("\nXData设置成功!"); } } catch (Exception ex) { } } #endregion #region 创建或获取图层ID /// /// 创建或获取图层ID /// /// 图层名 /// 颜色,默认:灰色-8 /// public static ObjectId GetOrCreateLayer(string layerName, Color color = null) { var doc = Application.DocumentManager.MdiActiveDocument; var ed = doc.Editor; var db = doc.Database; using (Transaction tr = db.TransactionManager.StartTransaction()) { LayerTable layerTable = (LayerTable)tr.GetObject(db.LayerTableId, OpenMode.ForRead); if (layerTable.Has(layerName)) { return layerTable[layerName]; } layerTable.UpgradeOpen(); LayerTableRecord layer = new LayerTableRecord { Name = layerName }; if (color != null) { layer.Color = color; } ObjectId layerId = layerTable.Add(layer); tr.AddNewlyCreatedDBObject(layer, true); tr.Commit(); return layerId; } } #endregion #region 获取所有图层名 /// /// 获取所有图层名 /// /// public static List GetAllLayerNames() { Document doc = Application.DocumentManager.MdiActiveDocument; Editor ed = doc.Editor; Database db = doc.Database; List listNames = new List(); try { using (Transaction tr = db.TransactionManager.StartTransaction()) { // 获取图层表 LayerTable layerTable = (LayerTable)tr.GetObject( db.LayerTableId, OpenMode.ForRead); // 收集图层名称 foreach (ObjectId layerId in layerTable) { LayerTableRecord layer = (LayerTableRecord)tr.GetObject( layerId, OpenMode.ForRead); listNames.Add(layer.Name); } tr.Commit(); } } catch (Exception ex) { ed.WriteMessage($"\n错误: {ex.Message}"); } return listNames; } #endregion #region 批量设置元素到图层 /// /// 批量设置元素到图层 /// /// 选中的ObjectId元素 /// 底图名 /// 底图颜色 /// 块名 public static void SetEntityToLayer(List listObjectId, string layerName, Color color, string blockName = null) { var doc = Application.DocumentManager.MdiActiveDocument; var ed = doc.Editor; var db = doc.Database; ObjectId layerId = GetOrCreateLayer(layerName, color); using (Transaction tr = db.TransactionManager.StartTransaction()) { //PromptSelectionResult selResult = ed.GetSelection(); //SelectionSet selection = selResult.Value; //foreach (SelectedObject selectedObj in selection) foreach (var objId in listObjectId) { if (!objId.IsValid || objId.IsErased) continue; Entity entity = tr.GetObject(objId, OpenMode.ForWrite) as Entity; if (entity == null) continue; entity.LayerId = layerId; if (color != null) { entity.Color = color; } } if (!string.IsNullOrEmpty(blockName)) { // 1:确定插入点 Point3d insertionPoint = GetInsertionPoint(ed, listObjectId.ToArray()); // 2:创建块定义 ObjectId blockId = CreateBlockDefinition(db, blockName, listObjectId.ToArray(), insertionPoint); // 3:插入块参照 InsertBlockReference(db, blockId, insertionPoint); // 4:删除原始对象 DeleteOriginalEntities(db, listObjectId.ToArray()); } tr.Commit(); } return; } // 获取插入点(自动计算或用户指定) private static Point3d GetInsertionPoint(Editor ed, ObjectId[] selectedIds) { // 自动计算选择集中心点 Extents3d overallExtents = new Extents3d(); using (Transaction tr = ed.Document.Database.TransactionManager.StartTransaction()) { foreach (ObjectId id in selectedIds) { Entity ent = tr.GetObject(id, OpenMode.ForRead) as Entity; if (ent?.GeometricExtents != null) { overallExtents.AddExtents(ent.GeometricExtents); } } tr.Commit(); } Point3d centerPoint = new Point3d( (overallExtents.MinPoint.X + overallExtents.MaxPoint.X) / 2, (overallExtents.MinPoint.Y + overallExtents.MaxPoint.Y) / 2, 0); return centerPoint; //// 提示用户确认或指定插入点 //PromptPointOptions ppo = new PromptPointOptions("\n指定插入点或按Enter使用中心点: "); //ppo.BasePoint = centerPoint; //ppo.UseBasePoint = true; //ppo.AllowNone = true; //PromptPointResult ppr = ed.GetPoint(ppo); //return ppr.Status == PromptStatus.OK ? ppr.Value : centerPoint; } // 创建块定义 private static ObjectId CreateBlockDefinition(Database db, string blockName, ObjectId[] sourceIds, Point3d basePoint) { using (Transaction tr = db.TransactionManager.StartTransaction()) { BlockTable blockTable = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead); // 检查块名是否已存在 //if (blockTable.Has(blockName)) //{ // // 删除现有块定义 // ObjectId existingId = blockTable[blockName]; // BlockTableRecord existingBtr = (BlockTableRecord)tr.GetObject(existingId, OpenMode.ForWrite); // // 安全删除(检查是否被参照) // if (!IsBlockReferenced(db, existingId)) // { // existingBtr.Erase(); // } // else // { // throw new InvalidOperationException($"块 '{blockName}' 已被参照,无法覆盖"); // } //} // 创建新块定义 BlockTableRecord newBtr = new BlockTableRecord { Name = blockName, Origin = basePoint }; // 添加到块表 blockTable.UpgradeOpen(); ObjectId blockId = blockTable.Add(newBtr); tr.AddNewlyCreatedDBObject(newBtr, true); // 克隆并添加源对象到块定义 IdMapping idMap = new IdMapping(); foreach (ObjectId sourceId in sourceIds) { DBObject sourceObj = tr.GetObject(sourceId, OpenMode.ForRead); if (sourceObj is Entity sourceEntity) { Entity clonedEntity = (Entity)sourceEntity.Clone(); newBtr.AppendEntity(clonedEntity); tr.AddNewlyCreatedDBObject(clonedEntity, true); // 调整位置(相对于基点) Vector3d translation = basePoint.GetVectorTo(sourceEntity.GeometricExtents.MinPoint); clonedEntity.TransformBy(Matrix3d.Displacement(translation.Negate())); } } tr.Commit(); return blockId; } } //插入块参照 private static void InsertBlockReference(Database db, ObjectId blockId, Point3d insertionPoint) { using (Transaction tr = db.TransactionManager.StartTransaction()) { BlockTableRecord modelSpace = (BlockTableRecord)tr.GetObject( SymbolUtilityServices.GetBlockModelSpaceId(db), OpenMode.ForWrite); BlockReference blockRef = new BlockReference(insertionPoint, blockId); modelSpace.AppendEntity(blockRef); tr.AddNewlyCreatedDBObject(blockRef, true); tr.Commit(); } } // 删除原始实体(可选) private static void DeleteOriginalEntities(Database db, ObjectId[] sourceIds) { using (Transaction tr = db.TransactionManager.StartTransaction()) { foreach (ObjectId id in sourceIds) { if (id.IsValid && !id.IsErased) { DBObject obj = tr.GetObject(id, OpenMode.ForWrite); obj.Erase(); } } tr.Commit(); } } // 检查块是否被参照 private static bool IsBlockReferenced(Database db, ObjectId blockId) { using (Transaction tr = db.TransactionManager.StartTransaction()) { BlockTableRecord blockDef = (BlockTableRecord)tr.GetObject(blockId, OpenMode.ForRead); return blockDef.GetBlockReferenceIds(true, false).Count > 0; } } #endregion #region 获取当前图纸选择集的元素 /// /// 获取当前选中元素 /// /// public static List GetSelectedObjectId() { List result = new List(); var doc = Application.DocumentManager.MdiActiveDocument; var ed = doc.Editor; var db = doc.Database; // 获取用户选择的元素 PromptSelectionResult selResult = ed.GetSelection(); if (selResult.Status != PromptStatus.OK) { ed.WriteMessage("\n未选中任何元素。"); return result; } SelectionSet selection = selResult.Value; // 开启事务以安全访问数据库 using (Transaction tr = db.TransactionManager.StartTransaction()) { try { foreach (SelectedObject selectedObj in selection) { ObjectId objId = selectedObj.ObjectId; if (!objId.IsValid) continue; // 跳过无效的 ObjectId result.Add(objId); } tr.Commit(); } catch (System.Exception ex) { ed.WriteMessage($"\n错误: {ex.Message}"); tr.Abort(); } } if (!result.Any()) { ed.WriteMessage("\n未找到有效句柄。"); } return result; } #endregion #region 检查块名是否已存在 /// /// 检查块名是否已存在 /// /// 块名 /// public static bool CheckHasBlockName(string blockName) { var doc = Application.DocumentManager.MdiActiveDocument; var ed = doc.Editor; var db = doc.Database; using (Transaction tr = db.TransactionManager.StartTransaction()) { BlockTable blockTable = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead); if (blockTable.Has(blockName)) { return true; } else { return false; } } } #endregion } }