AcDbVoidPtrArray *pReactors;
void *pSomething;
AcDbObjectReactor *pObjReactor;
AcDbObjectId persObjId;
AcDbObject *pPersReacObj;
pReactors = pEnt->reactors();
if (pReactors!= NULL && pReactors->length() > 0) {
for (int i = 0; i < pReactors->length(); i++) {
pSomething = pReactors->at(i);
// Is it a persistent reactor?
//
if (acdbIsPersistentReactor(pSomething)) {
persObjId = acdbPersistentReactorObjectId(pSomething);
acutPrintf("\n\nPersistent reactor found.");
// Echo the keyname to the user.
//
char *keyname = NULL;
getPersReactorKey(keyname, persObjId);
if (keyname) {
acutPrintf("\nThis is the reactor named %s",keyname);
free (keyname);
}
// Open it up and see if it’s one of ours. If it is,
// fire the custom notification.
//
if ((retStat = acdbOpenAcDbObject(pPersReacObj, persObjId, AcDb::kForNotify))
!= Acad::eOk)
{
acutPrintf("\nFailure for"
" openAcDbObject: retStat==%d\n",
retStat);
return;
}
AsdkPersReactor *pTmpPers;
if ((pTmpPers = AsdkPersReactor::cast((AcRxObject*)
pPersReacObj)) != NULL)
{
pTmpPers->custom();
}
pPersReacObj->close();
} else {
// Or is it transient?
//
pObjReactor = (AcDbObjectReactor *)
(pReactors->at(i));
acutPrintf("\n\nTransient Reactor found");
// Report what kind we found.
//
if (pObjReactor->isKindOf(
AsdkSimpleObjReactor::desc()))
{
acutPrintf(" of type"
" AsdkSimpleObjReactor");
} else if (pObjReactor->isKindOf(AcDbEntityReactor::desc()))
{
acutPrintf(" of type"
" AcDbEntityReactor");
} else if (pObjReactor->isKindOf(AcDbObjectReactor::desc()))
{
acutPrintf(" of type"
" AcDbObjectReactor");
} else {
acutPrintf(" of unknown type.");
}
}
}
} else {
acutPrintf("\nThis entity has no reactors.\n");
}
Пример формирования зависимостей в объекте
Следующий пример показывает, как Вы можете использовать реакторы, чтобы установить зависимости среди объектов базы данных. В этом примере, когда Вы изменяете одну линию, другие изменяются тоже.
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
|
Из за большого объема этот материал размещен на нескольких страницах:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 |


