Формирование Иерархии Монопольных использований
Следующий пример иллюстрирует, как формировать иерархию монопольных использований, используя функции ObjectARX. Пример показывает заголовку и исходным файлам для нового класса, OwnerDemo, который иллюстрирует, как создать дерево монопольных использований. Этот класс имеет два компонента данных, простое целое число, чтобы представить нормальные данные, и жесткое монопольное использование компонент данных ИДЕНТИФИКАТОРА, чтобы провести{*держать*} объект ID находящегося в собственности объекта. Функции
Обеспечиваются для получения и установки значений обоих компонентов данных.
Пример также отменяет четыре требуемых виртуальных функции:
dwgInFields(), dwgOutFields(), dxfInFields(), и dxfOutFields().
Иерархия монопольных использований установлена в createObjs () подпрограмма к концу примера. Объект имеет объект B. Объект B имеет объект C. Объект добавлен к словарю (ASDK_DICT) в названном объектном словаре. printOut() и listTree () подпрограммы печатает информацию относительно объектов в ASDK_DICT словаре.
ObjectARX Example
// Class declarations
//
class AsdkOwnerDemo : public AcDbObject
// This is a custom object class to demonstrate what is
// necessary to create ownership trees.
//
// To keep it simple, this class has two data members: a
// simple integer to represent normal data, and a hard
// ownership ID data member to hold the object ID of an owned
// object.
//
// Get and set functions are provided for both data members.
//
{
public:
ACRX_DECLARE_MEMBERS(AsdkOwnerDemo);
AsdkOwnerDemo(): mIntval(0) {};
AsdkOwnerDemo(const Adesk::Int16& val): mIntval(val) {};
Adesk::Int16 intData();
Acad::ErrorStatus setIntData(const Adesk::Int16&);
AcDbHardOwnershipId idData();
Acad::ErrorStatus setIdData(const AcDbHardOwnershipId&);
Acad::ErrorStatus dwgInFields (AcDbDwgFiler*);
Acad::ErrorStatus dwgOutFields(AcDbDwgFiler*) const;
Acad::ErrorStatus dxfInFields (AcDbDxfFiler*);
Acad::ErrorStatus dxfOutFields(AcDbDxfFiler*) const;
private:
Adesk::Int16 mIntval;
AcDbHardOwnershipId mObjId;
};
ACRX_DXF_DEFINE_MEMBERS(AsdkOwnerDemo, AcDbObject,
AcDb::kDHL_CURRENT, AcDb::kMReleaseCurrent, 0,
ASDKOWNERDEMO, OWNERSHIP);
// Gets the value of the integer data member.
//
Adesk::Int16
AsdkOwnerDemo::intData()
{
assertReadEnabled();
return mIntval;
}
// Sets the value of the integer data member.
//
Acad::ErrorStatus
AsdkOwnerDemo::setIntData(const Adesk::Int16& val)
{
assertWriteEnabled();
mIntval = val;
return Acad::eOk;
}
// Returns a copy of the ownership ID data member.
//
AcDbHardOwnershipId
AsdkOwnerDemo::idData()
{
assertReadEnabled();
return mObjId;
}
// Sets the value of the ownership ID data member.
//
Acad::ErrorStatus
AsdkOwnerDemo::setIdData(const AcDbHardOwnershipId& ownedId)
{
if (ownedId.asOldId() == 0L) {
return Acad::eInvalidInput;
}
assertWriteEnabled();
mObjId = ownedId;
// Now set the backpointer. A transaction is used for
// opening the object, so if the object is already
// open it won’t prevent this setting from taking place.
//
AcDbObject *pObj;
AcTransaction *pTrans
= actrTransactionManager->startTransaction();
pTrans->getObject(pObj, ownedId, AcDb::kForWrite);
pObj->setOwnerId(objectId());
actrTransactionManager->endTransaction();
return Acad::eOk;
}
// Files data in from a DWG file.
//
Acad::ErrorStatus
AsdkOwnerDemo::dwgInFields(AcDbDwgFiler* filer)
{
assertWriteEnabled();
AcDbObject::dwgInFields(filer);
// For wblock filing we wrote out our owner as a hard
// pointer Id so now we need to read it in to keep things
// in sync.
//
if (filer->filerType() == AcDb::kWblockCloneFiler) {
AcDbHardPointerId id;
filer->readItem(&id);
}
filer->readItem(&mIntval);
filer->readItem(&mObjId);
return filer->filerStatus();
}
// Files data out to a DWG file.
//
Acad::ErrorStatus
AsdkOwnerDemo::dwgOutFields(AcDbDwgFiler* filer) const
{
assertReadEnabled();
AcDbObject::dwgOutFields(filer);
// Since objects of this class will be in the Named
// Objects Dictionary tree and may be hard referenced
// by some other object, to support wblock we need to
// file out our owner as a hard pointer Id so that it
// will be added to the list of objects to be wblocked
//
if (filer->filerType() == AcDb::kWblockCloneFiler)
filer->writeHardPointerId((AcDbHardPointerId)ownerId());
filer->writeItem(mIntval);
filer->writeItem(mObjId);
return filer->filerStatus();
}
// Files data in from a DXF file.
//
Acad::ErrorStatus
AsdkOwnerDemo::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("AsdkOwnerDemo")) {
return Acad::eBadDxfSequence;
}
struct resbuf inbuf;
while (es == Acad::eOk) {
if ((es = filer->readItem(&inbuf)) == Acad::eOk) {
if (inbuf.restype == AcDb::kDxfInt16) {
mIntval = inbuf.resval.rint;
} else if (inbuf.restype == AcDb::kDxfHardOwnershipId)
{
acdbGetObjectId(mObjId,
inbuf.resval.rlname);
}
}
}
return filer->filerStatus();
}
// Files data out to a DXF file.
//
Acad::ErrorStatus
AsdkOwnerDemo::dxfOutFields(AcDbDxfFiler* filer) const
{
assertReadEnabled();
AcDbObject::dxfOutFields(filer);
filer->writeItem(AcDb::kDxfSubclass, "AsdkOwnerDemo");
filer->writeItem(AcDb::kDxfInt16, mIntval);
// Null object IDs are invalid: don’t write them out.
//
if (mObjId.asOldId() != 0L) {
filer->writeItem(AcDb::kDxfHardOwnershipId, mObjId);
}
return filer->filerStatus();
}
// Creates an AsdkOwnerDemo object (pObjC) and adds data to
// it. Then, AsdkOwnerDemo pObjC is created and set to be
// the owner of pObjC. Next, AsdkOwnerDemo pObjA is created
// and set to own pObjB. Finally, pObjA is added to a
// dictionary in the named object dictionary. Technically,
// we could just add pObjA to the named object dictionary
// itself, but that’ s not appropriate because it would clutter
// up the named object dictionary.
//
void
createObjs()
{
AcDbObjectId objIdA, objIdB, objIdC;
AcDbDictionary *pNamedobj;
AcDbDictionary *pDict = NULL;
AcDbDatabase *pCurDwg = acdbHostApplicationServices()->workingDatabase();
// Create object C with a dummy integer data value of 3.
//
AsdkOwnerDemo *pObjC = new AsdkOwnerDemo(3);
// Append object C to database without setting an owner.
//
pCurDwg->addAcDbObject(objIdC, pObjC);
pObjC->close();
// Create object B with a dummy integer data value of 2.
//
AsdkOwnerDemo *pObjB = new AsdkOwnerDemo(2);
// Append object B to the database without setting an owner.
//
pCurDwg->addAcDbObject(objIdB, pObjB);
// Now set up ownership for object C. The
// AsdkOwnerDemo::setIdData() function takes the
// objectId parameter and copies it into the
// AcDbHardOwnershipId data member. This places the
// object ID in a position to be filed out/in via the
// dwgInFields/dwgOutFields/dxfInFields/dxfOutFields
// member functions. This constitutes primary
// "ownership." The AsdkOwnerDemo::setIdData() function
// also calls each owned object’s setOwnerId() member
// function to set the backpointer and establish the
// full two-way ownership link.
//
pObjB->setIdData(objIdC);
pObjB->close();
// Create object A with a dummy integer data value of 1.
//
AsdkOwnerDemo *pObjA = new AsdkOwnerDemo(1);
// Next, add objA to a dictionary in the named object
// dictionary. This will establish ownership for objA,
// set the ownership backlink, and add it to the
// database.
//
pCurDwg->getNamedObjectsDictionary(pNamedobj, AcDb::kForWrite);
// Get a pointer to the ASDK_DICT dictionary. If it
// doesn’t exist, then create it and add it to the
// named object dictionary.
//
if (pNamedobj->getAt("ASDK_DICT", (AcDbObject*&) pDict,
AcDb::kForWrite) == Acad::eKeyNotFound)
{
pDict = new AcDbDictionary;
AcDbObjectId DictId;
pNamedobj->setAt("ASDK_DICT", pDict, DictId);
}
pNamedobj->close();
// Add object A to the ASDK_DICT dictionary.
//
pDict->setAt("OBJA", pObjA, objIdA);
pDict->close();
// Now set up ownership for object B.
//
pObjA->setIdData(objIdB);
pObjA->close();
}
// The list tree function runs through all objects in the
// ASDK_DICT dictionary, follows their ownership trees, and
// lists out information on all objects in the tree.
//
void
listTree()
{
AcDbDictionary *pNamedobj;
AcDbDictionary *pDict;
acdbHostApplicationServices()->workingDatabase()
->getNamedObjectsDictionary(pNamedobj, AcDb::kForWrite);
// Get a pointer to the ASDK_DICT dictionary.
//
pNamedobj->getAt("ASDK_DICT",(AcDbObject*&)pDict,
AcDb::kForRead);
pNamedobj->close();
// Run through the entries and list their backpointers.
//
AcDbDictionaryIterator *pDictItr = pDict->newIterator();
for (; !pDictItr->done(); pDictItr->next()) {
printOut(pDictItr->objectId());
}
pDict->close();
}
// Recursively walks down an ownership tree of AsdkOwnerDemo
// class objects, printing out information on each one.
//
void
printOut(AcDbObjectId id)
{
AsdkOwnerDemo *pDemo;
acdbOpenObject((AcDbObject*&)pDemo, id, AcDb::kForRead);
acutPrintf("\nIntdata: %d ObjId: %ld Backpointer:"
" %ld OwnedObj: %ld", pDemo->intData(),
(pDemo->objectId()).asOldId(),
(pDemo->ownerId()).asOldId(),
(pDemo->idData()).asOldId());
// Recursive tree walk
//
if ((pDemo->idData()).asOldId() != 0L) {
printOut(pDemo->idData());
}
pDemo->close();
}
// The initialization function is called from acrxEntryPoint()
// during kInitAppMsg case. This function is used to add commands
// to the command stack and to add classes to the ACRX class
// hierarchy.
//
void
initApp()
{
acedRegCmds->addCommand("ASDK_OWNERSHIP_COMMANDS",
"ASDK_CREATE", "CREATE",ACRX_CMD_MODAL, createObjs);
acedRegCmds->addCommand("ASDK_OWNERSHIP_COMMANDS",
"ASDK_LISTREE", "LISTREE",ACRX_CMD_MODAL, listTree);
AsdkOwnerDemo::rxInit();
acrxBuildClassHierarchy();
}
// The clean up function is called from acrxEntryPoint() during the
// kUnloadAppMsg case. This function removes this application’s
// command set from the command stack and the
// AsdkOwnerDemo class from the ARX runtime class tree.
//
void
unloadApp()
{
acedRegCmds->removeGroup("ASDK_OWNERSHIP_COMMANDS");
// Remove the AsdkOwnerDemo class from the ACRX runtime
// class hierarchy. If this is done while the database is
// still active, it should cause all objects of class
// AsdkOwnerDemo to be turned into proxies.
//
deleteAcRxClass(AsdkOwnerDemo::desc());
}
// ObjectARX entry point
//
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;
}