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

ADN Club => AutoCAD .NET API => Тема начата: Константин Соков от 02-12-2014, 23:58:14

Название: Удалить определение атрибута
Отправлено: Константин Соков от 02-12-2014, 23:58:14
Здравствуйте.
Пытаюсь удалить все определения атрибута из определения блока
Код - C# [Выбрать]
  1. BlockTableRecord blockFind = (BlockTableRecord)bt[name].GetObject(OpenMode.ForWrite);
  2. foreach (ObjectId ent in blockFind)
  3. {
  4.    if (ent.ObjectClass.Name == "AcDbAttributeDefinition")
  5.    {
  6.        AttributeDefinition attr = (AttributeDefinition)trans.GetObject(ent, OpenMode.ForWrite);
  7.        attr.Erase(true);
  8.     }
  9. }
После выполнения на чертеже атрибуты исчезают, но при выборе блока все равно вызывается _eattedit вместо _bedit. Один атрибут все же остается. Как удалить все атрибуты из блока?
Название: Re: Удалить определение атрибута
Отправлено: Александр Ривилис от 03-12-2014, 00:05:21
После выполнения на чертеже атрибуты исчезают, но при выборе блока все равно вызывается _eattedit вместо _bedit. Один атрибут все же остается. Как удалить все атрибуты из блока?
Нужно удалить атрибуты у конкретной вставки блока.
Название: Re: Удалить определение атрибута
Отправлено: Константин Соков от 03-12-2014, 00:35:04
Нет, вообще из определения блока
Название: Re: Удалить определение атрибута
Отправлено: trir от 03-12-2014, 07:10:51
АТРОБНОВИТЬ
Название: Re: Удалить определение атрибута
Отправлено: Константин Соков от 03-12-2014, 08:11:30
АТРОБНОВИТЬ
Не помогает. Не тот ли это баг (http://adn-cis.org/forum/index.php?topic=625.msg2168#msg2168)
Название: Re: Удалить определение атрибута
Отправлено: Александр Ривилис от 03-12-2014, 11:17:30
Нет, вообще из определения блока
С моей стороны был не вопрос, а утверждение. В своём коде ты показываешь, что удаляешь определения атрибутов из описания блока. Потом показываешь картинку, на которой вставка с одним атрибутом. Кстати у атрибута флажок удаленности (This entity is currently erased).
Возможно это и указанный тобой баг. Но это можно будет понять только после того как ты опишешь всю цепочку действий. Я увидел только то, что ты удаляешь у определения блока определения атрибутов. Откуда появилась вставка блока с удаленным атрибутом - загадка.
Название: Re: Удалить определение атрибута
Отправлено: Константин Соков от 03-12-2014, 11:49:42
Нахожу блок (по имени или выбираю вставку нужного блока в чертеже), перехожу в определение этого блока и удаляю все определения атрибутов. Картинка чтобы показать что после всех манипуляций в блоке все равно остается атрибут.
Название: Re: Удалить определение атрибута
Отправлено: Александр Ривилис от 03-12-2014, 12:30:11
Нахожу блок (по имени или выбираю вставку нужного блока в чертеже), перехожу в определение этого блока и удаляю все определения атрибутов. Картинка чтобы показать что после всех манипуляций в блоке все равно остается атрибут.
После этого ты делал вставку этого блока? И на картинке результат вставки?
Название: Re: Удалить определение атрибута
Отправлено: Константин Соков от 03-12-2014, 12:33:36
Нет, все вставки остаются без изменений.
Название: Re: Удалить определение атрибута
Отправлено: Александр Ривилис от 03-12-2014, 12:58:45
Нет, все вставки остаются без изменений.
Ты меня запутал окончательно.
Название: Re: Удалить определение атрибута
Отправлено: Константин Соков от 03-12-2014, 13:03:58
На картинке, результат вставки блока после выполнения команды, но она (вставка блока) была создана до выполнения команды (удаление определения атрибутов)  ???
Название: Re: Удалить определение атрибута
Отправлено: Александр Ривилис от 03-12-2014, 13:21:32
А теперь всё по порядку.
1) В чертеже было определение блока с атрибутами и одна (или несколько) вставок этого блока.
2) Ты запустил свой код, который удаляет из этого определения блока определения атрибутов. Где код? Я вижу только его обрывок.
3) В результате ты во вставке блока видишь атрибут, причем помеченный как удаленный?
Но ведь удаление определений атрибутов в определении блока не влияет на атрибуты во вставке блока! Точнее влияет только на постоянные (константные) атрибуты, которые одинаковы во всех вставках блока. 
Название: Re: Удалить определение атрибута
Отправлено: Константин Соков от 03-12-2014, 17:00:07
да вот собственно код, ничего особенного:
Код - C# [Выбрать]
  1. public static void DeleteAttribute(string nameBtr)
  2. {
  3.     Document doc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument;
  4.     Database db = doc.Database;
  5.     Editor ed = doc.Editor;
  6.  
  7.     using (Transaction trans = db.TransactionManager.StartTransaction())
  8.     {
  9.         try
  10.         {
  11.             BlockTable bt = (BlockTable)db.BlockTableId.GetObject(OpenMode.ForWrite);
  12.             if (bt.Has(nameBtr))
  13.             {
  14.                 BlockTableRecord blockFind = (BlockTableRecord)bt[nameBtr].GetObject(OpenMode.ForWrite);
  15.                 foreach (ObjectId ent in blockFind)
  16.                 {
  17.                     if (ent.ObjectClass.Name == "AcDbAttributeDefinition")
  18.                     {
  19.                         AttributeDefinition attr = (AttributeDefinition)trans.GetObject(ent, OpenMode.ForWrite);
  20.                         attr.Erase(true);
  21.                     }
  22.                 }
  23.                 BlockTableRecordExtensionMethods.AttSync(blockFind, true, true, true);
  24.             }
  25.             else
  26.                 ed.WriteMessage("\nНе найдено опеределение блока \"{0}\"", nameBtr);
  27.  
  28.             trans.Commit();
  29.         }
  30.         catch (Autodesk.AutoCAD.Runtime.Exception ex)
  31.         {
  32.             ed.WriteMessage("\n{0}", ex.Message);
  33.         }
  34.     }                          
  35. }

Где BlockTableRecordExtensionMethods.AttSync(blockFind, true, true, true) (https://sites.google.com/site/bushmansnetlaboratory/moi-zametki/attsynch) _attsync на .Net
Название: Re: Удалить определение атрибута
Отправлено: Александр Ривилис от 03-12-2014, 17:08:52
да вот собственно код, ничего особенного:
Особенное как раз есть. Это:
BlockTableRecordExtensionMethods.AttSync(blockFind, true, true, true);
Как я понимаю, это код Андрея Бушмана: https://sites.google.com/site/bushmansnetlaboratory/moi-zametki/attsynch , который как раз и модифицирует атрибуты вставки блоков. Вот тут то и нужно разбираться в чем дело.
Название: Re: Удалить определение атрибута
Отправлено: Александр Ривилис от 03-12-2014, 17:22:15
И если это действительно тот, указанный выше, баг, то его обойти можно только одним способом - заменой значения группы DXF 66 на 0.
Название: Re: Удалить определение атрибута
Отправлено: Константин Соков от 03-12-2014, 17:23:32
Но, кстати, без кода Андрея Бушмана, та же ситуация. Я просто думал что этот атрибут сидит потому что нужно запустить атробновить, но как оказалость дело не в этом
Название: Re: Удалить определение атрибута
Отправлено: Александр Ривилис от 03-12-2014, 17:25:41
Но, кстати, без кода Андрея Бушмана, та же ситуация.
Так она и с твоим кодом не связана. Атрибутов у вставки блока нет, а значение группы DXF 66 равно 1, чего быть не должно.
Название: Re: Удалить определение атрибута
Отправлено: Константин Соков от 03-12-2014, 18:18:24
заменой значения группы DXF 66 на 0
Это только на LISP или С++?
Название: Re: Удалить определение атрибута
Отправлено: Александр Ривилис от 04-12-2014, 03:20:11
Это только на LISP или С++?
Нет. Это еще и P/Invoke в .NET
Название: Re: Удалить определение атрибута
Отправлено: Константин Соков от 04-12-2014, 11:50:30
Это только на LISP или С++?
Нет. Это еще и P/Invoke в .NET

Может небольшой примерчик завалялся, или ссылка?
Название: Re: Удалить определение атрибута
Отправлено: Александр Ривилис от 04-12-2014, 14:47:01
Может небольшой примерчик завалялся, или ссылка?
Примерчик не завалялся - нужно сделать. Можешь сам попробовать из этого скомбинировать: http://habrahabr.ru/post/154591/
Но там многое менять придется. К сожалению P/Invoke существенно зависит от версии и разрядности AutoCAD.
Название: Re: Удалить определение атрибута
Отправлено: Константин Соков от 04-12-2014, 20:14:32
Заметил одну особенность - если выполнять код, без выполнения кода Андрея Бушмана, т. е. только удалять определения атрибутов из определения блока, а потом запускать АТРОБНОВИТЬ и при запросе выбирать блок (именно выбирать, а не вводить имя блока в командную строку, иначе не получается) то все атрибуты удаляются, и флага удаления не появляется. Получается дело за тем чтобы корректно обновить атрибуты после удаления определения атрибутов из определения блока.
Название: Re: Удалить определение атрибута
Отправлено: Константин Соков от 06-12-2014, 00:57:43
Пробую изменить (или вообще удалить) DXF группу 66, таким вот образом:
Код - C# [Выбрать]
  1. [System.Security.SuppressUnmanagedCodeSecurity]
  2. [DllImport("acdb19.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "?acdbGetAdsName@@YA?AW4ErrorStatus@Acad@@AAY01JVAcDbObjectId@@@Z")]
  3. private static extern int acdbGetAdsName(long[] name, ObjectId objId);
  4.  
  5. [DllImport("accore.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "acdbEntGet")]
  6. private static extern System.IntPtr acdbEntGet(long[] name);
  7.  
  8. [DllImport("accore.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "acdbEntMod")]
  9. private static extern System.Int32 acdbEntMod(System.IntPtr resbuf);
  10.  
  11. [DllImport("accore.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "acdbEntMake")]
  12. private static extern System.Int32 acdbEntMake(System.IntPtr resbuf);
  13.  
  14. [CommandMethod("DXFMod")]
  15. static public void DXFMod()
  16. {
  17.     Document acDoc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument;
  18.     Database acDb = acDoc.Database;
  19.     Editor ed = acDoc.Editor;
  20.  
  21.     PromptEntityOptions entityOpt = new PromptEntityOptions("\nSelect entity: ");
  22.     PromptEntityResult entityRes = ed.GetEntity(entityOpt);
  23.     if (entityRes.Status == PromptStatus.OK)
  24.     {
  25.         Transaction tr = acDb.TransactionManager.StartTransaction();
  26.         using (tr)
  27.         {
  28.             DBObject obj = tr.GetObject(entityRes.ObjectId, OpenMode.ForWrite);
  29.             long[] ent = new long[] { 0, 0 };
  30.             acdbGetAdsName(ent, entityRes.ObjectId);
  31.             System.IntPtr rb = acdbEntGet(ent);
  32.  
  33.             ResultBuffer dxflist = DisposableWrapper.Create(typeof(ResultBuffer), rb, true) as ResultBuffer;
  34.             ResultBuffer dxflistNew = new ResultBuffer();
  35.             if (dxflist != null)
  36.             {
  37.                 foreach (TypedValue val in dxflist)
  38.                 {
  39.                     if (val.TypeCode != 66)
  40.                     {
  41.                         dxflistNew.Add(val);
  42.                     }
  43.                     //Попытка изменить значение DXF группы
  44.                     //else
  45.                     //{
  46.                     //    TypedValue tp = new TypedValue(66, 0);
  47.                     //    dxflistNew.Add(tp);
  48.                     //}
  49.                 }
  50.                 acdbEntMod(dxflistNew.UnmanagedObject);
  51.             }
  52.             tr.Commit();
  53.         }
  54.     }
  55. }
но что-то результата никакого  :( . Этот атрибут с флагом "This entity is currently erased" все равно остается
Название: Re: Удалить определение атрибута
Отправлено: Александр Ривилис от 06-12-2014, 02:29:13
Значит и этот вариант не поможет. Увы.
Название: Re: Удалить определение атрибута
Отправлено: Константин Соков от 06-12-2014, 10:16:55
Может что-то с приведенным выше кодом? :o
Название: Re: Удалить определение атрибута
Отправлено: Александр Ривилис от 06-12-2014, 11:09:51
Может что-то с приведенным выше кодом?
С кодом всё нормально. Я проверил в AutoCAD 2014 - группу 66 таким образом установить не удается (в ObjectARX/Lisp аналогично).
Название: Re: Удалить определение атрибута
Отправлено: Константин Соков от 07-12-2014, 21:15:03
даже если штатными средствами AutoCAD удалить определение атрибута, который стоит первым в списке атрибутов, и при этом если в блоке останется хотя бы одно определение атрибута, то у всех вставок этого блока атрибут, который был первым в списке будет помечен как "This entity is currently erased", а при удалении вообще всех определений атрибутов из блока атрибуты удаляются полностью, никаких флагов не остается. Неужели никак нельзя программно удалить все атрибуты?
Название: Re: Удалить определение атрибута
Отправлено: Александр Ривилис от 07-12-2014, 21:17:59
Получается дело за тем чтобы корректно обновить атрибуты после удаления определения атрибутов из определения блока.
Очень может быть. И мне кажется что проблема в том, что BlockReference br в момент когда мы удаляем атрибуты открыт на запись. Возможно нужно предварительно закрыть BlockReference, а возможно нужно поиграться и заменить транзакцию на эмуляцию транзакции.
Название: Re: Удалить определение атрибута
Отправлено: Александр Ривилис от 07-12-2014, 21:21:32
даже если штатными средствами AutoCAD удалить определение атрибута, который стоит первым в списке атрибутов, и при этом если в блоке останется хотя бы одно определение атрибута, то у всех вставок этого блока атрибут, который был первым в списке будет помечен как "This entity is currently erased
Если это так, то это просто баг.

а при удалении вообще всех определений атрибутов из блока атрибуты удаляются полностью, никаких флагов не остается. Неужели никак нельзя программно удалить все атрибуты?
А вот тут я уже не понял. Если есть баг, то его врядли можно так просто обойти.
Название: Re: Удалить определение атрибута
Отправлено: Александр Ривилис от 07-12-2014, 21:41:24
даже если штатными средствами AutoCAD удалить определение атрибута, который стоит первым в списке атрибутов, и при этом если в блоке останется хотя бы одно определение атрибута, то у всех вставок этого блока атрибут, который был первым в списке будет помечен как "This entity is currently erased"
Что-то ты меня снова запутал. Я проверил гипотезу с багом в "штатных средствах" и она у меня не подтвердилась:
https://screencast.autodesk.com/main/details/b822b3e6-dca5-4e03-86ad-1b4a39d5fdbb

P.S.: Ага. Кажется до меня стало доходить о чем ты - ты забыл сообщить, что после удаления определения атрибута запустил команду _ATTSYNC. Да действительно у первого атрибута в блоке установлен признак IsErased:
https://screencast.autodesk.com/main/details/78ed5795-41ad-41a4-bb1f-aced403e4e3d
Я пометил что это баг, но потом сообразил, что в принципе это нормально. Если сохранить чертеж, закрыть и открыть его, то этого атрибута не будет видно и в ARXDBG. Можешь это проверить сам.
 
Название: Re: Удалить определение атрибута
Отправлено: Константин Соков от 07-12-2014, 21:55:05
Я делал так: есть блок с несколькими атрибутами, захожу в определение, удаляю первый атрибут, выхожу из определения, дальше АТРОБНОВИТЬ
Название: Re: Удалить определение атрибута
Отправлено: Константин Соков от 07-12-2014, 21:57:57
Если захожу в определение блока, удаляю все атрибуты потом АТРОБНОВИТЬ получается вот так (блок один и тот же)
Название: Re: Удалить определение атрибута
Отправлено: Александр Ривилис от 07-12-2014, 22:11:23
Это нормально. Фактически если не осталось ни одного атрибута в блоке, то DXF группа 66 устанавливается AutoCAD'ом в 0 и ARXDBG вообще не пытается искать и показывать атрибуты блока. Если же есть хоть один атрибут, то ARXDBG выводит все атрибуты, в том числе и удаленные. Никакого противоречия не вижу. При желании можно "пошаманить" с исходниками ARXDBG и сделать так, чтобы этот атрибут в список не попадал (файл из ObjectARX SDK \samples\database\ARXDBG\Snoop\ArxDbgUiTdcEntities.cpp):
Код - C++ [Выбрать]
  1. void
  2. ArxDbgUiTdcEntities::addSubentitiesToTree(const AcDbEntity* mainEnt, HTREEITEM parent)
  3. {
  4.         AcDbObjectIdArray subEnts;
  5.  
  6.     AcDbBlockReference* blkRef;
  7.        
  8.         if ((blkRef = AcDbBlockReference::cast(mainEnt)) != NULL) {
  9.                 collectAttributes(blkRef, subEnts);
  10.         }
  11.         else if ((mainEnt->isKindOf(AcDbPolyFaceMesh::desc())) ||
  12.                          (mainEnt->isKindOf(AcDbPolygonMesh::desc())) ||
  13.                          (mainEnt->isKindOf(AcDb2dPolyline::desc())) ||
  14.                          (mainEnt->isKindOf(AcDb3dPolyline::desc()))) {
  15.                 collectVertices(mainEnt, subEnts);
  16.         }
  17.  
  18.         AcDbObject* tmpObj;
  19.         HTREEITEM treeItem;
  20.         Acad::ErrorStatus es;
  21.         CString str;
  22.  
  23.         int len = subEnts.length();
  24.         for (int i=0; i<len; i++) {
  25.                // Если в следующей строке заменить true на false, то атрибут в ARXDBG виден не будет
  26.                 es = acdbOpenAcDbObject(tmpObj, subEnts[i], AcDb::kForRead, true);              // might have passed in erased ones
  27.                 if (es == Acad::eOk) {
  28.                         treeItem = addOneTreeItem(ArxDbgUtils::objToClassAndHandleStr(tmpObj, str), tmpObj, parent);
  29.                         tmpObj->close();
  30.                 }
  31.                 else
  32.                         ArxDbgUtils::rxErrorMsg(es);
  33.         }
  34. }
  35.  
Название: Re: Удалить определение атрибута
Отправлено: Константин Соков от 07-12-2014, 22:40:57
Да меня больше беспокоило в этой ситуации то что после удаления всех атрибутов (и определений и атрибутов у вставок блока), его не получилось открыть на редактирование двойным щелчком. При двойном щелчке на вставке, вызывалась команда _.eattedit, как будто в нем есть атрибуты, хотя в палитре свойств при этом никаких атрибутов нет. Теперь думаю можно поступить так: зайти в определение блока, удалить все определения атрибутов, потом старые вставки блока удалить, а на их места добавить уже новые (без определений атрибутов). Только  вот не слишком ли долго все это будет выполняться, если в чертеже будет много блоков?
Название: Re: Удалить определение атрибута
Отправлено: Александр Ривилис от 07-12-2014, 23:52:13
Только  вот не слишком ли долго все это будет выполняться, если в чертеже будет много блоков?
Думаю что это не принципиальное увеличение времени, т.к. это не то, что должно выполнятся в реальном времени. Если вместо 10 секунд этот код будет работать 20 секунд, то ничего страшного в этом не вижу.
Нашел еще один интересный баг. Если есть определение блока с определениями атрибутов и его вставка, а затем из определения блока определения атрибутов удалили (и это единственное определение блока в чертеже), то команда _ATTSYNC отказывается работать - говорит что нет блоков с атрибутами:
https://screencast.autodesk.com/main/details/023e40b3-9491-4345-b56a-1fa418cdfa63
Если же есть еще хотябы одно определение блока с определениями атрибута, то всё нормально:
https://screencast.autodesk.com/main/details/7b6f7c0e-8ab7-43c5-bc6a-5844abe31153
Так что займись исследованием кода Андрея. Где-то или у него неточность или в баг в .NET API, которым команда _ATTSYNC не пользуется.
Если же это блок не единственный
Название: Re: Удалить определение атрибута
Отправлено: Константин Соков от 08-12-2014, 00:04:27
(и это единственное определение блока в чертеже)
Точно, тоже наблюдал эту ситуацию!
Название: Re: Удалить определение атрибута
Отправлено: Александр Ривилис от 08-12-2014, 00:07:46
Но, кстати, без кода Андрея Бушмана, та же ситуация. Я просто думал что этот атрибут сидит потому что нужно запустить атробновить, но как оказалость дело не в этом
Так. А теперь начнем с начала. Без кода Андрея получить такой результат (как видишь из роликов) не получается.
Название: Re: Удалить определение атрибута
Отправлено: Константин Соков от 08-12-2014, 00:26:45
еще один момент: удаляю определения атрибутов из определения блока программно, вставки блока вообще не трогаю. потом запускаю _attsync и при запросе выбираю опцию "Имя",  а не опцию "Выбрать" - тогда сообщение о том что не найден блок с атрибутами. если выбрать опцию "Выбрать" то блок успешно обновляется.
Название: Re: Удалить определение атрибута
Отправлено: Александр Ривилис от 08-12-2014, 00:30:51
еще один момент: удаляю определения атрибутов из определения блока, вставки блока вообще не трогаю. потом запускаю _attsync и при запросе выбираю опцию "Имя",  а не выбрать - тогда сообщение о том что не найден блок с атрибутами. если выбрать опцию "Выбрать" то блок успешно обновляется.
Ну это тоже всё растёт из того что в случае "Имя" проверяется определение блока по имени, а в нём определения атрибутов нет. А в случае указания сначала проверяется вставка блока и, при наличии в ней атрибутов, наличие определения атрибутов в определении блока не учитывается. Как-то так.