命名对象字典对其条目具有软所有权。因此,这些条目不会被克隆。如有必要,由应用程序来复制这些对象。wblockClone() 在 INSERT 命令期间,不会复制命名对象字典中的应用程序定义条目。应用程序必须在该阶段执行所需的克隆,将对象 ID 添加到 ID 映射,并向名为对象字典的目标添加新条目。有关详细信息,请参阅编辑器反应器通知函数。beginDeepCloneXlation()beginDeepCloneXlation() 在 WBLOCK 命令期间,原始命名对象字典中的所有 ID 都将转到目标命名对象字典,但不会自动复制指向的对象。如果应用程序未克隆 ID 指向的对象,则会在翻译期间从目标字典中删除该 ID。同样,应用程序需要克隆对象并将 ID 添加到 ID 映射中。它不需要向目标命名对象字典添加新 ID,因为此任务是自动执行的。endDeepClone()beginDeepCloneXlation 下面的示例演示如何为放置在命名对象字典中的用户定义的对象字典编写函数。该示例仅涉及上下文。AcEditorReactor::beginDeepCloneXlation()kDcWblockkDcInsert // This example demonstrates a way to handle objects in // the named object dictionary for WBLOCK and INSERT. // Our object is an AcDbDictionary, which is called // "AsdkDictionary" in the named objects dictionary, // containing our custom objects. // const char *kpDictionary = "AsdkDictionary"; // AsdkNODEdReactor is derived from AcEditorReactor. // void AsdkNODEdReactor::beginDeepCloneXlation( AcDbIdMapping& idMap, Acad::ErrorStatus* pRetStat) { Acad::ErrorStatus es; AcDbObjectId dictId; if ( idMap.deepCloneContext() != AcDb::kDcWblock && idMap.deepCloneContext() != AcDb::kDcInsert) return; // Get the "from" and "to" databases. // AcDbDatabase *pFrom, *pTo; idMap.origDb(pFrom); idMap.destDb(pTo); // See if the "from" database has our dictionary, and // open it. If it doesn't have one, we are done. // AcDbDictionary *pSrcNamedObjDict; pFrom->getNamedObjectsDictionary(pSrcNamedObjDict, AcDb::kForRead); es = pSrcNamedObjDict->getAt(kpDictionary, dictId); pSrcNamedObjDict->close(); if (es == Acad::eKeyNotFound) return; AcDbDictionary *pSrcDict; acdbOpenObject(pSrcDict, dictId, AcDb::kForRead); AcDbObject *pClone; switch (idMap.deepCloneContext()) { case AcDb::kDcWblock: // WBLOCK clones all or part of a drawing into a // newly created drawing. This means that the // named object dictionary is always cloned, and // its AcDbObjectIds are in flux. Therefore, you // cannot use getAt() or setAt() on the dictionary // in the new database. This is because the // cloned dictionary references all refer to the // original objects. During deep clone translation, // all cloned entries will be translated to the // new objects, and entries not cloned will be // "removed" by getting "translated" to NULL. // // The cloning of entries in our own dictionary are // not handled here. If all are to be cloned, then // call setTreatElementsAsHard(Adesk::kTrue) on the // dictionary. Otherwise, only those entries that // are referred to by hard references in other // wblocked objects will have been cloned via // those references. // In this example, we will always write out all of // the records. Since TreatElementsAsHard is not // currently persistent, we reset it here each time. // pSrcDict->upgradeOpen(); pSrcDict->setTreatElementsAsHard(Adesk::kTrue); pClone = NULL; pSrcDict->wblockClone(pTo, pClone, idMap, Adesk::kFalse); if (pClone != NULL) pClone->close(); break; case AcDb::kDcInsert: // In INSERT, an entire drawing is cloned, and // "merged" into a pre-existing drawing. This // means that the destination drawing may already // have our dictionary, in which case we have to // merge our entries into the destination // dictionary. First we must find out if // the destination named objects dictionary contains // our dictionary. // AcDbDictionary *pDestNamedDict; pTo->getNamedObjectsDictionary(pDestNamedDict, AcDb::kForWrite); // Since INSERT does not clone the destination // named object dictionary, we can use getAt() // on it. // es = pDestNamedDict->getAt(kpDictionary, dictId); // If our dictionary does not yet exist in the // named object dictionary, which is not itself // cloned, we have to both clone and add our // dictionary to it. Since dictionary entries are // ownership references, all of our entries will // also be cloned at this point, so we are done. // if (es == Acad::eKeyNotFound) { pClone = NULL; pSrcDict->deepClone(pDestNamedDict, pClone, idMap); // Unless we have overridden the deepClone() // of our dictionary, we should expect it to // always be cloned here. // if (pClone == NULL) { *pRetStat = Acad::eNullObjectId; break; } pDestNamedDict->setAt(kpDictionary, pClone, dictId); pDestNamedDict->close(); pClone->close(); break; } pDestNamedDict->close(); // Our dictionary already exists in the destination // database, so now we must "merge" the entries // into it. Since we have not cloned our // destination dictionary, its object IDs are not in // flux, and we can use getAt() and setAt() on it. // AcDbDictionary *pDestDict; acdbOpenObject(pDestDict, dictId, AcDb::kForWrite); AcDbObject *pObj, *pObjClone; AcDbDictionaryIterator* pIter; pIter = pSrcDict->newIterator(); for (; !pIter->done(); pIter->next()) { const char *pName = pIter->name(); pIter->getObject(pObj, AcDb::kForRead); // If the dictionary contains any references // and/or other objects have references to it, // you must either use deepClone() or put the // ID pairs into the ID map here, so that they // will be in the map for translation. // pObjClone = NULL; pObj->deepClone(pDestDict, pObjClone, idMap); // INSERT usually uses a method of cloning // called CheapClone, where it "moves" objects // into the destination database instead of // actually cloning them. When this happens, // pObj and pObjClone are pointers to the // same object. We only want to close pObj // here if it really is a different object. // if (pObj != pObjClone) pObj->close(); if (pObjClone == NULL) continue; // If the name already exists in our // destination dictionary, it must be changed // to something unique. In this example, the // name is changed to an anonymous entry. // The setAt() method will automatically append // a unique identifier to each name beginning // with "*", for example: "*S04". // if ( pDestDict->getAt(pName, dictId) == Acad::eKeyNotFound) pDestDict->setAt(pName, pObjClone, dictId); else pDestDict->setAt("*S", pObjClone, dictId); pObjClone->close(); } delete pIter; pDestDict->close(); break; default: break; } pSrcDict->close(); } |
|Archiver|CAD开发者社区 ( 苏ICP备2022047690号-1 苏公网安备32011402011833)
GMT+8, 2025-1-8 19:36
Powered by Discuz! X3.4
Copyright © 2001-2021, Tencent Cloud.