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

ADN Club => AutoCAD .NET API => Тема начата: Максим Маркевич от 19-08-2016, 22:48:44

Название: Как грамотно выбрать только динамические блоки с конкретными именами?
Отправлено: Максим Маркевич от 19-08-2016, 22:48:44
Всем привет. Столкнулся с такой задачкой..
Выделяю чертеж, на котором может быть все, что угодно (любые объекты Autocad, прокси и прочее), хочу получить доступ только к динамическим блокам с определенным именем.
Когда задача была получать только динамические блоки, тогда делал я вот так:
Код - C# [Выбрать]
  1. [CommandMethod("Select")]
  2. public void Select()
  3. {
  4.     var doc = Application.DocumentManager.MdiActiveDocument;
  5.     if (doc == null)
  6.         return;
  7.     var db = doc.Database;
  8.     var ed = doc.Editor;
  9.     using (doc.LockDocument())
  10.     {
  11.         using (var tr = db.TransactionManager.StartTransaction())
  12.         {
  13.             var acSelSetPrompt = ed.GetSelection() as PromptSelectionResult;
  14.             if (acSelSetPrompt.Status == PromptStatus.OK)
  15.             {
  16.                 var acSSet = acSelSetPrompt.Value;
  17.                 foreach (SelectedObject acSelSetObj in acSSet)
  18.                 {
  19.                     if (acSelSetObj != null)
  20.                     {
  21.                         var blkRef = tr.GetObject(acSelSetObj.ObjectId, OpenMode.ForWrite) as BlockReference;
  22.                         if (blkRef.IsDynamicBlock == true && blkRef != null)
  23.                         {
  24.                             Application.ShowAlertDialog("Есть!!!");
  25.                         }
  26.                     }
  27.                 }
  28.             }
  29.             tr.Commit();
  30.         }
  31.     }
  32. }
Когда стало необходимо получить динамический блок с конкретным именем, то я добавил следующее:
Код - C# [Выбрать]
  1. [CommandMethod("Select")]
  2. public void Select()
  3. {
  4.     var doc = Application.DocumentManager.MdiActiveDocument;
  5.     if (doc == null)
  6.         return;
  7.     var db = doc.Database;
  8.     var ed = doc.Editor;
  9.     using (doc.LockDocument())
  10.     {
  11.         using (var tr = db.TransactionManager.StartTransaction())
  12.         {
  13.             var acSelSetPrompt = ed.GetSelection() as PromptSelectionResult;
  14.             if (acSelSetPrompt.Status == PromptStatus.OK)
  15.             {
  16.                 var acSSet = acSelSetPrompt.Value;
  17.                 foreach (SelectedObject acSelSetObj in acSSet)
  18.                 {
  19.                     if (acSelSetObj != null)
  20.                     {
  21.                         var blkRef = tr.GetObject(acSelSetObj.ObjectId, OpenMode.ForWrite) as BlockReference;
  22.                         var block = (BlockTableRecord)tr.GetObject(blkRef.DynamicBlockTableRecord, OpenMode.ForRead);
  23.                         if (blkRef.IsDynamicBlock == true && blkRef != null && block.Name == "Имя блока")
  24.                         {
  25.                             Application.ShowAlertDialog("Есть!!!");
  26.                         }
  27.                     }
  28.                 }
  29.             }
  30.             tr.Commit();
  31.         }
  32.     }
  33. }
Ну и что-то не то добавил :), так как, при выделении, например, полилинии, я получаю фатальную ошибку, не могу понять, почему?
Буду рад любой помощи и пояснениям. Заранее, спасибо.
Название: Re: Как грамотно выбрать только динамические блоки с конкретными именами?
Отправлено: Александр Ривилис от 19-08-2016, 22:52:25
У тебя же нет проверки на null значения blkRef после строки 21. Если попадает не BlockReference, то значение blkRef становится равным null. Ну и дальше Exception...
И зачем отрываешь ForWrite если не модифицируешь вставку блока?
Название: Re: Как грамотно выбрать только динамические блоки с конкретными именами?
Отправлено: Максим Маркевич от 19-08-2016, 23:13:03
У тебя же нет проверки на null значения blkRef после строки 21. Если попадает не BlockReference, то значение blkRef становится равным null. Ну и дальше Exception...
Вот же. Стоило поспать, прежде чем тему создавать.  :) Спасибо за оперативность!!
И зачем отрываешь ForWrite если не модифицируешь вставку блока?
В своем коде я модифицирую, для темы делал наглядный пример, не подправил.
Название: Re: Как грамотно выбрать только динамические блоки с конкретными именами?
Отправлено: Александр Ривилис от 19-08-2016, 23:17:29
Кстати, еще одно замечание. Такую проверку лучше не делать:
Код - C# [Выбрать]
  1. if (blkRef.IsDynamicBlock == true) {
  2. //...
  3. }
  4.  
Как оказалось не всегда у динамических блоков свойство IsDynamicBlock установлено в true. В частности если у блока разные масштабные коэффициенты по X,Y,Z. При этом во всём остальном поведение блока как у динамического. Я когда-то передавал эту информацию в  Autodesk.
Название: Re: Как грамотно выбрать только динамические блоки с конкретными именами?
Отправлено: Максим Маркевич от 19-08-2016, 23:38:51
Как оказалось не всегда у динамических блоков свойство IsDynamicBlock установлено в true. В частности если у блока разные масштабные коэффициенты по X,Y,Z. При этом во всём остальном поведение блока как у динамического. Я когда-то передавал эту информацию в  Autodesk.
Да ладно? Сейчас проверю..

Вот это прикол! :)
Спасибо, что предупредили.
Получается, смысл проверки совсем отпадает или можно сделать что-то аналогичное?
Название: Re: Как грамотно выбрать только динамические блоки с конкретными именами?
Отправлено: Александр Ривилис от 19-08-2016, 23:53:56
Получается, смысл проверки совсем отпадает или можно сделать что-то аналогичное?
Ну в общем то отпадает. Фактически можешь проверять на количество элементов в коллекции BlockReference.DynamicBlockReferencePropertyCollection - если > 0, то блок динамический.
Название: Re: Как грамотно выбрать только динамические блоки с конкретными именами?
Отправлено: Максим Маркевич от 20-08-2016, 03:29:36
Фактически можешь проверять на количество элементов в коллекции BlockReference.DynamicBlockReferencePropertyCollection - если > 0, то блок динамический.
Точно!! Спасибо. :)