ObjectARX
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Syncronize attributes

3 REPLIES 3
SOLVED
Reply
Message 1 of 4
marioriva
756 Views, 3 Replies

Syncronize attributes

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

3 REPLIES 3
Message 2 of 4
Nick1983
in reply to: marioriva

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);

 

---
#define QUESTION(b) (2*b)||(!(2*b)) © William Shakespeare
Message 3 of 4
Nick1983
in reply to: Nick1983

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;
}

 

 

---
#define QUESTION(b) (2*b)||(!(2*b)) © William Shakespeare
Message 4 of 4
marioriva
in reply to: Nick1983

Perfect !!! It works perfectly fine and it is exactly what I need.

 

Thank you very much. Have a nice day.

 

Regards,

 

Mario

 

 

Can't find what you're looking for? Ask the community or share your knowledge.

Post to forums  

Autodesk Design & Make Report

”Boost