Hi,
I need to change some attribute definitions in the existing block reference, but unable to do so.
I am trying to change the attribute definition for the "Tab","Prompt" and "Value", but can change only "Tab" and "Value".
Is there any way to change the prompt?
Any help/guidance with the same will be highly appreciated.
The approach am taking is as follows;
AcDbDatabase *dwgDb;
AcDbBlockTable *pBlockTbl;
AcDbBlockTableRecord *pModelSpaceTblRcd;
AcDbBlockTableRecordIterator *pModelSpaceItr;
AcDbEntity *pEntity;
AcDbBlockReference *pBlockRef;
AcDbAttribute *pAttribute;
AcDbObjectIterator *pAttrItr;
AcDbObject *pObject;
TCHAR tagBuffer[SINGLE_LINE_INPUT_LENGTH_SHORT];
// Prepare attribute location measurements
AcDbObjectId idOfEntity;
dwgDb = NULL;
dwgDb = acdbHostApplicationServices()->workingDatabase();
if (dwgDb == NULL)
{ AfxMessageBox(_T("Internal Error !"));
return false; }
dwgDb->getSymbolTable(pBlockTbl, AcDb::kForWrite);
pBlockTbl->getAt(ACDB_MODEL_SPACE, pModelSpaceTblRcd, AcDb::kForWrite);
pBlockTbl->close();
// Get an iterator to that we can iterate / pinpoint
// the desired entity via the objectID
pModelSpaceTblRcd->newIterator(pModelSpaceItr);
// Go to the block reference / objectID
if(pModelSpaceItr->seek(thePANBLKBlockId) != Acad::eOk)
{ AfxMessageBox(_T("Internal Error !"));
delete pModelSpaceItr; pModelSpaceTblRcd->close(); return false; }
// Access the block reference
pModelSpaceItr->getEntity(pEntity, AcDb::kForWrite);
pBlockRef = AcDbBlockReference::cast(pEntity);
// Prepare iterator to move through block's attributes
pAttrItr = pBlockRef->attributeIterator();
for(pAttrItr->start();
!pAttrItr->done();
pAttrItr->step())
{
acdbOpenAcDbObject(pObject, pAttrItr->objectId(), AcDb::kForWrite);
pAttribute = AcDbAttribute::cast(pObject);
_tcscpy_s(tagBuffer, SINGLE_LINE_INPUT_LENGTH_SHORT, pAttribute->tag());
pAttribute->upgradeOpen();
// LEFTBFHGT
if(_tcscmp(tagBuffer, _T("LEFTBFHGT")) == 0 ||
_tcscmp(tagBuffer, _T("LEFTHEIGHT")) == 0 )
{ pAttribute->setTag(_T("LEFTFFHGHT")); pAttribute->setTextString(attrText); }
pAttribute->close();
}
// Free the attribute iterator
delete pAttrItr;
pBlockRef->close();
delete pModelSpaceItr;
pModelSpaceTblRcd->close();
To clear up some terminology: the term "attribute definitions" refers to AcDbAttributeDefinition objects, which are owned by AcDbBlockTableRecord objects. According to your code, you are trying to modify attributes, or AcDbAttribute objects, which are owned by AcDbBlockReference objects.
You haven't described what the error is. Does AutoCAD crash when you execute the code? If so, what is the exception, and in which line does it occur? Does a function call return an error status? if so, what is the function and what is the returned error status?
Hi Owen,
Thanks for your reply.
There is no error, It changes the "TAG" and the "VALUE" tab of the attribute.
I also need to change the "PROMPT" but cannot do it for now. Need some help/guidance on the approach on how to do it.
I have also tried some code with the AcDbAttributeDefinition as follows,
for(pAttrItr->start();
!pAttrItr->done();
pAttrItr->step())
{
acdbOpenAcDbObject(pObject, pAttrItr->objectId(), AcDb::kForWrite);
pAttribute = AcDbAttribute::cast(pObject);
_tcscpy_s(tagBuffer, SINGLE_LINE_INPUT_LENGTH_SHORT, pAttribute->tag());
pAttribute->upgradeOpen();
// LEFTBFHGT
if(_tcscmp(tagBuffer, _T("LEFTBFHGT")) == 0 ||
_tcscmp(tagBuffer, _T("LEFTHEIGHT")) == 0 )
{
TCHAR attrText[COMMENT_LENGTH_SHORT];
_tcscpy_s(attrText, COMMENT_LENGTH_SHORT, pAttribute->textString() );
AcDbAttributeDefinition *tempAttrDefinition = new AcDbAttributeDefinition();
tempAttrDefinition->setPosition(pAttribute->position() );
tempAttrDefinition->setTextString(attrText);
tempAttrDefinition->setTag(_T("LEFTFFHGHT"));
tempAttrDefinition->setPrompt(_T("Left Front Face Height."));
tempAttrDefinition->setTextStyle(idTextStyleLeroy);
tempAttrDefinition->setHeight(.32); // for English
tempAttrDefinition->setFieldLength(FLOAT_ARRAY_LENGTH);
tempAttrDefinition->setInvisible(Adesk::kFalse);
tempAttrDefinition->setConstant(Adesk::kFalse);
tempAttrDefinition->setLockPositionInBlock(Adesk::kTrue);
tempAttrDefinition->setRotation(0);
pAttribute->setAttributeFromBlock(tempAttrDefinition, pBlockRef->blockTransform() );
pAttribute->transformBy(pBlockRef->blockTransform() );
pAttribute->downgradeOpen();
pModelSpaceTblRcd->appendAcDbEntity(pEntity);
pBlockTbl->upgradeOpen();
pModelSpaceTblRcd->upgradeOpen();
tempAttrDefinition->close();
}
You still have not described how it fails. What are the steps you take, what do you expect to happen, and what actually happens?
I have a block defined with "N" fields, Now what I need to do is "rename" one of the fields in the AcDbBlockRecord.
Is there any way to do that, or am I missing something here?
Example:
I have a PanelBlock with Fields
TAG PROMPT VALUE
NAME NAME OF PANEL A
RHEIGHT RIGHT HEIGHT 5
LHEIGHT LEFT HEIGHT 7
I need to rename LHEIGHT AND RHEIGHT along with the Prompt Values.
Is there some way to do it through ObjectARX
The basic steps are:
1. Open the owner AcDbBlockTableRecord AcDb::kForRead
2. Create an iterator
3. Close the AcDbBlockTableRecord
4. When you find one an AcDbAttributeDefinition that you want to change...
5. Open it AcDb::kForWrite; modify it; close it
6. Delete the iterator
Hello Owen,
Thanks for your reply.
I did get through the steps but I am not sure on how to get through the AttributeDefinition once I get the required Block.
I am using the code as follows;
pCurDb = acdbHostApplicationServices()->workingDatabase();
es =pCurDb->getBlockTable(pBlkTbl, AcDb::kForRead);
if(!pBlkTbl->has(_T("BLOCK")))
{
acutPrintf(L"\nBlock definition TEST does not exist");
pBlkTbl->close();
return;
}
es = pBlkTbl->getAt(L"BLOCK", pBlkRec, AcDb::kForWrite);
...... Not sure after this.
I'm happy to help, but I won't write the code for you for free.
Thanks Owen,
I dont want the code.
I think I am missing on some points. If you could help me with that, I would appreciate it.
Thanks
This API requires you to be able to crawl before you can walk, and walk before you can run. Copying and pasting code is no substitute for real programming. I recommend to spend a few weeks to work through some ObjectARX tutorials so that you obtain a solid foundation to build on. I think you will find that once you have invested some time to learn the basics such as drawing database structure and object access, your rudimentary task will become simple and you'll be able to complete it on your own without any assistance.
If you do need assistance, you're more likely to get help if you ask specific questions and demonstrate that you have made a real attempt on your own by showing what you tried, what you expected to happen, and how it failed (including error messages, etc.).