ADN Open CIS
Сообщество программистов Autodesk в СНГ

18/05/2016

Как обновить выбранные поля не выполняя регенерацию всего чертежа

Вопрос: Мне необходимо выполнить обновление некоторых полей в чертеже, но мне не хотелось бы выполнять полную регенерацию. Как это можно осуществить?

Ответ: В ObjectARX есть семейство функций acdbEvaluateFields, которые и позволяют обновить поля в чертеже. Пример использования функции acdbEvaluateFields смотрите ниже:

Код - C++: [Выделить]
  1. static void UPDFLD () {
  2.   Acad::ErrorStatus es;
  3.   ads_name en; ads_point p;
  4.   if (acedEntSel(_T("\nВыберите примитив: "), en, p) == RTNORM) {
  5.     AcDbObjectId eId; acdbGetObjectId(eId, en);
  6.     AcDbEntityPointer pEnt(eId, AcDb::kForRead);
  7.     if ((es = pEnt.openStatus()) != Acad::eOk) {
  8.       acutPrintf(_T("\nОшибка открытия: %s"),
  9.         acadErrorStatusText(pEnt.openStatus()));
  10.       return;
  11.     }
  12.     int i1 = 0, i2 = 0;
  13.     Acad::ErrorStatus es = acdbEvaluateFields(eId,
  14.       AcDbField::EvalContext::kRegen, NULL, NULL, AcFd::kEvalRecursive, &i1, &i2);
  15.   }
  16. }
  17.  

Если использовать AutoCAD .NET API, то имеется возможность обновить все поля в чертеже при помощи метода Database.EvaluateFields. Чтобы обновить выбранные поля придётся воспользоваться P/Invoke для acdbEvaluateFields. Так как сигнатура у этой функции не очень тривиальная, то привожу пример:

Код - C#: [Выделить]
  1. using System;
  2. using Autodesk.AutoCAD.Runtime;
  3. using Autodesk.AutoCAD.ApplicationServices;
  4. using Autodesk.AutoCAD.DatabaseServices;
  5. using Autodesk.AutoCAD.Geometry;
  6. using Autodesk.AutoCAD.EditorInput;
  7. using System.Runtime.InteropServices;
  8.  
  9.  
  10. [assembly: CommandClass(typeof(AutoCAD_CSharp_plug_in5.MyCommands))]
  11.  
  12. namespace AutoCAD_CSharp_plug_in5
  13. {
  14.   public class MyCommands
  15.   {
  16.     #region PInvoke acdbEvaluateFields
  17.     // Acad::ErrorStatus acdbEvaluateFields (
  18.     //   const AcDbObjectId& objId,
  19.     //   int nContext,
  20.     //   const ACHAR* pszPropName = NULL,
  21.     //   AcDbDatabase* pDb        = NULL,
  22.     //   AcFd::EvalFields nEvalFlag = AcFd::kEvalRecursive,
  23.     //   int* pNumFound           = NULL,
  24.     //   int* pNumEvaluated       = NULL
  25.     // );
  26.     // AutoCAD 2013 и 2014 x64
  27.     const string acdbEvaluateFields_x64 =
  28.       "?acdbEvaluateFields@@YA?AW4ErrorStatus@Acad@@AEBVAcDbObjectId@@HPEB_WPEAVAcDbDatabase@@W4EvalFields@AcFd@@PEAH4@Z";
  29.     const string acdbEvaluateFields_x32 =
  30.       "?acdbEvaluateFields@@YA?AW4ErrorStatus@Acad@@ABVAcDbObjectId@@HPB_WPAVAcDbDatabase@@W4EvalFields@AcFd@@PAH4@Z";
  31.     [DllImport("acdb19.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode, ExactSpelling = true,
  32.       EntryPoint = acdbEvaluateFields_x64)]
  33.     private static extern Int32 acdbEvaluateFields19x64(ref ObjectId id, Int32 context,
  34.       IntPtr pszPropName, IntPtr db, Int32 eval, IntPtr i1, IntPtr i2);
  35.     // AutoCAD 2013 и 2014 x86
  36.     [DllImport("acdb19.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode, ExactSpelling = true,
  37.     EntryPoint = acdbEvaluateFields_x32)]
  38.     private static extern Int32 acdbEvaluateFields19x32(ref ObjectId id, Int32 context,
  39.       IntPtr pszPropName, IntPtr db, Int32 eval, IntPtr i1, IntPtr i2);
  40.     // AutoCAD 2015 и 2016 x64
  41.     [DllImport("acdb20.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode, ExactSpelling = true,
  42.       EntryPoint = acdbEvaluateFields_x64)]
  43.     private static extern Int32 acdbEvaluateFields20x64(ref ObjectId id, Int32 context,
  44.       IntPtr pszPropName, IntPtr db, Int32 eval, IntPtr i1, IntPtr i2);
  45.     // AutoCAD 2015 и 2016 x86
  46.     [DllImport("acdb20.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode, ExactSpelling = true,
  47.     EntryPoint = acdbEvaluateFields_x32)]
  48.     private static extern Int32 acdbEvaluateFields20x32(ref ObjectId id, Int32 context,
  49.       IntPtr pszPropName, IntPtr db, Int32 eval, IntPtr i1, IntPtr i2);
  50.     // AutoCAD 2017 x64
  51.     [DllImport("acdb21.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode, ExactSpelling = true,
  52.       EntryPoint = acdbEvaluateFields_x64)]
  53.     private static extern Int32 acdbEvaluateFields21x64(ref ObjectId id, Int32 context,
  54.       IntPtr pszPropName, IntPtr db, Int32 eval, IntPtr i1, IntPtr i2);
  55.     // AutoCAD 2017x86
  56.     [DllImport("acdb21.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode, ExactSpelling = true,
  57.     EntryPoint = acdbEvaluateFields_x32)]
  58.     private static extern Int32 acdbEvaluateFields21x32(ref ObjectId id, Int32 context,
  59.       IntPtr pszPropName, IntPtr db, Int32 eval, IntPtr i1, IntPtr i2);
  60.     #endregion
  61.  
  62.     private Int32 acdbEvaluateFields(ref ObjectId id, Int32 context)
  63.     {
  64.       switch (Application.Version.Major)
  65.       {
  66.         case 21:
  67.           if (IntPtr.Size == 8)
  68.             return acdbEvaluateFields21x64(ref id, 16, IntPtr.Zero, IntPtr.Zero, 1, IntPtr.Zero, IntPtr.Zero);
  69.           else
  70.             return acdbEvaluateFields21x32(ref id, 16, IntPtr.Zero, IntPtr.Zero, 1, IntPtr.Zero, IntPtr.Zero);
  71.         case 20:
  72.           if (IntPtr.Size == 8)
  73.             return acdbEvaluateFields20x64(ref id, 16, IntPtr.Zero, IntPtr.Zero, 1, IntPtr.Zero, IntPtr.Zero);
  74.           else
  75.             return acdbEvaluateFields20x32(ref id, 16, IntPtr.Zero, IntPtr.Zero, 1, IntPtr.Zero, IntPtr.Zero);
  76.         case 19:
  77.           if (IntPtr.Size == 8)
  78.             return acdbEvaluateFields19x64(ref id, 16, IntPtr.Zero, IntPtr.Zero, 1, IntPtr.Zero, IntPtr.Zero);
  79.           else
  80.             return acdbEvaluateFields19x32(ref id, 16, IntPtr.Zero, IntPtr.Zero, 1, IntPtr.Zero, IntPtr.Zero);
  81.         default:
  82.           break;
  83.       }
  84.       return 0;
  85.     }
  86.  
  87.     [CommandMethod("Test", "Test", CommandFlags.Modal)]
  88.     public void Test()
  89.     {
  90.       // Обновление полей в блоке
  91.       Document doc = Application.DocumentManager.MdiActiveDocument;
  92.       Database db = doc.Database;
  93.       Editor ed = doc.Editor;
  94.  
  95.       var sel = ed.GetEntity("Выбери блок для обновления полей в атрибутах: ");
  96.       if (sel.Status == PromptStatus.OK)
  97.       {
  98.         ObjectId id = sel.ObjectId;
  99.         acdbEvaluateFields(ref id, 16);
  100.       }
  101.     }
  102.   }
  103. }
  104.  

 

Видео обновления полей.

Автор: Александр Ривилис

Обсуждение: http://adn-cis.org/forum/index.php?topic=7092

Опубликовано 18.05.2016
Отредактировано 18.05.2016 в 19:47:43