Handling Hard References to AcDbEntities During wblockClone(): CASE 1

If the referring and referenced entities always exist in the same AcDbBlockTableRecord, it is sufficient for the referring entity's overridden wblock() to forward the isPrimary value it received to call the referenced entity's wblock(). This takes advantage of the default behavior of all three forms of WBLOCK, as noted in the previous section. We do not need to be concerned with which type of WBLOCK is occurring.

Here are two ways to override the default behavior of wblock clone for this case. First, you could overwrite the entire wblockClone() for the referring entity. In the sample code for the default implementation of wblockClone() (in the previous section), you'll see a loop on getNextHardObject(). Within this loop you would have to intercept the referenced object's ID and change the isPrimary value from Adesk::kFalse to be the same as the isPrimary value passed in.

However, a much simpler way to do this is to continue to use the default wblockClone() for your custom entity, but clone the referenced entity first, with the correct settings, when the default setting of isPrimary would not be correct. Once you've cloned the referenced entity, when you call your own wblockClone(), it will see that the referenced entity is already cloned and will not attempt to clone it using the default settings. The following sample demonstrates this. The data member, mRefEnt, is the reference AcDbHardPointerId.

Acad::ErrorStatus
AsdkEntity::wblockClone(AcRxObject* pOwner,
                        AcDbObject*& pClone,
                        AcDbIdMapping& idMap,
                        Adesk::Boolean isPrimary) const
{
    // If isPrimary is kTrue, then override the default cloning
    // within our own cloning, which would set it to kFalse,
    // by cloning our referenced entity first.
    //
    if (isPrimary) {
        Acad::ErrorStatus es;
        AcDbEntity* pEnt;
        es = acdbOpenAcDbEntity(pEnt, mRefEnt, AcDb::kForRead);
        if (es != Acad::eOk)
            return es;
        // Use the same owner, and pass in the same isPrimary
        // value.
        //
        AcDbObject* pSubClone = NULL;
        es = pEnt->wblockClone(pOwner, pSubClone, idMap, kTrue);
        if (pSubClone != NULL)
            pSubClone->close();
        pEnt->close();
        if (es != Acad::eOk)
           return es;
    }
    // Now we can clone ourselves by calling our parent's method.
    //
    return AcDbEntity::wblockClone(pOwner, pClone, idMap,
        isPrimary);
}