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.
Solved by Nick1983. 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