ObjectARX, AutoCAD. Среда программирования библиотеки C++

       

Пример формирования зависимостей в объекте


Следующий пример показывает, как Вы можете использовать реакторы, чтобы установить зависимости среди объектов базы данных. В этом примере, когда Вы изменяете одну линию, другие изменяются тоже.

class AsdkObjectToNotify : public AcDbObject

//

// AsdkObjectToNotify - customized AcDbObject for persistent

// reactor to notify.

//

{

public:

ACRX_DECLARE_MEMBERS(AsdkObjectToNotify);

AsdkObjectToNotify() {};

void eLinkage(AcDbObjectId i, double f=1.0)

{mId=i; mFactor=f; };

void modified(const AcDbObject*);



Acad::ErrorStatus dwgInFields(AcDbDwgFiler*);

Acad::ErrorStatus dwgOutFields(AcDbDwgFiler*) const;

Acad::ErrorStatus dxfInFields(AcDbDxfFiler*);

Acad::ErrorStatus dxfOutFields(AcDbDxfFiler*) const;

private:

AcDbObjectId mId;

double mFactor;

};

ACRX_DXF_DEFINE_MEMBERS(AsdkObjectToNotify, AcDbObject,

AcDb::kDHL_CURRENT, AcDb::kMReleaseCurrent,

0, ASDKOBJECTTONOTIFY, persreac);

// This function is called every time the line it’s

// "watching" is modified. When it’s called, it opens the

// other line of the pair and changes that line’s length to

// match the new length of the line that’s just been

// modified.

//

void

AsdkObjectToNotify::modified(const AcDbObject* pObj)

{

AcDbLine *pLine = AcDbLine::cast(pObj);

if (!pLine) {

const char* cstr = pObj->isA()->name();

acutPrintf("This is a %s.\n", cstr);

acutPrintf("I only work with lines. Sorry.\n");

return;

}

acutPrintf("\nReactor attached to %lx calling %lx.\n",

pLine->objectId(), mId);

// This open will fail during notification caused by a

// reactor being added to the entity or when this

// notification is in reaction to a change due to the

// other line’s reactor changing this line. This will

// properly prevent an infinite recursive loop

// between the two lines and their reactors.

//

AcDbLine *pLine2;

if (acdbOpenObject((AcDbObject*&)pLine2, mId, AcDb::kForWrite) == Acad::eOk)

{

// Get length of line entity we’re being notified


// has just been modified.
//
AcGePoint3d p = pLine->startPoint();
AcGePoint3d q = pLine->endPoint();
AcGeVector3d v = q-p;
double len = v.length();
// update other entity to match:
//
p = pLine2->startPoint();
q = pLine2->endPoint();
v = q-p;
v = len * mFactor * v.normal();
pLine2->setEndPoint(p+v);
pLine2->close();
}
}
// Files an object’s information in.
//
Acad::ErrorStatus
AsdkObjectToNotify::dwgInFields(AcDbDwgFiler* filer)
{
assertWriteEnabled();
AcDbObject::dwgInFields(filer);
filer->readItem(&mFactor);
filer->readItem((AcDbSoftPointerId*) &mId);
return filer->filerStatus();
}
// Files an object’s information out.
//
Acad::ErrorStatus
AsdkObjectToNotify::dwgOutFields(AcDbDwgFiler* filer) const
{
assertReadEnabled();
AcDbObject::dwgOutFields(filer);
filer->writeItem(mFactor);
filer->writeItem((AcDbSoftPointerId&)mId);
return filer->filerStatus();
}
// Files an object’ s information in from DXF and AutoLISP.
//
Acad::ErrorStatus
AsdkObjectToNotify::dxfInFields(AcDbDxfFiler* filer)
{
assertWriteEnabled();
Acad::ErrorStatus es;
if ((es = AcDbObject::dxfInFields(filer)) != Acad::eOk)
{
return es;
}
// Check if we’re at the right subclass data marker.
//
if(!filer->atSubclassData("AsdkObjectToNotify")) {
return Acad::eBadDxfSequence;
}
struct resbuf rbIn;
while (es == Acad::eOk) {
if ((es = filer->readItem(&rbIn)) == Acad::eOk) {
if (rbIn.restype == AcDb::kDxfReal) {
mFactor = rbIn.resval.rreal;
} else if (rbIn.restype == AcDb::kDxfSoftPointerId)
{
// ObjectIds are filed in as ads_names.
//
acdbGetObjectId(mId, rbIn.resval.rlname);
} else { // invalid group
return(filer->pushBackItem());
}
}
}
return filer->filerStatus();
}
// Files an object’s information out to DXF and AutoLISP.
//
Acad::ErrorStatus
AsdkObjectToNotify::dxfOutFields(AcDbDxfFiler* filer) const
{
assertReadEnabled();
AcDbObject::dxfOutFields(filer);


filer->writeItem(AcDb::kDxfSubclass, "AsdkObjectToNotify");
filer->writeItem(AcDb::kDxfReal, mFactor);
filer->writeItem(AcDb::kDxfSoftPointerId, mId);
return filer->filerStatus();
}
// Creates two lines and two AsdkObjectToNotify objects and
// ties them all together.
//
void
assocLines()
{
AcDbDatabase *pDb = acdbHostApplicationServices()->workingDatabase();
AcDbObjectId aId, bId;
AcDbLine *pLineA = new AcDbLine;
pLineA->setDatabaseDefaults(pDb);
pLineA->setStartPoint(AcGePoint3d(1, 1, 0));
pLineA->setEndPoint(AcGePoint3d(2, 1, 0));
addToModelSpace(aId, pLineA);
acutPrintf( "Line A is %lx from 1,1 to 2,1.\n",
pLineA->objectId());
AcDbLine *pLineB = new AcDbLine;
pLineB->setDatabaseDefaults(pDb);
pLineB->setStartPoint(AcGePoint3d(1, 2, 0));
pLineB->setEndPoint(AcGePoint3d(2, 2, 0));
addToModelSpace(bId, pLineB);
acutPrintf("Line B is %lx from 1,2 to 2,2.\n", pLineB->objectId());
// Open the named object dictionary, and check if there is
// an entry with the key "ASDK_DICT". If not, create a
// dictionary and add it.
//
AcDbDictionary *pNamedObj;
AcDbDictionary *pNameList;
pDb->getNamedObjectsDictionary(pNamedObj, AcDb::kForWrite);
if (pNamedObj->getAt("ASDK_DICT",
(AcDbObject*&)pNameList, AcDb::kForWrite)
== Acad::eKeyNotFound)
{
pNameList = new AcDbDictionary;
AcDbObjectId DictId;
pNamedObj->setAt("ASDK_DICT", pNameList, DictId);
}
pNamedObj->close();
// Create the AsdkObjectToNotify for line A.
//
AsdkObjectToNotify *pObj = new AsdkObjectToNotify();
pObj->eLinkage(bId);
AcDbObjectId objId;
if ((pNameList->getAt("object_to_notify_A", objId)) == Acad::eKeyNotFound)
{
pNameList->setAt("object_to_notify_A", pObj, objId);
pObj->close();
} else {
delete pObj;
acutPrintf("object_to_notify_A already exists\n");
}
// Set up persistent reactor link between line A


// and AsdkObjectToNotify.
//
pLineA->addPersistentReactor(objId);
pLineA->close();
// Create the AsdkObjectToNotify for line B.
//
pObj = new AsdkObjectToNotify();
pObj->eLinkage(aId);
if ((pNameList->getAt("object_to_notify_B", objId)) == Acad::eKeyNotFound)
{
pNameList->setAt("object_to_notify_B", pObj, objId);
pObj->close();
} else {
delete pObj;
acutPrintf("object_to_notify_B already exists\n");
}
pNameList->close();
// Set up persistent reactor link between line B
// and AsdkObjectToNotify.
//
pLineB->addPersistentReactor(objId);
pLineB->close();
}
// Adds an entity to model space, but does not close
// the entity.
//
void
addToModelSpace(AcDbObjectId &objId, AcDbEntity* pEntity)
{
AcDbBlockTable *pBlockTable;
AcDbBlockTableRecord *pSpaceRecord;
acdbHostApplicationServices()->workingDatabase()
->getSymbolTable(pBlockTable, AcDb::kForRead);
pBlockTable->getAt(ACDB_MODEL_SPACE, pSpaceRecord,
AcDb::kForWrite);
pBlockTable->close();
pSpaceRecord->appendAcDbEntity(objId, pEntity);
pSpaceRecord->close();
return;
}
// This is the initialization function called from acrxEntryPoint()
// during the kInitAppMsg case. This function is used to add
// commands to the command stack.
//
void
initApp()
{
acedRegCmds->addCommand("ASDK_ALINES", "ASDK_ALINES",
"ALINES", ACRX_CMD_MODAL, assocLines);
AsdkObjectToNotify::rxInit();
acrxBuildClassHierarchy();
}
// This is the clean-up function called from acrxEntryPoint() during
// the kUnloadAppMsg case. This function removes this application’s
// command set from the command stack.
//
void
unloadApp()
{
acedRegCmds->removeGroup("ASDK_ALINES");
// Remove the AsdkObjectToNotify class from the ACRX
// runtime class hierarchy. If this is done while the
// database is still active, it should cause all objects
// of class AsdkObjectToNotify to be turned into proxies.
//
deleteAcRxClass(AsdkObjectToNotify::desc());
}
// ObjectARX entry point
//
AcRx::AppRetCode
acrxEntryPoint(AcRx::AppMsgCode msg, void* appId)
{
switch (msg) {
case AcRx::kInitAppMsg:
acrxDynamicLinker->unlockApplication(appId);
acrxDynamicLinker->registerAppMDIAware(appId);
initApp();
break;
case AcRx::kUnloadAppMsg:
unloadApp();
}
return AcRx::kRetOK;
}

Содержание раздела