MTextAttributeDefinition

Автор Тема: MTextAttributeDefinition  (Прочитано 11309 раз)

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

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

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

  • ADN Club
  • **
  • Сообщений: 81
  • Карма: 0
MTextAttributeDefinition
« : 20-04-2015, 17:15:58 »
Добрый день.
Изложу суть проблемы:
Мне нужно программно создать определение блока AcDbBlockTableRecord с многострочным атрибутом с маскировкой текста.
Перерыл весь инет, ничего похожего для примера не нашел.
На c# знаю как сделать, но мне нужно именно на c++;
С обычным атрибутом знаю как сделать, все работает, а вот с многострочным не разобрался.
Нашел такие методы как
pAttdef->getMTextAttributeDefinition();
pAttdef->setMTextAttributeDefinition(pText);
pAttdef->convertIntoMTextAttributeDefinition();
но в какой последовательности и как их применить, не понимаю механизма.

На c# можно так pAttdef.IsMTextAttributeDefinition = true;
Но на arx так не сделать!

Может кто сталкивался с подобным, помогите советом или ссылкой.

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

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: MTextAttributeDefinition
« Ответ #1 : 20-04-2015, 17:49:59 »
Ну вообще-то должно быть достаточно:
pAttdef->convertIntoMTextAttributeDefinition();
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • ADN Club
  • **
  • Сообщений: 81
  • Карма: 0
Re: MTextAttributeDefinition
« Ответ #2 : 21-04-2015, 10:41:40 »
Привожу весь код на рассмотрение

1. Описание блока создается без маскировки
2. Вертикальное выравнивание атрибута в описании получается по середине текста, хотя я задаю
    pAttdef->setVerticalMode(AcDb::kTextBottom)
3. Если затем вручную вставить этот блок командой _insert и выбором имени добавленного мной описания, то вылетает ошибка

4. Во вставленном программно блоке маскировка есть.

Что не так в коде?
« Последнее редактирование: 21-04-2015, 16:50:13 от Александр Ривилис »

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

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: MTextAttributeDefinition
« Ответ #3 : 21-04-2015, 11:51:18 »
Для начала прочитай мою подпись и исправь форматирование кода.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • ADN Club
  • **
  • Сообщений: 81
  • Карма: 0
Re: MTextAttributeDefinition
« Ответ #4 : 21-04-2015, 13:02:02 »
Исправил форматирование.

Код - C++ [Выбрать]
  1.         AcDbObjectId idBtr = AcDbObjectId::kNull;
  2.         AcDbBlockTable *pBlockTable = NULL;
  3.         AcDbBlockTableRecord* pBlockRecord = NULL;
  4.         const TCHAR *pName = _T("MyBlock");
  5.  
  6.         acdbHostApplicationServices()->workingDatabase()->getSymbolTable(pBlockTable, AcDb::kForWrite);
  7.         if (!pBlockTable->has(pName)) // для краткости привожу вариант только с созданием нового описания блока
  8.         {
  9.                 pBlockRecord = new AcDbBlockTableRecord;
  10.                 pBlockRecord->setName(pName);
  11.                 pBlockRecord->setOrigin(AcGePoint3d::kOrigin);
  12.                 if (pBlockTable->add(idBtr, pBlockRecord) != Acad::eOk)
  13.                 {
  14.                         delete pBlockRecord;
  15.                         pBlockTable->close();
  16.                         return;
  17.                 }
  18.         }
  19.  
  20.         AcDbPolyline *pLine = new AcDbPolyline();
  21.         AcDbObjectId entId;
  22.         pLine->addVertexAt(0, AcGePoint2d(0, 1));
  23.         pLine->addVertexAt(0, AcGePoint2d(0, -1));
  24.         pLine->setColorIndex(0);
  25.         pLine->setLineWeight(AcDb::LineWeight::kLnWtByBlock);
  26.         pBlockRecord->appendAcDbEntity(entId, pLine);
  27.         pLine->close();
  28.  
  29.         AcDbAttributeDefinition *pAttdef = new AcDbAttributeDefinition;
  30.         pAttdef->setTag(_T("NUM")); // если сразу не установить тэг, то в дальнейшем выскакивает ошибка при работе с pText
  31.         pAttdef->convertIntoMTextAttributeDefinition();
  32.         AcDbMText* pText = pAttdef->getMTextAttributeDefinition();
  33.         pText->setBackgroundFill(true);
  34.         pText->setBackgroundScaleFactor(1.1);
  35.         pText->setUseBackgroundColor(true);
  36.         pAttdef->setMTextAttributeDefinition(pText);
  37.  
  38.         pAttdef->setTextStyle(styleId());
  39.         pAttdef->setHeight(2.0);
  40.         pAttdef->setColorIndex(0);
  41.         pAttdef->setPosition(AcGePoint3d(0, 2, 0));
  42.         pAttdef->setVerticalMode(AcDb::kTextBottom);
  43.         pAttdef->setHorizontalMode(AcDb::kTextMid);
  44.         pAttdef->setAlignmentPoint(AcGePoint3d(0, 2, 0));
  45.  
  46.         pBlockRecord->appendAcDbEntity(entId, pAttdef);
  47.  
  48.         pAttdef->close();
  49.         pBlockRecord->close();
  50.  
  51.  
  52.         // Вставка BlockReference
  53.  
  54.         AcGeVector3d normal(0.0, 0.0, 1.0);
  55.         AcGePlane plane(AcGePoint3d::kOrigin, normal);
  56.         AcDbBlockReference *pBlkRef = new AcDbBlockReference;
  57.         pBlkRef->setBlockTableRecord(idBtr);
  58.         pBlkRef->setPosition(m_Pos);
  59.         pBlkRef->setRotation(m_Ang.angleOnPlane(plane));
  60.         pBlkRef->setNormal(normal);
  61.  
  62.  
  63.         AcGeVector3d normal(0.0, 0.0, 1.0);
  64.         AcGePlane plane(AcGePoint3d::kOrigin, normal);
  65.         AcDbBlockReference *pBlkRef = new AcDbBlockReference;
  66.         pBlkRef->setBlockTableRecord(idBtr);
  67.         pBlkRef->setPosition(m_Pos);
  68.  
  69.         AcDbObjectId newEntId;
  70.         postToDb(pBlkRef, newEntId);
  71.  
  72.         pBlkRef->setNormal(normal);
  73.         pBlkRef->setRotation(m_Ang.angleOnPlane(plane));
  74.  
  75.         AcDbEntity *pEnt = NULL;
  76.         AcDbBlockTableRecord *pBlockDef;
  77.         acdbOpenObject(pBlockDef, idBtr, AcDb::kForRead);
  78.         AcDbBlockTableRecordIterator *pIterator;
  79.         pBlockDef->newIterator(pIterator);
  80.         for (pIterator->start(); !pIterator->done(); pIterator->step())
  81.         {
  82.                 pIterator->getEntity(pEnt, AcDb::kForRead);
  83.                 pAttdef = AcDbAttributeDefinition::cast(pEnt);
  84.                 if (pAttdef != NULL)
  85.                 {
  86.                         AcDbAttribute *pAtt = new AcDbAttribute();
  87.                         pAtt->setPropertiesFrom(pAttdef);
  88.                         pAtt->setInvisible(pAttdef->isInvisible());
  89.                         AcGePoint3d basePoint = pAttdef->position();
  90.                         basePoint += pBlkRef->position().asVector();
  91.                         pAtt->setPosition(basePoint);
  92.                         pAtt->setHeight(pAttdef->height());
  93.                         pAtt->setRotation(pBlkRef->rotation());
  94.                         pAtt->setTag(_T("NUM"));
  95.                         pAtt->setFieldLength(25);
  96.                         const TCHAR *pStr = pAttdef->tagConst();
  97.                         pAtt->setTag(pStr);
  98.                         pAtt->setFieldLength(pAttdef->fieldLength());
  99.                         pAtt->setTextString(m_Name);
  100.                         if (pAttdef->isMTextAttributeDefinition())
  101.                         {
  102.                                 pAtt->convertIntoMTextAttribute();
  103.                                 AcDbMText* pText = pAtt->getMTextAttribute();
  104.                                 pText->setBackgroundFill(pAttdef->getMTextAttributeDefinition()->backgroundFillOn());
  105.                                 double sf;
  106.                                 pAttdef->getMTextAttributeDefinition()->getBackgroundScaleFactor(sf);
  107.                                 pText->setBackgroundScaleFactor(sf);
  108.                                 pText->setUseBackgroundColor(pAttdef->getMTextAttributeDefinition()->useBackgroundColorOn());
  109.                                 pAtt->setMTextAttribute(pText);
  110.                                 pAtt->updateMTextAttribute();
  111.                         }
  112.                         AcDbObjectId attId;
  113.                         pBlkRef->appendAttribute(attId, pAtt);
  114.                         pAtt->close();
  115.                 }
  116.                 pEnt->close();
  117.         }
  118.         delete pIterator;
  119.         pBlockDef->close();
  120.         pBlkRef->close();

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

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: MTextAttributeDefinition
« Ответ #5 : 21-04-2015, 15:50:38 »
Посмотри. Я тут немного переделал твой код и в какой-то момент он заработал. В чем была причина - не выполнялся ли где-то close() или еще что-то - не знаю. Но полученный код у меня работает.
Код - C++ [Выбрать]
  1. static void MAttBlock(void)
  2. {
  3.  
  4.   AcDbDatabase *pDb = acdbCurDwg();
  5.   AcDbObjectId idBtr = AcDbObjectId::kNull;
  6.  
  7.   const TCHAR *pName = _T("MyBlock");
  8.   {
  9.     // Создаём блок
  10.     AcDbBlockTableRecordPointer pBlockRecord;
  11.     AcDbBlockTablePointer pBlockTable(pDb->blockTableId(), AcDb::kForWrite);
  12.     if (!pBlockTable->has(pName)) // для краткости привожу вариант только с созданием нового описания блока
  13.     {
  14.       pBlockRecord.create();
  15.       pBlockRecord->setName(pName);
  16.       pBlockRecord->setOrigin(AcGePoint3d::kOrigin);
  17.       if (pBlockTable->add(idBtr, pBlockRecord) != Acad::eOk)
  18.         return;
  19.     }
  20.  
  21.     AcDbPolyline *pLine = new AcDbPolyline();
  22.     pLine->setDatabaseDefaults();
  23.     AcDbObjectId entId;
  24.     pLine->addVertexAt(0, AcGePoint2d(0, 1));
  25.     pLine->addVertexAt(0, AcGePoint2d(0, -1));
  26.     pLine->setColorIndex(0);
  27.     pLine->setLineWeight(AcDb::kLnWtByBlock);
  28.     pBlockRecord->appendAcDbEntity(entId, pLine);
  29.     pLine->close();
  30.  
  31.     AcDbObjectPointer<AcDbAttributeDefinition> pAttdef; pAttdef.create();
  32.     pAttdef->setDatabaseDefaults();
  33.     pBlockRecord->appendAcDbEntity(entId, pAttdef);
  34.     pAttdef->setTag(_T("NUM"));
  35.     pAttdef->setTextString(_T("NUM"));
  36.     pAttdef->setPrompt(_T("NUM"));
  37.     pAttdef->setTextStyle(pDb->textstyle());
  38.     pAttdef->setHeight(2.0);
  39.     pAttdef->setColorIndex(0);
  40.     pAttdef->setPosition(AcGePoint3d(0, 2, 0));
  41.     pAttdef->setVerticalMode(AcDb::kTextBottom);
  42.     pAttdef->setHorizontalMode(AcDb::kTextMid);
  43.     pAttdef->setAlignmentPoint(AcGePoint3d(0, 2, 0));
  44.     pAttdef->convertIntoMTextAttributeDefinition();
  45.     AcDbMText* pText = new AcDbMText();
  46.     pText->setBackgroundFill(true);
  47.     pText->setBackgroundScaleFactor(1.1);
  48.     pText->setUseBackgroundColor(true);
  49.     pText->setContents(_T("NUM"));
  50.     pAttdef->setMTextAttributeDefinition(pText);
  51.  
  52.   }
  53.  
  54.   {
  55.     // Вставка BlockReference
  56.  
  57.     AcGeVector3d normal(0.0, 0.0, 1.0);
  58.     AcGePlane plane(AcGePoint3d::kOrigin, normal);
  59.     AcDbObjectPointer<AcDbBlockReference> pBlkRef; pBlkRef.create();
  60.     pBlkRef->setBlockTableRecord(idBtr);
  61.     pBlkRef->setPosition(AcGePoint3d(0,0,0));
  62.     pBlkRef->setRotation(0.0);
  63.     pBlkRef->setNormal(AcGeVector3d(0,0,1));
  64.  
  65.     AcDbObjectId newEntId;
  66.     postToDb(pBlkRef, newEntId);
  67.  
  68.     AcDbBlockTableRecordPointer pBlockDef(idBtr, AcDb::kForRead);
  69.     Acad::ErrorStatus es = pBlockDef.openStatus();
  70.     AcDbBlockTableRecordIterator *pIterator = NULL;
  71.     pBlockDef->newIterator(pIterator);
  72.     for (pIterator->start(); !pIterator->done(); pIterator->step())
  73.     {
  74.       AcDbObjectId idAttDef;
  75.       pIterator->getEntityId(idAttDef);
  76.       AcDbObjectPointer<AcDbAttributeDefinition> pAttdef(idAttDef, AcDb::kForRead);
  77.       if (pAttdef.openStatus() == Acad::eOk && !pAttdef->isConstant())
  78.       {
  79.         AcDbObjectPointer<AcDbAttribute> pAtt; pAtt.create();
  80.         pAtt->setAttributeFromBlock(pAttdef,AcGeMatrix3d::kIdentity);
  81.         AcDbObjectId attId;
  82.         pBlkRef->appendAttribute(attId, pAtt);
  83.       }
  84.     }
  85.     delete pIterator;
  86.   }
  87. }
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • ADN Club
  • **
  • Сообщений: 81
  • Карма: 0
Re: MTextAttributeDefinition
« Ответ #6 : 21-04-2015, 16:56:04 »
Так у меня тоже работает.
Дополнил код чтобы учитывать точку вставки блока и угол поворота.

Код - C++ [Выбрать]
  1.     for (pIterator->start(); !pIterator->done(); pIterator->step())
  2.     {
  3.       AcDbObjectId idAttDef;
  4.       pIterator->getEntityId(idAttDef);
  5.       AcDbObjectPointer<AcDbAttributeDefinition> pAttdef(idAttDef, AcDb::kForRead);
  6.       if (pAttdef.openStatus() == Acad::eOk && !pAttdef->isConstant())
  7.       {
  8.         AcDbObjectPointer<AcDbAttribute> pAtt; pAtt.create();
  9.         pAtt->setAttributeFromBlock(pAttdef,AcGeMatrix3d::kIdentity);
  10.  
  11.         AcGePoint3d basePoint = pAttdef->position();
  12.         basePoint += pBlkRef->position().asVector();
  13.         pAtt->setTextString(m_Name);
  14.         pAtt->setPosition(basePoint);
  15.         pAtt->setAlignmentPoint(basePoint);
  16.  
  17.         pAtt->setRotation(pBlkRef->rotation());
  18.         AcDbObjectId attId;
  19.         pBlkRef->appendAttribute(attId, pAtt);
  20.       }
  21.     }
  22.     delete pIterator;
  23.     pBlockDef->close();
  24.     pBlkRef->close();

Все работает, но почему выравнивание атрибута получается не по центру над точкой вставки, а со смещением вправо?
Причем у описания блока это смещение одно, а во вставке блока атрибут смещается в зависимости от угла поворота блока?


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

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: MTextAttributeDefinition
« Ответ #7 : 21-04-2015, 17:07:40 »
Попробуй трансформировать pAtt через pBlkRef->blockTransform(). Думаю что никакие другие операции над pAtt не нужны:
Код - C++ [Выбрать]
  1. if (pAttdef.openStatus() == Acad::eOk && !pAttdef->isConstant())
  2. {
  3.   AcDbObjectPointer<AcDbAttribute> pAtt; pAtt.create();
  4.   pAtt->setAttributeFromBlock(pAttdef,AcGeMatrix3d::kIdentity);
  5.   pAtt->transformBy(pBlkRef->blockTransform());
  6.   AcDbObjectId attId;
  7.   pBlkRef->appendAttribute(attId, pAtt);
  8. }
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Отмечено как Решение Gennadiy 21-04-2015, 17:29:40

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

  • ADN Club
  • **
  • Сообщений: 81
  • Карма: 0
Re: MTextAttributeDefinition
« Ответ #8 : 21-04-2015, 17:29:08 »
Отлично, получилось.
Чтобы не смещался атрибут в описании блока, строчку кода

Код - C++ [Выбрать]
  1. pAttdef->setAlignmentPoint(AcGePoint3d(0, 2, 0));

я поставил в конце определения, после строки
Код - C++ [Выбрать]
  1. pAttdef->setMTextAttributeDefinition(pText);

А во вставке блока

Цитировать
Попробуй трансформировать pAtt через pBlkRef->blockTransform(). Думаю что никакие другие операции над pAtt не нужны.

Код - C++ [Выбрать]
  1. pAtt->transformBy(pBlkRef->blockTransform());

Теперь все работает как надо. Спасибо Александр!