CAD开发者社区

 找回密码
 立即注册

QQ登录

只需一步,快速开始

ObjectARX 开发指南

示例:构建对象依赖项

2022-12-31 19:57| 发布者: admin| 查看: 264| 评论: 0|来自: AutoCAD

下面的示例演示如何使用反应器在数据库对象之间建立依赖关系。在此示例中,当您更改一行时,另一行也会更改。

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 fails 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
    // properly prevents an infinite recursive loop
    // between the two lines and their reactors.
    // 
    AcDbLine *pLine2;
    if (acdbOpenObject((AcDbObject*&)pLine2, mId,
        AcDb::kForWrite) == Acad::eOk)
    {
        // Gets 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();
        // Updates 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;
    }
    // Checks 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());
    // Opens the named object dictionary, and checks if there is
    // an entry with the key "ASDK_DICT". If not, creates 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();
    // Creates 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");
    }
    // Sets up persistent reactor link between line A
    // and AsdkObjectToNotify.
    //
    pLineA->addPersistentReactor(objId);
    pLineA->close();
    // Creates 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();
    // Sets 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");
    // Removes 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
//
extern "C" 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;
}

路过

雷人

握手

鲜花

鸡蛋

最新评论

QQ|Archiver|CAD开发者社区 ( 苏ICP备2022047690号-1 )

GMT+8, 2024-5-19 13:52

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

返回顶部