using System; using System.Collections.Generic; using Autodesk.AutoCAD.DatabaseServices; using CadParamPluging.Common; using Autodesk.AutoCAD.ApplicationServices; using Autodesk.AutoCAD.EditorInput; namespace CadParamPluging.Cad { /// /// 辅助类:用于操作 AutoCAD 的扩展字典 (Extension Dictionary / NOD) /// public static class DictionaryHelper { // 我们在 NOD (Named Objects Dictionary) 中使用的根字典名称 private const string AppDictionaryName = "CadParamPluging_Data"; // 存储参数的 XRecord 名称 private const string ParamsRecordName = "DrawingParams"; /// /// 将参数包保存到当前文档的 Extension Dictionary (NOD) 中 /// public static void SaveParams(Database db, ParamBag bag) { if (db == null || bag == null || bag.Items == null || bag.Items.Count == 0) { return; } using (var tr = db.TransactionManager.StartTransaction()) { var nod = (DBDictionary)tr.GetObject(db.NamedObjectsDictionaryId, OpenMode.ForWrite); // 1. 获取或创建我们的应用专属字典 DBDictionary appDict; if (nod.Contains(AppDictionaryName)) { appDict = (DBDictionary)tr.GetObject(nod.GetAt(AppDictionaryName), OpenMode.ForWrite); } else { appDict = new DBDictionary(); nod.SetAt(AppDictionaryName, appDict); tr.AddNewlyCreatedDBObject(appDict, true); } // 2. 准备数据 (XRecord) // XRecord 本质上是一个 ResultBuffer 链表 // 我们使用 DxfCode.Text (1000) 来存储 key=value 字符串 var rb = new ResultBuffer(); // serialize user inputs into a single text block var fullString = ""; foreach (var item in bag.Items) { if (!string.IsNullOrWhiteSpace(item.Key)) { fullString += $"{item.Key}={item.Value ?? string.Empty}\n"; } } // DxfCode.Text has a 255-character limit in AutoCAD ResultBuffer. // We use code 301 (XTextString) and chunk the string to support any length. var temp = fullString; while (temp.Length > 0) { var chunk = temp.Length > 250 ? temp.Substring(0, 250) : temp; rb.Add(new TypedValue(301, chunk)); // 301 = DxfCode.XTextString temp = temp.Length > 250 ? temp.Substring(250) : ""; } try { // Application.DocumentManager.MdiActiveDocument.Editor.WriteMessage($"\n[CadParamPluging] Saving Params: Count={bag.Items.Count}\n"); } catch {} var xrec = new Xrecord(); xrec.Data = rb; // 如果已存在则覆盖,否则添加 if (appDict.Contains(ParamsRecordName)) { // 为了简单起见,这里选择直接删除旧的再添加新的,或者覆盖 // 如果用 GetObject 获取旧的 xrec,可以直接 xrec.Data = rb var oldId = appDict.GetAt(ParamsRecordName); var oldXrec = (Xrecord)tr.GetObject(oldId, OpenMode.ForWrite); oldXrec.Data = rb; } else { appDict.SetAt(ParamsRecordName, xrec); tr.AddNewlyCreatedDBObject(xrec, true); } tr.Commit(); } } /// /// (可选) 从当前文档读取参数 /// public static ParamBag ReadParams(Database db) { var bag = new ParamBag(); using (var tr = db.TransactionManager.StartTransaction()) { var nod = (DBDictionary)tr.GetObject(db.NamedObjectsDictionaryId, OpenMode.ForRead); if (!nod.Contains(AppDictionaryName)) { return bag; } var appDict = (DBDictionary)tr.GetObject(nod.GetAt(AppDictionaryName), OpenMode.ForRead); if (!appDict.Contains(ParamsRecordName)) { return bag; } var xrec = (Xrecord)tr.GetObject(appDict.GetAt(ParamsRecordName), OpenMode.ForRead); var rb = xrec.Data; if (rb == null) { return bag; } var sb = new System.Text.StringBuilder(); bool hasCode301 = false; // Read chunks from new format foreach (var tv in rb) { if (tv.TypeCode == 301) { hasCode301 = true; if (tv.Value is string s) { sb.Append(s); } } } if (hasCode301) { var fullText = sb.ToString(); foreach (var line in fullText.Split(new[] { '\n' }, StringSplitOptions.RemoveEmptyEntries)) { var parts = line.Split(new[] { '=' }, 2); if (parts.Length == 2) bag.Set(parts[0], parts[1]); else if (parts.Length == 1) bag.Set(parts[0], ""); } return bag; } // Fallback to read from old Code 1 format foreach (var tv in rb) { if (tv.TypeCode == (int)DxfCode.Text) { var line = tv.Value as string; if (!string.IsNullOrWhiteSpace(line)) { var parts = line.Split(new[] { '=' }, 2); if (parts.Length == 2) { bag.Set(parts[0], parts[1]); try { // Log Hardness read } catch {} } else if (parts.Length == 1) { bag.Set(parts[0], ""); } } } } } return bag; } } }