void ArxDbgAppEditorReactor::searchOneDictionary(AcDbDictionary* dict, AcDbObjectIdArray& objIds) { // get an iterator over this dictionary AcDbDictionaryIterator* dictIter = dict->newIterator(); ASSERT(dictIter != NULL); // walk dictionary and just collect all the entries that are of the // given type AcDbObject* obj; for (; !dictIter->done(); dictIter->next()) { if (acdbOpenAcDbObject(obj, dictIter->objectId(), AcDb::kForRead) == Acad::eOk) { if (obj->isKindOf(ArxDbgDbDictRecord::desc())) { objIds.append(obj->objectId()); } else if (obj->isKindOf(AcDbDictionary::desc())) { searchOneDictionary(AcDbDictionary::cast(obj), objIds); } obj->close(); } } delete dictIter; dict->close(); }
bool ArxDbgUtils::isOnLockedLayer(AcDbEntity* ent, bool printMsg) { AcDbObject* obj; AcDbLayerTableRecord* layer; bool isLocked = false; Acad::ErrorStatus es; es = acdbOpenAcDbObject(obj, ent->layerId(), AcDb::kForRead); if (es == Acad::eOk) { layer = AcDbLayerTableRecord::cast(obj); if (layer) isLocked = layer->isLocked(); else { ASSERT(0); } obj->close(); } else { ASSERT(0); ArxDbgUtils::rxErrorMsg(es); } if (isLocked && printMsg) { acutPrintf(_T("\nSelected entity is on a locked layer.")); } return isLocked; }
BOOL ArxDbgUiTdcObjects::OnInitDialog() { ArxDbgUiTdcDbObjectBase::OnInitDialog(); m_lbObjList.ResetContent(); AcDbObject* obj; CString str; Acad::ErrorStatus es; int len = m_objList.length(); for (int i=0; i<len; i++) { es = acdbOpenAcDbObject(obj, m_objList[i], AcDb::kForRead, true); // might have passed in erased ones if (es == Acad::eOk) { ArxDbgUtils::objToClassAndHandleStr(obj, str); m_lbObjList.AddString(str); obj->close(); } } m_lbObjList.SetCurSel(0); buildColumns(m_dataList); displayCurrent(0); return TRUE; }
void ArxDbgUiTdcObjReactorsBase::displayEntList() { m_entsAttached.setLogicalLength(0); m_lbEntList.ResetContent(); getAttachedEntities(m_entsAttached); CString str; Acad::ErrorStatus es; AcDbObject* obj; int len = m_entsAttached.length(); for (int i=0; i<len; i++) { es = acdbOpenAcDbObject(obj, m_entsAttached[i], AcDb::kForRead, true); if (es == Acad::eOk) { ArxDbgUtils::objToClassAndHandleStr(obj, str); if (obj->isErased()) str += _T(" (erased)"); m_lbEntList.AddString(str); obj->close(); } } setButtonModes(); }
// Get an AcGiTextStyle from an AcDbTextStyleTableRecord. // Try to map as many characteristics as we can. // Acad::ErrorStatus rx_getTextStyle(AcGiTextStyle &newStyle, AcDbObjectId styleId) { AcDbTextStyleTableRecord *oldStyle; Acad::ErrorStatus es = acdbOpenAcDbObject((AcDbObject *&)oldStyle, styleId, AcDb::kForRead); if (es == Acad::eOk) { const TCHAR *tmpStr; if ((es = oldStyle->fileName(tmpStr)) != Acad::eOk) { oldStyle->close(); return es; } newStyle.setFileName(tmpStr); if ((es = oldStyle->bigFontFileName(tmpStr)) != Acad::eOk) { oldStyle->close(); return es; } newStyle.setBigFontFileName(tmpStr); newStyle.setTextSize(oldStyle->textSize()); newStyle.setXScale(oldStyle->xScale()); newStyle.setObliquingAngle(oldStyle->obliquingAngle()); oldStyle->close(); newStyle.loadStyleRec(); } return es; }
static AcDbDictionary* GetDictObject( const AcDbObjectId& dictId ) { AcDbDictionary* pDict = 0; if( Acad::eOk != acdbOpenAcDbObject( ( AcDbObject*& ) pDict, dictId, AcDb::kForWrite ) ) return 0; else return pDict; }
AcDbObjectId OarxEmployeeService::getAppDictionary () { AcDbDictionary *pNOD =NULL ; AcDbDictionary *pFirmDict =NULL ; AcDbDictionary *pAppDict =NULL ; try { //----- Get hold of the NOD ARXOK ( getNOD (pNOD, AcDb::kForRead) ) ; //----- Get our Firm Dictionary AcDbObjectId id0 ; if ( pNOD->getAt (OARX_FIRM_DICT, id0) == Acad::eKeyNotFound ) { //----- Then create it pFirmDict =new AcDbDictionary ; if ( pFirmDict == NULL ) throw Acad::eOutOfMemory ; ARXOK ( pNOD->upgradeOpen () ) ; ARXOK ( pNOD->setAt (OARX_FIRM_DICT, pFirmDict, id0) ) ; } else { //----- Open the dictionary ARXOK ( acdbOpenAcDbObject ((AcDbObject *&)pFirmDict, id0, AcDb::kForRead) ) ; } //----- Get our App Dictionary if ( pFirmDict->getAt (OARX_APP_DICT, id0) == Acad::eKeyNotFound ) { //----- Then create it pAppDict =new AcDbDictionary ; if ( pAppDict == NULL ) throw Acad::eOutOfMemory ; if ( pFirmDict->isWriteEnabled () == false ) ARXOK ( pFirmDict->upgradeOpen () ) ; ARXOK ( pFirmDict->setAt (OARX_APP_DICT, pAppDict, id0) ) ; id0 =pAppDict->objectId () ; } pNOD->close () ; pFirmDict->close () ; pAppDict->close () ; return (id0) ; } catch (const Acad::ErrorStatus es) { if ( pNOD != NULL ) pNOD->cancel () ; if ( pFirmDict != NULL && pFirmDict->objectId () == AcDbObjectId::kNull ) delete pFirmDict ; else if ( pFirmDict != NULL ) pFirmDict->cancel () ; if ( pAppDict != NULL && pAppDict->objectId () == AcDbObjectId::kNull ) delete pAppDict ; else pAppDict->cancel () ; return (AcDbObjectId::kNull) ; } }
void ArxEntityHelper::EraseObject2( const AcDbObjectId& objId, Adesk::Boolean erasing ) { AcDbObject* pObj; if( Acad::eOk == acdbOpenAcDbObject( pObj, objId, AcDb::kForWrite, !erasing ) ) { pObj->erase( erasing ); pObj->close(); //acutPrintf(_T("\n使用Open/close机制删除对象成功")); } }
void AsdkWblockReactor::otherWblock(AcDbDatabase* pDestDb, AcDbIdMapping& idMap, AcDbDatabase* pSrcDb) { // To find the destination Model Space, you must look // it up in the ID map: AcDbBlockTable *pSrcBlockTable; pSrcDb->getSymbolTable(pSrcBlockTable, AcDb::kForRead); AcDbObjectId srcModelSpaceId; pSrcBlockTable->getAt(ACDB_MODEL_SPACE, srcModelSpaceId); pSrcBlockTable->close(); AcDbIdPair idPair; idPair.setKey(srcModelSpaceId); idMap.compute(idPair); AcDbBlockTableRecord *pDestBTR; acdbOpenAcDbObject((AcDbObject*&)pDestBTR, idPair.value(), AcDb::kForRead, Adesk::kTrue); // END CODE APPEARING IN SDK DOCUMENT. acutPrintf("\nCorrect destination BTR's ObjectId is:\t\t%Ld", pDestBTR->objectId().asOldId()); pDestBTR->close(); // Incorrect way done here so that the wrong value can be // compared to the correct value // AcDbBlockTable *pDestBlockTable; pDestDb->getSymbolTable(pDestBlockTable, AcDb::kForRead); pDestBlockTable->getAt(ACDB_MODEL_SPACE, pDestBTR, AcDb::kForRead); pDestBlockTable->close(); acutPrintf("\nIncorrect destination BTR's ObjectId is \t\t%Ld", pDestBTR->objectId().asOldId()); pDestBTR->close(); // source database Model Space BTR's ObjectId is shown to // demonstrate that this is what the incorrect method gets // pSrcDb->getSymbolTable(pSrcBlockTable, AcDb::kForRead); pSrcBlockTable->getAt(ACDB_MODEL_SPACE, srcModelSpaceId); pSrcBlockTable->close(); acutPrintf("\nSource Database's Model Space BTR's ObjectId is \t%Ld", srcModelSpaceId.asOldId()); }
//----------------------------------------------------------------------------- //----- This is the AcRxService class Implementation Adesk::Boolean OarxEmployeeService::isEmployeeExist (int id) { AcDbDictionary *pNOD =NULL ; AcDbDictionary *pFirmDict =NULL ; AcDbDictionary *pAppDict =NULL ; try { //----- Get hold of the NOD ARXOK ( getNOD (pNOD, AcDb::kForRead) ) ; //----- Get our Firm Dictionary AcDbObjectId id0 ; ARXOK ( pNOD->getAt (OARX_FIRM_DICT, id0) ) ; ARXOK ( acdbOpenAcDbObject ((AcDbObject *&)pFirmDict, id0, AcDb::kForRead) ) ; //----- Get our App Dictionary ARXOK ( pFirmDict->getAt (OARX_APP_DICT, id0) ) ; ARXOK ( acdbOpenAcDbObject ((AcDbObject *&)pAppDict, id0, AcDb::kForRead) ) ; //----- Check if that entry already exist char buffer [33] ; sprintf (buffer, "%d", id) ; Adesk::Boolean bRet =pAppDict->has (buffer) ; //----- Normally we should have open the associated XRecord, and check the validity of //----- the SoftPointerId which is supposed to point to an OarxEmployee entity... But //----- to simplify the sample we stop checking here! pNOD->close () ; pFirmDict->close () ; pAppDict->close () ; return (bRet) ; } catch (const Acad::ErrorStatus es) { if ( pNOD != NULL ) pNOD->cancel () ; if ( pFirmDict != NULL ) pFirmDict->cancel () ; if ( pAppDict != NULL ) pAppDict->cancel () ; return (Adesk::kFalse) ; } }
LPCTSTR ArxDbgUtils::objIdToHandleStr(const AcDbObjectId& objId, CString& str) { AcDbObject* obj; Acad::ErrorStatus es; es = acdbOpenAcDbObject(obj, objId, AcDb::kForRead); if (es != Acad::eOk) str = ACDB_NULL_HANDLE; else { ArxDbgUtils::objToHandleStr(obj, str); obj->close(); } return str; }
void ArxDbgEditorReactor::printReactorMessage(LPCTSTR event, const AcDbObjectId& objId) const { CString str; AcDbObject* obj; Acad::ErrorStatus es = acdbOpenAcDbObject(obj, objId, AcDb::kForRead); if (es == Acad::eOk) { acutPrintf(_T("\n%-15s : [%-18s: %s, %s] "), _T("[ED REACTOR]"), event, ArxDbgUtils::objToClassStr(obj), ArxDbgUtils::objToHandleStr(obj, str)); obj->close(); } else { ArxDbgUtils::rxErrorMsg(es); printReactorMessage(event); } }
void ArxDbgUiTdcPersistentReactors::attachObjReactors(const AcDbObjectIdArray& objIds) { Acad::ErrorStatus es; AcDbObject* obj; ArxDbgPersistentObjReactor* peReactor; AcDbObjectId prId; ArxDbgDocLockWrite docLock; // these potentially came from other documents int len = objIds.length(); for (int i=0; i<len; i++) { es = docLock.lock(objIds[i].database()); // lock the document associated with this database if (es == Acad::eOk) { es = acdbOpenAcDbObject(obj, objIds[i], AcDb::kForWrite, true); if (es == Acad::eOk) { prId = getPersistentObjReactor(objIds[i].database(), true); if (ArxDbgUiTdmReactors::hasPersistentReactor(obj, prId)) { ArxDbgUtils::alertBox(_T("That object already has the reactor attached.")); } else { obj->addPersistentReactor(prId); es = acdbOpenObject(peReactor, prId, AcDb::kForWrite); if (es == Acad::eOk) { peReactor->attachTo(obj->objectId()); peReactor->close(); } else { CString str; str.Format(_T("ERROR: Could not update backward reference in reactor: (%s)"), ArxDbgUtils::rxErrorStr(es)); ArxDbgUtils::stopAlertBox(str); } } obj->close(); } else { ArxDbgUtils::rxErrorMsg(es); } } else { ArxDbgUtils::rxErrorAlert(es); } } }
void ArxDbgUiTdcReferences::addEntriesToTree(const AcDbObjectIdArray& ids, HTREEITEM parent) { AcDbObject* tmpObj; HTREEITEM treeItem; Acad::ErrorStatus es; CString str; int len = ids.length(); for (int i=0; i<len; i++) { es = acdbOpenAcDbObject(tmpObj, ids[i], AcDb::kForRead, true); // might have passed in erased ones if (es == Acad::eOk) { treeItem = addOneTreeItem(ArxDbgUtils::objToClassAndHandleStr(tmpObj, str), tmpObj, parent); tmpObj->close(); } else ArxDbgUtils::rxErrorMsg(es); } }
void ArxDbgUiTdcWblockClone::divideCloneSet(const AcDbObjectIdArray& cloneSet, AcDbObjectIdArray& nonEntSet, AcDbObjectIdArray& okToCloneSet) { Acad::ErrorStatus es; AcDbObject* obj; int len = cloneSet.length(); for (int i=0; i<len; i++) { es = acdbOpenAcDbObject(obj, cloneSet[i], AcDb::kForRead); if (es == Acad::eOk) { if (obj->isKindOf(AcDbEntity::desc())) okToCloneSet.append(obj->objectId()); else nonEntSet.append(obj->objectId()); obj->close(); } } }
void ArxDbgUiTdcCloneSet::displayObjList() { m_objIds.setLogicalLength(0); m_lbObjList.ResetContent(); int index = m_lbDbList.GetCurSel(); if (index == LB_ERR) { ASSERT(0); return; } AcDbDatabase* curDb = static_cast<AcDbDatabase*>(m_dbPtrs[index]); m_cloneSet.getObjectsForDatabase(curDb, m_objIds); CString str; Acad::ErrorStatus es; AcDbObject* obj; int len = m_objIds.length(); for (int i=0; i<len; i++) { es = acdbOpenAcDbObject(obj, m_objIds[i], AcDb::kForRead, true); if (es == Acad::eOk) { ArxDbgUtils::objToClassAndHandleStr(obj, str); if (obj->isErased()) str += _T(" (erased)"); m_lbObjList.AddString(str); obj->close(); } } m_lbObjList.SetCurSel(-1); setButtonModes(); }
void PlotByPtMaxAndMin(AcGePoint3d ptMin,AcGePoint3d ptMax) { //获取当前数据库指针 AcDbDatabase *pCurDb=acdbHostApplicationServices()->workingDatabase(); //获取表记录 AcDbBlockTable *pBlockTable=NULL; AcDbBlockTableRecord *pBlkTblRcd=NULL; if(Acad::eOk != pCurDb->getBlockTable(pBlockTable,AcDb::kForRead)) return; if(Acad::eOk != pBlockTable->getAt(ACDB_MODEL_SPACE,pBlkTblRcd,AcDb::kForRead)) { pBlockTable->close(); return; } pBlockTable->close(); //获取样式ID AcDbObjectId LaoutId=pBlkTblRcd->getLayoutId(); pBlkTblRcd->close(); char* plotCfgchar = NULL; AcDbLayout *pSrcLayout = NULL; if(acdbOpenAcDbObject((AcDbObject*&)pSrcLayout,LaoutId,AcDb::kForWrite)!=Acad::eOk) return; Acad::ErrorStatus es; AcDbPlotSettingsValidator *pPltValid = acdbHostApplicationServices()->plotSettingsValidator(); if((es = pPltValid->setPlotWindowArea (pSrcLayout,0,0,100,100)) != Acad::eOk) { pSrcLayout->close(); return; } if((es =pPltValid->setPlotType (pSrcLayout, AcDbPlotSettings::PlotType::kWindow))!=Acad::eOk) { pSrcLayout->close(); return; } if((es =pSrcLayout->getPlotCfgName(plotCfgchar)) != Acad::eOk) { pSrcLayout->close(); return; } pPltValid->refreshLists(pSrcLayout); pSrcLayout->close(); if(acdbOpenAcDbObject((AcDbObject*&)pSrcLayout,LaoutId,AcDb::kForWrite)!=Acad::eOk) return; if((es = pPltValid->setPlotWindowArea (pSrcLayout,ptMin.x,ptMin.y,ptMax.x,ptMax.y)) != Acad::eOk) { pSrcLayout->close(); return; } if((es = pPltValid->setPlotType (pSrcLayout, AcDbPlotSettings::PlotType::kWindow)) != Acad::eOk) { pSrcLayout->close(); return; } if((es = pSrcLayout->getPlotCfgName(plotCfgchar)) != Acad::eOk) { pSrcLayout->close(); return; } pPltValid->refreshLists(pSrcLayout); pSrcLayout->close(); CString plotCfgName(plotCfgchar); //模型Model if(plotCfgName.Find("无")>=0) { acutPrintf("\n请设置打印样式,并置为当前!%s\n",plotCfgchar);return; } acedCommand(RTSTR,"_plot",RTSTR,"N",RTSTR,"模型",RTSTR,"",RTSTR,plotCfgName,RTSTR,"N",RTSTR,"N",RTSTR,"Y",0); }
void ArxDbgAppEditorReactor::beginDeepCloneXlation( AcDbIdMapping& idMap, Acad::ErrorStatus* es) { m_didTheseDicts.setLogicalLength(0); // reset the dictionaries we have processed AcDbDatabase* origDb; AcDbDatabase* destDb; idMap.origDb(origDb); idMap.destDb(destDb); AcDbObject* clonedObj; AcDbObject* objToClone; // we catch this event so that we can wblock objects that are not entities. // This happens from the class ArxDbgUiTdcWblockClone where you are allowed // to pick non-entities to wblock to a new/existing drawing. AcDbDatabase::wblock() // only allows entities to be in the set of objects passed to it, but you // can manually wblockClone them yourself here. if (idMap.deepCloneContext() == AcDb::kDcWblock) { // see what non-entity objects we have to clone by hand. AcDbObjectIdArray handCloneObjects; m_cloneSet.getObjectsForDatabase(origDb, handCloneObjects); if (handCloneObjects.isEmpty()) return; // walk through the clone set and try to clone // everything. If something is already cloned, // its ok, it won't be cloned again or return an // error, it will just set clonedObj to NULL. CString str; int len = handCloneObjects.length(); for (int i=0; i<len; i++) { clonedObj = NULL; if (acdbOpenAcDbObject(objToClone, handCloneObjects[i], AcDb::kForRead) == Acad::eOk) { objToClone->wblockClone(destDb, clonedObj, idMap, Adesk::kFalse); if (clonedObj != NULL) { acutPrintf(_T("\nArxDbgAppEditorReactor: cloned additional object [%s, %s]"), ArxDbgUtils::objToClassStr(clonedObj), ArxDbgUtils::objToHandleStr(objToClone, str)); clonedObj->close(); } objToClone->close(); } } } // catching this event allows us to correctly bring in our Dictionary Records. // If we don't do this, then they will be orphaned. AutoCAD will not hook up // the cloned dictionary records automatically. else if ((ArxDbgOptions::m_instance.m_doDictRecordInsertByHand) && ((idMap.deepCloneContext() == AcDb::kDcInsert) || (idMap.deepCloneContext() == AcDb::kDcInsertCopy))) { // have to manually find all things we are interested in inserting. // So, look for all ArxDbgDictRecords, if its a dict record, // make sure owner dict is cloned in new database AcDbObjectIdArray objIds; collectAllDictRecords(origDb, objIds); int len = objIds.length(); for (int i=0; i<len; i++) { // find out if object is a dict record Acad::ErrorStatus es; es = acdbOpenObject(objToClone, objIds[i], AcDb::kForRead); if (es == Acad::eOk) { acutPrintf("\nArxDbgAppEditorReactor: hand inserting [%s]", ArxDbgUtils::objToClassStr(objToClone)); // clone the owner dictionary if one of our dictionary records if (objToClone->isKindOf(ArxDbgDbDictRecord::desc())) insertCloneOwnerDict(objToClone->ownerId(), destDb, idMap); objToClone->close(); } } } }
OarxEmployee *OarxEmployeeService::createEmployee (int id, AcGePoint3d location, int cubeNumber, char *strFirstName, char *strLastName) { OarxEmployee *p =NULL ; AcDbXrecord *pRec =NULL ; AcDbDictionary *pAppDict =NULL ; try { //----- Create the object p =new OarxEmployee ; if ( p == NULL ) throw Acad::eOutOfMemory ; ARXOK ( p->setID (id) ) ; ARXOK ( p->setCubeNumber (cubeNumber) ) ; ARXOK ( p->setFirstName (strFirstName) ) ; ARXOK ( p->setLastName (strLastName) ) ; ARXOK ( p->setCenter (location) ) ; AcDbObjectId id0 ; ARXOK ( postToDatabase (p, id0) ) ; pRec =new AcDbXrecord ; if ( pRec == NULL ) throw Acad::eOutOfMemory ; struct resbuf rb ; rb.restype =330 ; //----- SoftPointerId to the OarxEmployee entity rb.rbnext =NULL ; ARXOK ( acdbGetAdsName (rb.resval.rlname, id0) ) ; ARXOK ( pRec->setFromRbChain (rb) ) ; pRec->setXlateReferences (Adesk::kTrue) ; AcDbObjectId idDict =getAppDictionary () ; if ( idDict == AcDbObjectId::kNull ) throw Acad::eNullObjectId ; ARXOK ( acdbOpenAcDbObject ((AcDbObject *&)pAppDict, idDict, AcDb::kForWrite) ) ; char buffer [33] ; sprintf (buffer, "%d", id) ; ARXOK ( pAppDict->setAt (buffer, pRec, id0) ) ; pRec->close () ; pAppDict->close () ; return (p) ; } catch (const Acad::ErrorStatus es) { if ( p != NULL && p->objectId () == AcDbObjectId::kNull ) delete p ; else p->cancel () ; if ( pRec != NULL && pRec->objectId () == AcDbObjectId::kNull ) delete pRec ; else pRec->cancel () ; if ( pAppDict != NULL ) pAppDict->cancel () ; return (NULL) ; } }
Acad::ErrorStatus ArxDbgDbEntity::deepClone(AcDbObject* pOwner, AcDbObject*& pClonedObject, AcDbIdMapping& idMap, Adesk::Boolean isPrimary) const { // You should always pass back pClonedObject == NULL // if, for any reason, you do not actually clone it // during this call. The caller should pass it in // as NULL, but to be safe, we set it here as well. pClonedObject = NULL; if (ArxDbgOptions::m_instance.m_showDeepCloneDetails) { CString titleStr, tmpStr; titleStr.Format(_T("Beginning -- deepClone: %s"), ArxDbgUtils::objToClassAndHandleStr(const_cast<ArxDbgDbEntity*>(this), tmpStr)); ArxDbgUiTdmIdMap dbox(&idMap, acedGetAcadDwgView(), titleStr); dbox.DoModal(); } AcDb::DeepCloneType type = idMap.deepCloneContext(); // if we know everything will be cloned for us, just let // the base class do everything for us. if ((type == AcDb::kDcInsert) || (type == AcDb::kDcInsertCopy) || (type == AcDb::kDcExplode)) return AcDbEntity::deepClone(pOwner, pClonedObject, idMap, isPrimary); // following case happens when doing a AcDbDatabase::deepCloneObjects() // and the owner happens to be the same... then its really like a // kDcCopy, otherwise deepCloneObjects() is like a kDcBlock if (type == AcDb::kDcObjects) { if (ownerId() == pOwner->objectId()) type = AcDb::kDcCopy; else type = AcDb::kDcBlock; } // now ask derived classes what references they want cloned for them AcDbObjectIdArray refEntIds; AcDbIntArray refTypes; getCloneReferences(type, refEntIds, refTypes); ASSERT(refEntIds.length() == refTypes.length()); // if derived class doesn't have any references to take care of, then // we will just let the AcDbEntity::deepClone() take care of things. if (refEntIds.isEmpty()) return AcDbEntity::deepClone(pOwner, pClonedObject, idMap, isPrimary); // If this object is in the idMap and is already // cloned, then return. bool tmpIsPrimary = isPrimary ? true : false; // get around compiler performance warning AcDbIdPair idPair(objectId(), AcDbObjectId::kNull, false, tmpIsPrimary); if (idMap.compute(idPair) && (idPair.value() != NULL)) return Acad::eOk; // STEP 1: // Create the clone // AcDbObject *pClone = (AcDbObject*)isA()->create(); if (pClone != NULL) pClonedObject = pClone; // set the return value else return Acad::eOutOfMemory; // STEP 2: // Append the clone to its new owner. In this example, // we know that we are derived from AcDbEntity, so we // can expect our owner to be an AcDbBlockTableRecord, // unless we have set up an ownership relationship with // another of our objects. In that case, we need to // establish how we connect to that owner in our own // way. This sample shows a generic method using // setOwnerId(). // AcDbBlockTableRecord *pBTR = AcDbBlockTableRecord::cast(pOwner); if (pBTR != NULL) { AcDbEntity* ent = AcDbEntity::cast(pClone); pBTR->appendAcDbEntity(ent); } else { if (isPrimary) return Acad::eInvalidOwnerObject; // Some form of this code is only necessary if // anyone has set up an ownership for our object // other than with an AcDbBlockTableRecord. // pOwner->database()->addAcDbObject(pClone); pClone->setOwnerId(pOwner->objectId()); } // STEP 3: // Now we copy our contents to the clone. This is done // using an AcDbDeepCloneFiler. This filer keeps a // list of all AcDbHardOwnershipIds and // AcDbSoftOwnershipIds we, and any classes we derive // from, have. This list is then used to know what // additional, "owned" objects need to be cloned below. // AcDbDeepCloneFiler filer; dwgOut(&filer); // STEP 4: // Rewind the filer and read the data into the clone. // filer.seek(0L, AcDb::kSeekFromStart); pClone->dwgIn(&filer); // STEP 5: // This must be called for all newly created objects // in deepClone. It is turned off by endDeepClone() // after it has translated the references to their // new values. // pClone->setAcDbObjectIdsInFlux(); // STEP 6: // Add the new information to the idMap. We can use // the idPair started above. // idPair.setValue(pClonedObject->objectId()); idPair.setIsCloned(Adesk::kTrue); idMap.assign(idPair); // STEP 7: // Using the filer list created above, find and clone // any owned objects. // AcDbObject *pSubObject; AcDbObject *pClonedSubObject; AcDbObjectId id; Acad::ErrorStatus es; while (filer.getNextOwnedObject(id)) { // Open the object and clone it. Note that we now // set "isPrimary" to kFalse here because the object // is being cloned, not as part of the primary set, // but because it is owned by something in the // primary set. es = acdbOpenAcDbObject(pSubObject, id, AcDb::kForRead); if (es != Acad::eOk) continue; // could have been NULL or erased pClonedSubObject = NULL; pSubObject->deepClone(pClonedObject, pClonedSubObject, idMap, Adesk::kFalse); // If this is a kDcInsert context, the objects // may be "cheapCloned". In this case, they are // "moved" instead of cloned. The result is that // pSubObject and pClonedSubObject will point to // the same object. So, we only want to close // pSubObject if it really is a different object // than its clone. if (pSubObject != pClonedSubObject) pSubObject->close(); // The pSubObject may either already have been // cloned, or for some reason has chosen not to be // cloned. In that case, the returned pointer will // be NULL. Otherwise, since we have no immediate // use for it now, we can close the clone. if (pClonedSubObject != NULL) pClonedSubObject->close(); } // clone the referenced entities AcDbObject* ent; int len = refEntIds.length(); for (int i=0; i<len; i++) { if (refTypes[i] == kClone) { es = acdbOpenAcDbObject(ent, refEntIds[i], AcDb::kForRead); if (es == Acad::eOk) { pClonedSubObject = NULL; es = ent->deepClone(pOwner, pClonedSubObject, idMap, Adesk::kTrue); if (es == Acad::eOk) { // see comment above about cheap clone if (ent != pClonedSubObject) ent->close(); if (pClonedSubObject != NULL) pClonedSubObject->close(); } } } // this case is needed for RefEdit so we can pass its validation // test when editing a blockReference. We don't actually clone it // but we add it to the map so it thinks it got cloned and is therefore // a valid "Closed Set" of objects. else if (refTypes[i] == kFakeClone) { AcDbIdPair idPair(refEntIds[i], refEntIds[i], false, false, true); idMap.assign(idPair); } } if (ArxDbgOptions::m_instance.m_showDeepCloneDetails) { CString titleStr, tmpStr; titleStr.Format(_T("End -- deepClone: %s"), ArxDbgUtils::objToClassAndHandleStr(const_cast<ArxDbgDbEntity*>(this), tmpStr)); ArxDbgUiTdmIdMap dbox(&idMap, acedGetAcadDwgView(), titleStr); dbox.DoModal(); } // Leave pClonedObject open for the caller return Acad::eOk; }