Good morning,
I'm writing the following procedure:
1. CREATE TOOLPALETTES
2. CREATE CUSTOMIZED LIST OF BLOCKS
3. CREATE A COMMAND to INSERT THE SELECTED BLOCK AND SET ATTRIBUTES FROM PALETTES
The code behind the INSERT COMMAND in the form:
1. LOCK DOC
AcApDocument *pDoc=acDocManager->curDocument();
acDocManager->lockDocument(pDoc,AcAp::kWrite);
2. ADD BLOCK DEF TO DB
Acad::ErrorStatus es = Acad::eOk;
bool regenInstances = false;
AcDbDatabase *curDwg = acdbHostApplicationServices()->workingDatabase ();
// if we got that ok
if (curDwg != NULL)
{
{
// open up the block table
AcDbBlockTablePointer blockTable (curDwg, AcDb::kForRead);
// if ok
if (blockTable.openStatus () == Acad::eOk)
{
// now see if the block already exists
AcDbBlockTableRecordPointer blockTableRecord (blockName, curDoc()->database(), AcDb::kForWrite);
// if it does exist
if (blockTableRecord.openStatus () == Acad::eOk)
{
return (Acad::eOk);
}
}
}
AcDbObjectId blockId;
// insert the external block
es = curDwg->insert (blockId, blockName, db);
3. INSERT BLOCK
m_block1= new AcDbBlockReference(AcGePoint3d(0,0,0),blockId);
m_block1->setPosition(pIns);
m_block1->setRotation(rotRad);
//my function to add to model space
es=addToModelSpace(idBlockIns1,m_block1);
4. SET ATTRIBUTES
Here the problem because before I need to sync atts but with acedCommand or with pDocManager->sendStringToExecute(pDoc, sCommandLine, true, true, false); there's no way. How can I sync and set the attributes at the same time?
5. DO SOMETHING ELSE IN THE SAME COMMAND. If it's possible I don't want to call command to sync att, command to set atts and command to do something else.
Thank you.
Regards,
Mario
Solved! Go to Solution.
try this.
h
struct NAME_DATA_STRINGS { CString name_; CString value_; }; AcDbObjectId addBlockWithAttributes (AcDbObjectId blockId, AcGePoint3d basePoint, std::vector<NAME_DATA_STRINGS> attributes, double rotation = 0.0);
cpp
AcDbObjectId addBlockWithAttributes (AcDbObjectId blockId, AcGePoint3d basePoint, std::vector<NAME_DATA_STRINGS> attributes, double rotation) { Acad::ErrorStatus es; AcDbObjectId newEntId; newEntId.setNull(); AcDbBlockReference *pBlkRef =new AcDbBlockReference(basePoint,blockId) ; pBlkRef->setRotation(rotation); pBlkRef->setNormal(AcGeVector3d (0.0, 0.0, 1.0)); pBlkRef->setScaleFactors(AcGeScale3d(1.0)); newEntId = postToDb(pBlkRef); AcDbObjectPointer<AcDbBlockReference> pAddedEnt(newEntId,AcDb::kForWrite); if (pAddedEnt.openStatus () != Acad::eOk) return NULL; AcDbBlockTableRecord * pBlockDef; acdbOpenObject(pBlockDef, blockId, AcDb::kForRead); AcDbBlockTableRecordIterator * pIterator; pBlockDef->newIterator(pIterator); AcDbEntity * pEnt; AcDbAttributeDefinition * pAttdef; for ( pIterator->start(); !pIterator->done(); pIterator->step() ) { pIterator->getEntity(pEnt, AcDb::kForRead); pAttdef =AcDbAttributeDefinition::cast(pEnt); if ( pAttdef != NULL && !pAttdef->isConstant () ) { AcDbAttribute * pAtt = new AcDbAttribute; es = pAtt->setAttributeFromBlock(pAttdef,pBlkRef->blockTransform()); TCHAR *pStr = pAttdef->tag(); pAtt->setTag(pStr); pAtt->setFieldLength(pAttdef->fieldLength()); for (int i = 0; i < attributes.size(); i++) { if (attributes.at(i).name_.CompareNoCase(pStr) == 0) { pAtt->setTextString(attributes.at(i).value_.GetString()); } } delete pStr; AcDbObjectId attId; pAddedEnt->appendAttribute(attId, pAtt); pAtt->close(); } pEnt->close(); } delete pIterator; pBlockDef->close(); AcGeMatrix3d matUcs; acedGetCurrentUCS(matUcs); pAddedEnt->transformBy(matUcs); return newEntId; }
AcDbObjectId blockId - get from your code here ( es = curDwg->insert (blockId, blockName, db);)
attributes - struct for attributes, contains fields name (name of an attribute) and value (its value)
for example
NAME_DATA_STRINGS one_attribute; std::vector<NAME_DATA_STRINGS> attr; one_attribute.name_ = _T("NAME"); one_attribute.value_ = _T("Hello"); attr.push_back(one_attribute); one_attribute.name_ = _T("ATTR2"); one_attribute.value_ = _T("23.55"); attr.push_back(one_attribute);
or if you dont know attributes names and values and want user set em during inserting block use this one
AcDbObjectId addBlockToCurDrawing(AcDbObjectId blockId,// ID of blockTableReccord AcGePoint3d basePoint,double scale,double rotation = 0.0); AcDbObjectId addBlockToCurDrawing(AcDbObjectId blockId, AcGePoint3d basePoint, double scale, double rotation) { bool haveToDel = false; Acad::ErrorStatus es; AcDbObjectId newEntId; newEntId.setNull(); AcDbBlockReference *pBlkRef =new AcDbBlockReference(basePoint,blockId) ; pBlkRef->setRotation(rotation); pBlkRef->setNormal(AcGeVector3d (0.0, 0.0, 1.0)); pBlkRef->setScaleFactors(AcGeScale3d(scale)); newEntId = postToDb(pBlkRef); AcDbObjectPointer<AcDbBlockReference> pAddedEnt(newEntId,AcDb::kForWrite); if (pAddedEnt.openStatus () != Acad::eOk) return NULL; AcDbBlockTableRecord * pBlockDef; acdbOpenObject(pBlockDef, blockId, AcDb::kForRead); AcDbBlockTableRecordIterator * pIterator; pBlockDef->newIterator(pIterator); AcDbEntity * pEnt; AcDbAttributeDefinition * pAttdef; for ( pIterator->start(); !pIterator->done(); pIterator->step() ) { pIterator->getEntity(pEnt, AcDb::kForRead); pAttdef =AcDbAttributeDefinition::cast(pEnt); if ( pAttdef != NULL && !pAttdef->isConstant () ) { AcDbAttribute * pAtt = new AcDbAttribute; es = pAtt->setAttributeFromBlock(pAttdef,pBlkRef->blockTransform()); ACHAR *pStr = pAttdef->tag(); pAtt->setTag(pStr); pAtt->setFieldLength(pAttdef->fieldLength()); ACHAR *pPrompt = pAttdef->prompt(); CString pDefValue = pAttdef->textStringConst(); ACHAR promptStr[255]; _tcsncpy(promptStr,_T("\0"),255); _tcscpy(promptStr,_T("\n")); _tcscat(promptStr,pPrompt); if (!pDefValue.IsEmpty()) { _tcscat(promptStr,_T(" <")); _tcscat(promptStr,pDefValue.GetString()); _tcscat(promptStr,_T(">")); } _tcscat(promptStr,_T(": ")); ACHAR txtStr[255]; int ret = acedGetString(TRUE,promptStr, txtStr); if (RTNORM == ret) { if (_tcslen(txtStr) > 0) pAtt->setTextString(txtStr); else pAtt->setTextString(pDefValue.GetString()); } else if (RTNONE == ret) pAtt->setTextString(pDefValue.GetString()); else haveToDel = true; delete pStr; delete pPrompt; AcDbObjectId attId; pAddedEnt->appendAttribute(attId, pAtt); pAtt->close(); } pEnt->close(); } delete pIterator; pBlockDef->close(); AcGeMatrix3d matUcs; acedGetCurrentUCS(matUcs); pAddedEnt->transformBy(matUcs); pAddedEnt->downgradeOpen(); pAddedEnt->close(); if (haveToDel) { deleteEntities(newEntId); // you have to del block if user press ESC newEntId.setNull(); } return newEntId; }
Perfect !!! It works perfectly fine and it is exactly what I need.
Thank you very much. Have a nice day.
Regards,
Mario