Атрибуты у вхождений блока

Автор Тема: Атрибуты у вхождений блока  (Прочитано 12330 раз)

0 Пользователей и 1 Гость просматривают эту тему.

Тема содержит сообщение с Решением. Нажмите здесь чтобы посмотреть его.

Оффлайн JohnLenninАвтор темы

  • .Net Teapot
  • ADN OPEN
  • Сообщений: 49
  • Карма: 1
Добрый день, коллеги!
Жизнь заставила снова сесть за VS и доработать старый плагин для AutoCAD. Если раньше надо было читать и править уже существующие атрибуты и с этим мне уважаемые коллеги на форуме помогли, спасибо кстати им за это огромное!
Прошлая тема здесь: http://adn-cis.org/forum/index.php?topic=4285.0
Но в это раз, никак до меня не может дойти, как к конкретной выбранной BlockReference (у которой вообще нет атрибутов) добавить пару тройку атрибутов. Причем может быть так, что у одного и того же блока в разных вставках могут быть разные атрибуты.
AtributeDefinition я создаю:
Код - C# [Выбрать]
  1.             AttributeDefinition attrDef = new AttributeDefinition();
  2.             attrDef.Tag = AttrName;
  3.             attrDef.TextString = AttrValue;
  4.             attrDef.Prompt = AttrValue;
  5.             attrDef.LockPositionInBlock = true;
  6.             attrDef.Visible = Visible;
  7.             attrDef.Height = 3;
  8.             attrDef.TextStyleId = doc.Database.Textstyle;
  9.             attrDef.Verifiable = false;
  10.             attrDef.Position = new Point3d(6.0, 0.5, 0);
  11.             attrDef.AdjustAlignment(doc.Database);
  12.  
А дальше? Как его приаттачить к конкретной BlockReference?
Прошу прощения, коллеги, за возможно дилетантский вопрос, но я действительно редко (пару раз в год) забегаю в VS и только для того, чтобы доработать плагин для AutoCAD.

Оффлайн Александр Пекшев aka Modis

  • ADN Club
  • *****
  • Сообщений: 1658
  • Карма: 366
  • Отец modplus.org
    • ModPlus
Re: Атрибуты у вхождений блока
« Ответ #1 : 15-02-2017, 13:46:50 »
Нужно сначала добавить определение атрибута в определение блока, а потом уже добавлять вхождение атрибута во вхождение блока - пример в справке

Оффлайн JohnLenninАвтор темы

  • .Net Teapot
  • ADN OPEN
  • Сообщений: 49
  • Карма: 1
Re: Атрибуты у вхождений блока
« Ответ #2 : 18-02-2017, 13:52:21 »
Спасибо за подсказку на справку - посмотрел, но только все равно не получается. В справке написано как добавлять атрибуты к только что созданным объектам, а к существующим команда acTrans.AddNewlyCreatedDBObject(acBlkTblRec, true) не прокатывает в 47 строке ошибка и в 98 соответственно.
Что-то я совсем запутался, может там надо кроме определения атрибутов AttributeDefinition создать еще и ссылку AttributeReference и ее приаттачить к выбранной ссылке блока? В общем совсем что-то туплю, менять атрибуты я умею, создавать новые блоки с атрибутами тоже (спасибо за ссылку на справку!!!), а вот приаттачить к существующей BlockReference не получается. До конца не понимаю механизма как это все работает, что за чем надо создавать и что к чему привязывать.

Код - C# [Выбрать]
  1.         public static int LetsMadeAnAttributeToSelectedBR(long brHandle, Document doc, string AttrName, string AttrValue)
  2.         {
  3.             int AttrCreatedCount = 0;
  4.             Database acCurDb = doc.Database;            
  5.             using (DocumentLock acLckDoc = doc.LockDocument())
  6.             {
  7.                 using (Transaction acTrans = acCurDb.TransactionManager.StartTransaction())
  8.                 {
  9.                     // Open the Block table for write
  10.                     BlockTable acBlkTbl;
  11.                     acBlkTbl = acTrans.GetObject(acCurDb.BlockTableId, OpenMode.ForWrite) as BlockTable;
  12.                     // Open the Block table record Model space for write
  13.                     BlockTableRecord acBlkTblRec;
  14.                     acBlkTblRec = acTrans.GetObject(acBlkTbl[BlockTableRecord.ModelSpace], OpenMode.ForWrite) as BlockTableRecord;
  15.                     //BlockReference nbr = acBlkTblRec .geto
  16.                     Handle hBlock = new Handle(brHandle);
  17.                     ObjectId idBlock;
  18.                     BlockReference brBlock = null;
  19.                     if (acCurDb.TryGetObjectId(hBlock, out idBlock))
  20.                     {
  21.                         brBlock = idBlock.GetObject(OpenMode.ForWrite) as BlockReference;
  22.                     }
  23.                     // проверяем есть ли блок с таким handle
  24.                     if (brBlock == null)
  25.                     { return 0; }
  26.  
  27.                     // получаем атрибуты
  28.                     AttributeCollection attrC = null;
  29.                     attrC = brBlock.AttributeCollection;
  30.                     // проверяем есть ли атрибуты
  31.                     if (attrC.Count == 0)
  32.                     {
  33.                         // создаем атрибут
  34.                         using (AttributeDefinition acAttDef = new AttributeDefinition())
  35.                         {
  36.                             acAttDef.Position = new Point3d(0, 0, 0);
  37.                             acAttDef.Visible = true;
  38.                             acAttDef.Verifiable = false;
  39.                             acAttDef.Prompt = AttrValue;
  40.                             acAttDef.Tag = AttrName;
  41.                             acAttDef.TextString = AttrValue;
  42.                             acAttDef.Height = 5;
  43.                             acAttDef.Justify = AttachmentPoint.BottomLeft;
  44.                             acBlkTblRec.AppendEntity(acAttDef);
  45.                             acBlkTbl.UpgradeOpen();
  46.                             acBlkTbl.Add(acBlkTblRec);
  47.                             acTrans.AddNewlyCreatedDBObject(acBlkTblRec, true);
  48.                             AttrCreatedCount++;
  49.                         }
  50.                     }
  51.                     else
  52.                     {                        
  53.                         // смотрим есть ли такой атрибут
  54.                         foreach (ObjectId idAtrRef in attrC)
  55.                         {
  56.                             // если есть, то меняем значение
  57.                             using (var atrRef = idAtrRef.GetObject(OpenMode.ForWrite) as AttributeReference)
  58.                             {
  59.                                 // если блок динамический то добавляем только активные атрибуты
  60.                                 if (brBlock.IsDynamicBlock)
  61.                                 {
  62.                                     if (atrRef != null && atrRef.Visible)
  63.                                         if (atrRef.Tag== AttrName)
  64.                                         {
  65.                                             atrRef.TextString = AttrValue;
  66.                                             AttrCreatedCount++;
  67.                                         }
  68.                                 }
  69.                                 else
  70.                                 // если обычный, то все
  71.                                 {
  72.                                     if (atrRef != null)
  73.                                         if (atrRef.Tag == AttrName)
  74.                                         {
  75.                                             atrRef.TextString = AttrValue;
  76.                                             AttrCreatedCount++;
  77.                                         }
  78.                                 }
  79.                             } // using
  80.                         }
  81.                         // если нет, то создаем атрибут
  82.                         if (AttrCreatedCount == 0)
  83.                         {
  84.                             // создаем атрибут
  85.                             using (AttributeDefinition acAttDef = new AttributeDefinition())
  86.                             {
  87.                                 acAttDef.Position = new Point3d(0, 0, 0);
  88.                                 acAttDef.Visible = true;
  89.                                 acAttDef.Verifiable = false;
  90.                                 acAttDef.Prompt = AttrValue;
  91.                                 acAttDef.Tag = AttrName;
  92.                                 acAttDef.TextString = AttrValue;
  93.                                 acAttDef.Height = 5;
  94.                                 acAttDef.Justify = AttachmentPoint.BottomLeft;
  95.                                 acBlkTblRec.AppendEntity(acAttDef);
  96.                                 acBlkTbl.UpgradeOpen();
  97.                                 acBlkTbl.Add(acBlkTblRec);
  98.                                 acTrans.AddNewlyCreatedDBObject(acBlkTblRec, true);
  99.                                 AttrCreatedCount++;
  100.                             }
  101.                         }                        
  102.                     }
  103.                     acTrans.Commit();                    
  104.                 }
  105.             }
  106.             return AttrCreatedCount;
  107.         }
  108.  

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: Атрибуты у вхождений блока
« Ответ #3 : 18-02-2017, 14:00:12 »
Что-то я совсем запутался, может там надо кроме определения атрибутов AttributeDefinition создать еще и ссылку AttributeReference и ее приаттачить к выбранной ссылке блока?
Конечно.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Александр Пекшев aka Modis

  • ADN Club
  • *****
  • Сообщений: 1658
  • Карма: 366
  • Отец modplus.org
    • ModPlus
Re: Атрибуты у вхождений блока
« Ответ #4 : 18-02-2017, 14:30:47 »
Вот еще посмотрите

Оффлайн JohnLenninАвтор темы

  • .Net Teapot
  • ADN OPEN
  • Сообщений: 49
  • Карма: 1
Re: Атрибуты у вхождений блока
« Ответ #5 : 18-02-2017, 15:08:45 »
Ура! Заработало! Действительно надо было AttributeReference создать и его применить!!!
Код - C# [Выбрать]
  1.                                 AttributeReference ar = new AttributeReference();
  2.                                 ar.SetAttributeFromBlock(acAttDef, brBlock.BlockTransform);
  3.                                 brBlock.AttributeCollection.AppendAttribute(ar);
  4.                                 acTrans.AddNewlyCreatedDBObject(ar, true);
  5.  
Спасибо!! Осталось только еще для разных видимостей динамического блока разобрать как сделать разные атрибуты. Поробую разобраться.

Оффлайн JohnLenninАвтор темы

  • .Net Teapot
  • ADN OPEN
  • Сообщений: 49
  • Карма: 1
Re: Атрибуты у вхождений блока
« Ответ #6 : 25-02-2017, 07:02:28 »
Вроде все работает, только почему-то после того как выполняется команда, редактор блока не открывается, приходится сохранять файл, закрывать его и снова открывать - тогда все открывается. И еще в командной строке AutoCAD постоянно появляется сообщение - "Внимание* Объект с несколькими владельцами, метка "1F"".
Может что-то я делаю не правильно?

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: Атрибуты у вхождений блока
« Ответ #7 : 25-02-2017, 11:03:09 »
Думаешь без полного кода можно догадаться что ты делаешь не так?
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: Атрибуты у вхождений блока
« Ответ #8 : 25-02-2017, 11:12:40 »
http://adn-cis.org/forum/index.php?topic=881
Почитай. Может это твой случай.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн JohnLenninАвтор темы

  • .Net Teapot
  • ADN OPEN
  • Сообщений: 49
  • Карма: 1
Re: Атрибуты у вхождений блока
« Ответ #9 : 25-02-2017, 12:47:03 »
Ой, Сорри! Спасибо за уточнение Александр!
Совсем затупил. Прошу прощения вот код:
Код - C# [Выбрать]
  1.         public static int LetsMadeAnAttributeToSelectedBR(long brHandle, Document doc, string AttrName, string AttrValue)
  2.         {
  3.             int AttrCreatedCount = 0;
  4.             Database acCurDb = doc.Database;
  5.             using (DocumentLock acLckDoc = doc.LockDocument())
  6.             {
  7.                 using (Transaction acTrans = acCurDb.TransactionManager.StartTransaction())
  8.                 {
  9.                     // Open the Block table for write
  10.                     BlockTable acBlkTbl;
  11.                     acBlkTbl = acTrans.GetObject(acCurDb.BlockTableId, OpenMode.ForWrite) as BlockTable;
  12.                     // Open the Block table record Model space for write
  13.                     BlockTableRecord acBlkTblRec;
  14.                     acBlkTblRec = acTrans.GetObject(acBlkTbl[BlockTableRecord.ModelSpace], OpenMode.ForWrite) as BlockTableRecord;
  15.                     //BlockReference nbr = acBlkTblRec .geto
  16.                     Handle hBlock = new Handle(brHandle);
  17.                     ObjectId idBlock;
  18.                     BlockReference brBlock = null;
  19.                     if (acCurDb.TryGetObjectId(hBlock, out idBlock))
  20.                         brBlock = idBlock.GetObject(OpenMode.ForWrite) as BlockReference;
  21.                     // проверяем есть ли блок с таким handle
  22.                     if (brBlock == null)
  23.                         return 0;
  24.                     // получаем атрибуты
  25.                     AttributeCollection attrC = null;
  26.                     attrC = brBlock.AttributeCollection;
  27.                     // проверяем есть ли атрибуты
  28.                     if (attrC.Count == 0)
  29.                     {
  30.                         if (brBlock.IsDynamicBlock)
  31.                         {
  32.                             AttrCreatedCount += CreateNewAttrDynamicBlock(AttrName, AttrValue, acTrans, acBlkTbl, acBlkTblRec, brBlock);
  33.                         }
  34.                         else
  35.                             AttrCreatedCount += CreateNewAttrSimpleBlock(AttrName, AttrValue, acTrans, acBlkTbl, acBlkTblRec, brBlock);
  36.                     }
  37.                     else
  38.                     {
  39.                         // смотрим есть ли такой атрибут
  40.                         foreach (ObjectId idAtrRef in attrC)
  41.                         {
  42.                             // если есть, то меняем значение
  43.                             using (var atrRef = idAtrRef.GetObject(OpenMode.ForWrite) as AttributeReference)
  44.                             {
  45.                                 // если блок динамический то изменяем активные атрибуты
  46.                                 if (brBlock.IsDynamicBlock)
  47.                                 {
  48.                                     if (atrRef != null && atrRef.Visible)
  49.                                         if (ComparePrefixWithNumber(AttrName, atrRef.Tag))
  50.                                         {
  51.                                             atrRef.TextString = AttrValue;
  52.                                             AttrCreatedCount++;
  53.                                         }
  54.                                 }
  55.                                 else
  56.                                 // если обычный, то просто изменяем атрибут
  57.                                 {
  58.                                     if (atrRef != null)
  59.                                         if (ComparePrefixWithNumber(AttrName, atrRef.Tag))
  60.                                         {
  61.                                             atrRef.TextString = AttrValue;
  62.                                             AttrCreatedCount++;
  63.                                         }
  64.                                 }
  65.                             } // using
  66.                         }
  67.                         // если атрибуты есть, но нет атрибута с таким именем то создаем атрибут
  68.                         if (AttrCreatedCount == 0)
  69.                         {
  70.                             if (brBlock.IsDynamicBlock)
  71.                             {
  72.                                 // создаем список атрибутов, которые есть у блока и совпадающие с префиксом
  73.                                 List<string> AttrNames = new List<string>();
  74.                                 foreach (ObjectId idAtrRef in attrC)
  75.                                 {
  76.                                     using (var atrRef = idAtrRef.GetObject(OpenMode.ForWrite) as AttributeReference)
  77.                                     {
  78.                                         if (atrRef != null)
  79.                                             if (ComparePrefixWithNumber(AttrName, atrRef.Tag))
  80.                                                 AttrNames.Add(atrRef.TextString);
  81.                                     }
  82.                                 }
  83.                                 // новое имя атрибута
  84.                                 string NewAttrName = AttrName;
  85.                                 // если атрибуты есть, но не видимые, то добавляем постфикс следующее число
  86.                                 if (AttrNames.Count > 0)
  87.                                     NewAttrName = AttrName + NextAttrName(AttrNames);
  88.                                 // надо создать атрибуты для динамического блока
  89.                                 AttrCreatedCount += CreateNewAttrDynamicBlock(NewAttrName, AttrValue, acTrans, acBlkTbl, acBlkTblRec, brBlock);
  90.                             }
  91.                             else
  92.                                 //если блок обычный
  93.                                 AttrCreatedCount += CreateNewAttrSimpleBlock(AttrName, AttrValue, acTrans, acBlkTbl, acBlkTblRec, brBlock);
  94.                         }
  95.                     }
  96.                     acTrans.Commit();
  97.                     acTrans.Dispose();
  98.                 }
  99.             }
  100.             return AttrCreatedCount;
  101.         }
  102.  
  103.        private static int CreateNewAttrSimpleBlock(string AttrName, string AttrValue, Transaction acTrans, BlockTable acBlkTbl, BlockTableRecord acBlkTblRec, BlockReference brBlock)
  104.         {
  105.             int AttrCreatedCount = 0;
  106.             // создаем атрибут
  107.             using (AttributeDefinition acAttDef = new AttributeDefinition())
  108.             {
  109.                 acAttDef.Position = new Point3d(0, 0, 0);
  110.                 acAttDef.Invisible = false;
  111.                 acAttDef.Visible = true;
  112.                 acAttDef.Verifiable = false;
  113.                 acAttDef.Prompt = AttrValue;
  114.                 acAttDef.Tag = AttrName;
  115.                 acAttDef.TextString = AttrValue;
  116.                 acAttDef.Height = 5;
  117.                 acAttDef.Justify = AttachmentPoint.BottomLeft;
  118.                 acBlkTblRec.AppendEntity(acAttDef);
  119.                 acBlkTbl.UpgradeOpen();
  120.                 acBlkTbl.Add(acBlkTblRec);
  121.                 AttributeReference ar = new AttributeReference();
  122.                 ar.SetAttributeFromBlock(acAttDef, brBlock.BlockTransform);
  123.                 brBlock.AttributeCollection.AppendAttribute(ar);
  124.                 acTrans.AddNewlyCreatedDBObject(ar, true);
  125.                 AttrCreatedCount++;
  126.             }
  127.             return AttrCreatedCount;
  128.         }
  129.  
  130.  

Отмечено как Решение JohnLennin 26-03-2017, 11:39:02

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: Атрибуты у вхождений блока
« Ответ #10 : 25-02-2017, 16:30:45 »
Понять логику работы твоей программы я не смог. Мог лишь понять, что в CreateNewAttrSimpleBlock у тебя полный бред.
1. acBlkTblRec судя по твоему коду - это ModelSpace, а ты его в CreateNewAttrSimpleBlock добавляешь в таблицу блоков acBlkTbl, хотя он и так уже там есть (вот это скорее всего и даёт твою ошибку: "Внимание* Объект с несколькими владельцами, метка "1F"".) - твой чертеж испорчен.
2. Ты создаёшь AttributeDefinition acAttDef и зачем-то добавляешь его не в блок, а в пространство модели. Причем непонятно зачем используешь using при его создании, но не используешь acTrans.AddNewlyCreatedDBObject(acAttDef, true);
3. Ты вызываешь acTrans.Commit(); и  acTrans.Dispose(); хотя у тебя acTrans внутри using и  acTrans.Dispose(); выполнится автоматически, так что считай, что ты дважды вызвал  acTrans.Dispose();
Такое впечатление, что этот код бездумно надерган из совершенно разрозненных кусков.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн JohnLenninАвтор темы

  • .Net Teapot
  • ADN OPEN
  • Сообщений: 49
  • Карма: 1
Re: Атрибуты у вхождений блока
« Ответ #11 : 27-02-2017, 11:28:40 »
Александр, спасибо за ответ.
Действительно код бездумно надерган из разных кусков  :'(
По первому пункту понял
По второму пункту при вызове команды acTrans.AddNewlyCreatedDBObject(acAttDef, true) - была ошибка, что объект не новый. Теперь я понимаю почему она возникала (см. первый пункт в Вашем ответе)
По третьему тоже понял
Спасибо большое, за ваши комментарии и ответы на вопросы, что бы я без вас делал.