Share

AcEditorReactor::commandEnded

C++

virtual void commandEnded(
    const ACHAR*
);

Description

This callback function indicates that the command cmdStr has completed.

cmdStr may be up to 257 characters (including the string terminator).

With commands involving sets of entities, and when AcEditorReactor::comandEnded() notification is sent, the last entity operated upon is still open for read even though AutoCAD is no longer looking at it. This prevents that entity from being opened for write via acdbOpenObject() within the notification callback.

There are two ways to get around this limitation:

1 The preferred method is to use a transaction to manipulate the entities within your implementation of the commandEnded(). This bypasses any problems opening objects that are still open.

Warning

When using this method, you must be sure to end or terminate the transaction before you return from the commandEnded() function.

Following is a simple example of this method:

void
AsdkEdReactor::commandEnded(const char *pCommand)
{
    // If AutoCAD is shutting down, then do nothing.
    //
    if (!acdbHostApplicationServices()->working Database())
        return;

    // get entities just operated on
    //
    ads_name sset;
    int err = acedSSGet("p", NULL, NULL, NULL, sset);
    if (err != RTNORM) {
        acutPrintf("nError acquiring previous selection set");
        return;
    }
    actrTransactionManager->startTransaction();

    long length;
    acedSSLength(sset, &length);

    ads_name en;
    AcDbObjectId eId;
    AcDbEntity *pEnt;
    for (long i=0; i < length; i++) {
        acedSSName(sset, i, en);

        Acad::ErrorStatus es = acdbGetObjectId(eId, en);
        if (es != Acad::eOk) {
            acutPrintf("nacdbGetObjectId failed: "
                "Entity name <%lx,%lx>, error %s.", en[0], en[1],
                acadErrorStatusText(es));
            acedSSFree(sset);
            return;
        }
        es = actrTransactionManager->getObject((AcDbObject*&)pEnt,
            eId, AcDb::kForWrite);
        if (es == Acad::eOk) {
            pEnt->setColorIndex(1);
            pEnt->close();
        } else {
            acutPrintf("ngetObject failed with error %s.",
                acadErrorStatusText(es));
            actrTransactionManager->abortTransaction();
            acedSSFree(sset);
            return;
        }
    }
    actrTransactionManager->endTransaction();
    acedSSFree(sset);
}

2 Within the commandEnded() implementation, you can open the entity for read and then repeatedly call its close() method until its isReallyClosing() method returns Acad::kTrue, indicating that there is now only one reader, and then use the entity's upgradeOpen() method to upgrade the open to AcDb::kForWrite.

Now the entity is in a normal open AcDb::kForWrite state, so do whatever operations you want, followed by a call to the entity's close() or cancel().

Following is a simple example of this method:

void
AsdkEdReactor::commandEnded(const char *pCommand)
{
    // If AutoCAD is shutting down, then do nothing.
    //
    if (!acdbHostApplicationServices()->working Database())
        return;

    // get entities just operated on
    //
    ads_name sset;
    int err = acedSSGet("p", NULL, NULL, NULL, sset);
    if (err != RTNORM) {
        acutPrintf("nError acquiring previous selection set");
        return;
    }

    long length;
    acedSSLength(sset, &length);

    ads_name en;
    AcDbObjectId eId;
    AcDbEntity *pEnt;
    for (long i=0; i < length; i++) {
        acedSSName(sset, i, en);

        Acad::ErrorStatus es = acdbGetObjectId(eId, en);
        if (es != Acad::eOk) {
            acutPrintf("nacdbGetObjectId failed: "
                "Entity name <%lx,%lx>, error %s.", en[0], en[1],
                acadErrorStatusText(es));
            acedSSFree(sset);
            return;
        }
        es = acdbOpenObject(pEnt, eId, AcDb::kForWrite);
        if (es == Acad::eOk) {
            pEnt->setColorIndex(cindex);
            pEnt->close();
        } else if (es == Acad::eWasOpenForRead) {
            // open it for read again to get a pointer to the
            // entity and then close it repeatedly until it's
            // down to one open for read.
            //
            acdbOpenObject(pEnt, eId, AcDb::kForRead);
            do
                pEnt->close();
            while (!pEnt->isReallyClosing());

            // Now that we're down to one open for read, upgrade
            // the open to kForWrite.
            //
            pEnt->upgradeOpen();

            // do what we want and then close
            //
            pEnt->setColorIndex(1);
            pEnt->close();
        } else {
            acutPrintf("nacdbOpenObject failed with error %s.",
                acadErrorStatusText(es));
            acedSSFree(sset);
            return;
        }
    }
    acedSSFree(sset);
}

Parameters

Parameters Description
cmdStr Passed in string of the command being executed

Links

AcEditorReactor Class

Was this information helpful?