This protocol extension example is divided into three parts:
// This is the AsdkEntTemperature protocol extension abstract base // class. Notice that this is the lowest level that uses // the ACRX macros. // class AsdkEntTemperature : public AcRxObject { public: ACRX_DECLARE_MEMBERS(AsdkEntTemperature); virtual double reflectedEnergy(AcDbEntity*) const = 0; }; ACRX_NO_CONS_DEFINE_MEMBERS(AsdkEntTemperature, AcRxObject); // This is the default implementation to be attached to AcDbEntity // as a catch-all. This guarantees that this protocol extension will // be found for any entity, so the search up the AcRxClass tree will // not fail and abort AutoCAD. // class AsdkDefaultTemperature : public AsdkEntTemperature { public: virtual double reflectedEnergy(AcDbEntity* pEnt) const; }; double AsdkDefaultTemperature::reflectedEnergy( AcDbEntity* pEnt) const { acutPrintf( "\nThis entity has no area, and no reflection.\n"); return -1.0; } // AsdkEntTemperature implementation for Regions // class AsdkRegionTemperature : public AsdkEntTemperature { public: virtual double reflectedEnergy(AcDbEntity* pEnt) const; }; double AsdkRegionTemperature::reflectedEnergy( AcDbEntity* pEnt) const { AcDbRegion *pRegion = AcDbRegion::cast(pEnt); if (pRegion == NULL) acutPrintf("\nThe impossible has happened!"); // Compute the reflected energy as the region area multiplied // by a dummy constant. // double retVal; if (pRegion->getArea(retVal) != Acad::eOk) return -1.0; return retVal * 42.0; } // AsdkEntTemperature implementation for circles // class AsdkCircleTemperature : public AsdkEntTemperature { public: virtual double reflectedEnergy(AcDbEntity* pEnt) const; }; double AsdkCircleTemperature::reflectedEnergy( AcDbEntity* pEnt) const { AcDbCircle *pCircle = AcDbCircle::cast(pEnt); // Compute the reflected energy in a manner distinctly // different than for AcDbRegion. // return pCircle->radius() * 6.21 * 42.0; } // This function has the user select an entity and then // calls the reflectedEnergy() function in the protocol // extension class attached to that entity's class. // void energy() { AcDbEntity *pEnt; AcDbObjectId pEntId; ads_name en; ads_point pt; if (acedEntSel("\nSelect an Entity: ", en, pt) != RTNORM) { acutPrintf("Nothing Selected\n"); return; } acdbGetObjectId(pEntId, en); acdbOpenObject(pEnt, pEntId, AcDb::kForRead); // call the protocol extension class's method // double eTemp = ACRX_X_CALL(pEnt, AsdkEntTemperature)->reflectedEnergy(pEnt); acutPrintf("\nEnergy == %f\n", eTemp); pEnt->close(); } // Pointers for protocol extension objects. These pointers // are global so that they can be accessed during // initialization and cleanup. // AsdkDefaultTemperature *pDefaultTemp; AsdkRegionTemperature *pRegionTemp; AsdkCircleTemperature *pCircleTemp; // Initialization function called from acrxEntryPoint() during // kInitAppMsg case. This function is used to add commands // to the command stack and to add protocol extension // objects to classes. // void initApp() { acrxRegisterService("AsdkTemperature"); AsdkEntTemperature::rxInit(); acrxBuildClassHierarchy(); pDefaultTemp = new AsdkDefaultTemperature(); pRegionTemp = new AsdkRegionTemperature(); pCircleTemp = new AsdkCircleTemperature(); // Add the protocol extension objects to the appropriate // AcRxClass objects. // AcDbEntity::desc()->addX(AsdkEntTemperature::desc(), pDefaultTemp); AcDbRegion::desc()->addX(AsdkEntTemperature::desc(), pRegionTemp); AcDbCircle::desc()->addX(AsdkEntTemperature::desc(), pCircleTemp); acedRegCmds->addCommand("ASDK_TEMPERATURE_APP", "ASDK_ENERGY", "ENERGY", ACRX_CMD_TRANSPARENT, energy); } void unloadApp() { delete acrxServiceDictionary->remove("AsdkTemperature"); acedRegCmds->removeGroup("ASDK_TEMPERATURE_APP"); // Remove protocol extension objects from the AcRxClass // object tree. This must be done before removing the // AsdkEntTemperature class from the ACRX runtime class // hierarchy, so the AsdkEntTemperature::desc() // still exists. // AcDbEntity::desc()->delX(AsdkEntTemperature::desc()); delete pDefaultTemp; AcDbRegion::desc()->delX(AsdkEntTemperature::desc()); delete pRegionTemp; AcDbCircle::desc()->delX(AsdkEntTemperature::desc()); delete pCircleTemp; // Remove the AsdkEntTemperature class from the ARX // runtime class hierarchy. // deleteAcRxClass(AsdkEntTemperature::desc()); } 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; }