Как найти все поля (Field) в чертеже?
Словарь именованных объектов (NOD) в базе данных содержит запись “ACAD_FIELDLIST” если чертеж содержит хотя бы одно поле. Эта запись содержит записи класса “AcDbFieldList”, который к сожалению не доступен ни в ObjectARX, ни в .NET API.
Каждый объект AcDbField обычно доступен из словаря расширения (Extension Dictionary). Например, если мы создаём MText содержащий поле, мы можем получить доступ к MTextyou и посмотреть AcDbField в его ExtensionDictionary.
Чтобы получить все поля непосредственно – единственный путь получить все TypedValue (DxfCode – пары значений) из нашего AcDbFieldList, пройдя по ним по всем и отобрав все, у которых код = 330 и тип AcDbField.
Нам придётся положится на старый добрый вызов P/Invoked для arx-методов, так что код становится зависимым от версии AutoCAD. Пример ниже ориентирован на R19 (т.е. AutoCAD 2013 и 2014). Для AutoCAD 2015 и 2016 потребуется замена "acdb19.dll" на "acdb20.dll"
- class ImportsR19
- {
- public struct ads_name
- {
- public IntPtr a;
- public IntPtr b;
- };
- [DllImport("acdb19.dll",
- CallingConvention = CallingConvention.Cdecl,
- EntryPoint = "?acdbGetAdsName@@YA?AW4ErrorStatus@Acad@@AAY01JVAcDbObjectId@@@Z")]
- public static extern int acdbGetAdsName32(
- ref ads_name name,
- ObjectId objId);
- [DllImport("acdb19.dll",
- CallingConvention = CallingConvention.Cdecl,
- EntryPoint = "?acdbGetAdsName@@YA?AW4ErrorStatus@Acad@@AEAY01_JVAcDbObjectId@@@Z")]
- public static extern int acdbGetAdsName64(
- ref ads_name name,
- ObjectId objId);
- public static int acdbGetAdsName(
- ref ads_name name,
- ObjectId objId)
- {
- if (Marshal.SizeOf(IntPtr.Zero) > 4)
- return acdbGetAdsName64(ref name, objId);
- return acdbGetAdsName32(ref name, objId);
- }
- [DllImport("accore.dll",
- CharSet = CharSet.Unicode,
- CallingConvention = CallingConvention.Cdecl,
- EntryPoint = "acdbEntGet")]
- public static extern System.IntPtr acdbEntGet(
- ref ads_name ename);
- public static System.Collections.Generic.List<TypedValue>
- acdbEntGetTypedValues(ObjectId id)
- {
- System.Collections.Generic.List<TypedValue> result =
- new System.Collections.Generic.List<TypedValue>();
- ads_name name = new ads_name();
- int res = acdbGetAdsName(ref name, id);
- ResultBuffer rb = new ResultBuffer();
- Autodesk.AutoCAD.Runtime.Interop.AttachUnmanagedObject(
- rb,
- acdbEntGet(ref name),
- true);
- ResultBufferEnumerator iter = rb.GetEnumerator();
- while (iter.MoveNext())
- {
- result.Add((TypedValue)iter.Current);
- }
- return result;
- }
- }
- [CommandMethod("FieldList")]
- public void FieldList()
- {
- Document doc = Application.DocumentManager.MdiActiveDocument;
- Database db = doc.Database;
- Editor ed = doc.Editor;
- using (var tx = db.TransactionManager.StartTransaction())
- {
- var nod = tx.GetObject(
- db.NamedObjectsDictionaryId,
- OpenMode.ForRead) as DBDictionary;
- if (!nod.Contains("ACAD_FIELDLIST"))
- {
- ed.WriteMessage("\nВ чертеже нет полей...");
- return;
- }
- var id = nod.GetAt("ACAD_FIELDLIST");
- List<TypedValue> dxf = ImportsR19.acdbEntGetTypedValues(id);
- foreach (var entry in dxf)
- {
- if (entry.TypeCode == 330)
- {
- ObjectId objId = (ObjectId)entry.Value;
- if (objId.ObjectClass.Name == "AcDbField")
- {
- Field field = tx.GetObject(
- objId,
- OpenMode.ForWrite) as Field;
- field.Evaluate();
- ed.WriteMessage(
- "\n - Формат: " + field.Format +
- " Значение: " +
- field.GetStringValue());
- }
- }
- }
- }
- }
Источник: http://adndevblog.typepad.com/autocad/2014/07/how-to-find-all-fields-in-a-drawing.html
Обсуждение: http://adn-cis.org/forum/index.php?topic=2722
Опубликовано 19.05.2015