上一次说wblockcloneobjcts方法不能写视口,又研究了一下,把“曲线救国”方法发挥到极致,终于有点
收获了。试了N种方法,最后采用的是:先建立一个模板,把图纸空间初始化,然后wblockcloneobjects到模型
空间(wblock命令也是把对象放到模型空间的,如果wblockcloneobjcts直接放图纸空间,打开视口时cad会崩溃)。
然后再将视口deepclone到图纸空间就OK了
AcDbDatabase *pDbMid=new AcDbDatabase; //建模板dwg文件,先切换到图纸空间,把全局视口建起来 //每个图纸空间都有一个全局视口,视口下还挂了反应器 //直接wblockcloneobjects一个new的database的话,会因为没有这个视口而搞得acad崩溃 //如果想用new的database,要先把这个全局视口建立起来,现在还不知道怎么建难过 pDbMid->readDwgFile(_T("c:\\template.dwg")); //读取模板 ads_name name; ads_point pnt; AcDbEntity * pEnt; int i; Acad::ErrorStatus es; acedEntSel(_T("选择一个视口\n"),name,pnt); AcDbObjectId objId,dicObj; acdbGetObjectId(objId,name); AcDbObjectIdArray arrID; arrID.append(objId); acedEntSel(_T("选择一个视口\n"),name,pnt); acdbGetObjectId(objId,name); arrID.append(objId); //将扩展字典改为硬拥有,否则写块出去后会丢失 AcDbObjectId tempObjId; for (i=0;i<arrID.length();i++) { if(Acad::eOk==(es=acdbOpenObject(pEnt,arrID[i],AcDb::kForWrite))){ AcDbObjectId obj; if ((obj = pEnt->extensionDictionary()) != AcDbObjectId::kNull) { AcDbDictionary *pDict = NULL; acdbOpenObject(pDict, obj, AcDb::kForWrite); if (pDict) { pDict->setTreatElementsAsHard(Adesk::kTrue); pDict->close(); } } pEnt->close(); } } AcDbBlockTable *pBT; AcDbObjectId MspaceID,PspaceID,blkObjId; pDbMid->getSymbolTable(pBT,AcDb::kForWrite); pBT->getAt(ACDB_MODEL_SPACE,MspaceID); pBT->close(); AcDbIdMapping idMap; idMap.setDestDb(pDbMid); es=pDbMid->wblockCloneObjects(arrID,MspaceID,idMap,AcDb::kDrcIgnore); AcDbIdPair IdPair; AcDbObjectId cloneObjId; AcDbIdMapping idMap2; AcDbObjectIdArray arrID2; for (i=0;i<arrID.length();i++) //获取克隆后的对象的objectid { IdPair.setKey(arrID[i]); if (idMap.compute(IdPair)) { arrID2.append(IdPair.value()); } } AcDbSymbolUtilities::getBlockId(PspaceID,ACDB_PAPER_SPACE,pDbMid); es=pDbMid->deepCloneObjects( arrID2,PspaceID, idMap2 ); //deepclone视口对象到图纸空间 for (i=0;i<arrID2.length();i++) //删除原有模型空间的视口对象 { IdPair.setKey(arrID2[i]); if (idMap2.compute(IdPair)) //将图纸空间的视口打开 { AcDbObjectPointer<AcDbViewport> EntPtr1(IdPair.value(),AcDb::kForWrite); EntPtr1->setOn(); EntPtr1->close(); } AcDbObjectPointer<AcDbViewport> EntPtr2(arrID2[i],AcDb::kForWrite); EntPtr2->erase(); EntPtr2->close(); } pBT->close(); pDbMid->saveAs(_T("c:\\dddddd.dwg")); delete pDbMid;
将当前dwg内的对象复制到另一个dwg文件中
//将当前dwg内的对象复制到另一个dwg文件中 AcDbDatabase * pDB=acdbHostApplicationServices()->workingDatabase(); AcDbBlockTable *pBT1; pDB->getBlockTable(pBT1,AcDb::kForRead); AcDbBlockTableRecord *pBTR1; pBT1->getAt(ACDB_MODEL_SPACE,pBTR1,AcDb::kForRead); AcDbBlockTableRecordIterator * pBTRIt; AcDbObjectIdArray objArr; AcDbIdMapping idMap; pBTR1->newIterator(pBTRIt); pBTRIt->start(); for (;!pBTRIt->done();pBTRIt->step()) { AcDbObjectId objID; pBTRIt->getEntityId(objID); objArr.append(objID); //下面的代码要执行,到时整合 // for ( ; !pIT->done(); pIT->step()) { // if (Acad::eOk == pIT->getEntityId( id )) { // list.append( id ); // // // There is a bug in ARX that causes extension dictionaries // // to appear to be soft owners of their contents. This causes // // the contents to be skipped during wblock. To fix this we // // must explicitly tell the extension dictionary to be a hard // // owner of it's entries. // // // AcDbEntity *pEnt; // if ( Acad::eOk == pIT->getEntity(pEnt, AcDb::kForRead)) { // AcDbObjectId obj; // if ((obj = pEnt->extensionDictionary()) // != AcDbObjectId::kNull) // { // AcDbDictionary *pDict = NULL; // acdbOpenObject(pDict, obj, AcDb::kForWrite); // if (pDict) { // pDict->setTreatElementsAsHard(Adesk::kTrue); // pDict->close(); // } // } // pEnt->close(); // } // } // } } delete pBTRIt; pBTR1->close(); pBT1->close(); AcDbDatabase* pTempDb=new AcDbDatabase(); idMap.setDestDb(pTempDb); pTempDb->getSymbolTable(pBT1,AcDb::kForRead); Acad::ErrorStatus e; AcDbBlockTableRecord * pBTR2; AcDbObjectId pSpaceObjID; pBT1->getAt(ACDB_MODEL_SPACE,pSpaceObjID); pBT1->close(); // pSpaceObjID=getBlockId(ACDB_PAPER_SPACE); e=pTempDb->wblockCloneObjects(objArr,pSpaceObjID,idMap,AcDb::kDrcIgnore); pTempDb->saveAs(_T("c:\\aaa.dwg")); delete pTempDb;
————————————————
ObjectARX学习笔记(二十五)---如何在两个dwg里面拷贝字体样式表AcGiTextStyle ,AcDbTextStyleTableRecord
//两个dwg拷贝字体信息 bool CopyTextStyleIdInfo(AcDbDatabase *pFromDataSrc/*in*/,AcDbDatabase *pToDataDes/*in*/) { if (pFromDataSrc == NULL || pToDataDes == NULL) return false; AcDbTextStyleTable *pStyleTable = NULL; Acad::ErrorStatus es = Acad::eOk; es = pFromDataSrc->getSymbolTable(pStyleTable,AcDb::kForRead); if (es != Acad::eOk) return false; AcDbTextStyleTableIterator *pIterator = NULL; es = pStyleTable->newIterator(pIterator); if (es != Acad::eOk) { pStyleTable->close(); pStyleTable = NULL; return false; } for (pIterator->start();!pIterator->done();pIterator->step()) { AcDbObjectId styleId = AcDbObjectId::kNull; if ((es = pIterator->getRecordId(styleId)) == Acad::eOk) { AcGiTextStyle *pTextStyle=new AcGiTextStyle(pToDataDes); if((es =fromAcDbTextStyle(*pTextStyle,styleId)) == Acad::eOk ) { AcDbTextStyleTableRecord* pNewRec = new AcDbTextStyleTableRecord; setSymbolName(pNewRec,pTextStyle->styleName()); pNewRec->setFileName(pTextStyle->fileName()); /*待完善*/ ACHAR * pTypeface = NULL; Adesk::Boolean bold; Adesk::Boolean italic; int charset; int pitchAndFamily; es = pTextStyle->font(pTypeface,bold,italic,charset,pitchAndFamily); if (es == Acad::eOk) pNewRec->setFont(pTypeface,bold,italic,charset,pitchAndFamily); pNewRec->setBigFontFileName(_T(""));// must explicitly set to "" pNewRec->setTextSize(pTextStyle->textSize()); pNewRec->setObliquingAngle(pTextStyle->obliquingAngle()); pNewRec->setXScale(pTextStyle->xScale()); addToSymbolTableAndClose(pNewRec,pToDataDes); } if (pTextStyle != NULL) { delete pTextStyle; pTextStyle = NULL; } } } if (pIterator != NULL) { delete pIterator; pIterator = NULL; pStyleTable->close(); pStyleTable = NULL; } return true; } if (pDataBase == NULL || systemTextRec == NULL) return FALSE; AcDbTextStyleTable* symTextTbl = NULL; Acad::ErrorStatus es = Acad::eOk; es = pDataBase->getTextStyleTable(symTextTbl, AcDb::kForWrite); if (es != Acad::eOk) { if (systemTextRec != NULL) { delete systemTextRec; systemTextRec = NULL; } return FALSE; } AcDbSymbolTable *pSysRec = AcDbTextStyleTable::cast(symTextTbl); //覆盖字体样式 es = pSysRec->add(systemTextRec); if (es != Acad::eOk ) { symTextTbl->close(); systemTextRec->close(); return FALSE; } else { systemTextRec->close(); symTextTbl->close(); } return TRUE; } BOOL setSymbolName(AcDbSymbolTableRecord* newRec, LPCTSTR newName) { Acad::ErrorStatus es; es = newRec->setName(newName); if (es != Acad::eOk) { newRec->close(); } return(es); } //返回实体所在图层颜色 Adesk::UInt16 getColorIndexByLayer(Adesk::UInt16 icolorIndex,CString lyname,AcDbDatabase *pDb) { if (pDb == NULL) return 7; Adesk::UInt16 iclorIndexResult = 0; Acad::ErrorStatus bEs = Acad::eOk; if (icolorIndex == 256) //随层 { AcDbLayerTable *pDbLy; bEs = pDb->getLayerTable(pDbLy,AcDb::kForRead); if (bEs == Acad::eOk) { Adesk::Boolean es=pDbLy->has(lyname); if (es) { AcDbLayerTableRecord *pLayerTblRcd; bEs = pDbLy->getAt(lyname,(AcDbLayerTableRecord*&)pLayerTblRcd, AcDb::kForRead); if (bEs == Acad::eOk) { AcCmColor color = pLayerTblRcd->color(); iclorIndexResult = color.colorIndex(); pLayerTblRcd->close(); } } pDbLy->close(); } } else if(icolorIndex == 0) //随块 { ;//待完善 } else { iclorIndexResult = icolorIndex; } return iclorIndexResult; } //添加文字样式块表记录 BOOL addToSymbolTableAndClose(AcDbSymbolTableRecord* systemTextRec/*in*/,AcDbDatabase *pDataBase/*in*/) { if (pDataBase == NULL || systemTextRec == NULL) return FALSE; AcDbTextStyleTable* symTextTbl = NULL; Acad::ErrorStatus es = Acad::eOk; es = pDataBase->getTextStyleTable(symTextTbl, AcDb::kForWrite); if (es != Acad::eOk) { if (systemTextRec != NULL) { delete systemTextRec; systemTextRec = NULL; } return FALSE; } AcDbSymbolTable *pSysRec = AcDbTextStyleTable::cast(symTextTbl); //覆盖字体样式 es = pSysRec->add(systemTextRec); if (es != Acad::eOk ) { symTextTbl->close(); systemTextRec->close(); return FALSE; } else { systemTextRec->close(); symTextTbl->close(); } return TRUE; } BOOL setSymbolName(AcDbSymbolTableRecord* newRec, LPCTSTR newName) { Acad::ErrorStatus es; es = newRec->setName(newName); if (es != Acad::eOk) { newRec->close(); } return(es); } //返回实体所在图层颜色 Adesk::UInt16 getColorIndexByLayer(Adesk::UInt16 icolorIndex,CString lyname,AcDbDatabase *pDb) { if (pDb == NULL) return 7; Adesk::UInt16 iclorIndexResult = 0; Acad::ErrorStatus bEs = Acad::eOk; if (icolorIndex == 256) //随层 { AcDbLayerTable *pDbLy; bEs = pDb->getLayerTable(pDbLy,AcDb::kForRead); if (bEs == Acad::eOk) { Adesk::Boolean es=pDbLy->has(lyname); if (es) { AcDbLayerTableRecord *pLayerTblRcd; bEs = pDbLy->getAt(lyname,(AcDbLayerTableRecord*&)pLayerTblRcd, AcDb::kForRead); if (bEs == Acad::eOk) { AcCmColor color = pLayerTblRcd->color(); iclorIndexResult = color.colorIndex(); pLayerTblRcd->close(); } } pDbLy->close(); } } else if(icolorIndex == 0) //随块 { ;//待完善 } else { iclorIndexResult = icolorIndex; } return iclorIndexResult; }
[ObjectARX]-在图形数据库之间传递数据 Wblock
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/qq_40416052/article/details/82933824
(1)使用ObjectARX向导创建一个新工程,名称为Wblock.
添加普通类CBlockUtil,并在类中添加函数CopyBlockDefOtherDwg,用于将其他Dwg文件 中的块定义赋值到当前图形数据库。
实现代码:
AcDbObjectId CBlockUtil::CopyBlockDefFromOtherDwg(const TCHAR* fileName,
const TCHAR* blkDefName)
{
AcDbObjectId blockRefId = AcDbObjectId::kNull;
//AcDbObjectId :: kNull表示当前DWG中不存在对象(图层)
//使用_SH_DENYNO参数打开图形(只读打开),允许其他用户读写文件
AcDbDatabase* pSourceDwg = new AcDbDatabase(false);
Acad::ErrorStatus es = pSourceDwg->readDwgFile(fileName,
static_cast<AcDbDatabase::OpenMode>(_SH_DENYNO));
if (es != Acad::eOk)
{
delete pSourceDwg;
pSourceDwg = NULL;
acutPrintf(TEXT("\n读入dwg图形错误,图形名称:%s"), fileName);
return blockRefId;
}
//打开外部图形数据库的块表,寻找给定名称的块表记录
AcDbBlockTable* pBlkTable = NULL;
es = pSourceDwg->getBlockTable(pBlkTable, AcDb::kForRead);
//以只读模式打开数据库的块表,pBlkTable获得块表地址
assert(es == Acad::eOk);
bool bRet = false;
if (pBlkTable->has(blkDefName)) //不存在指定的图块
{
AcDbObjectId destBlkDefId; //指定图块的块表记录Id
es = pBlkTable->getAt(blkDefName, destBlkDefId);
//把指定的图块输出到一个临时的图形数据库
AcDbDatabase *pTempDb = NULL; //注意:这里千万不能new
es = pSourceDwg->wblock(pTempDb, destBlkDefId);//创建一个新的数据库对象,pTempDb指向它
assert(es == Acad::eOk);
//把临时图形数据库作为插入块插入到当前dwg
AcDbDatabase* pCurDb = acdbHostApplicationServices()->workingDatabase();
es = pCurDb->insert(blockRefId, blkDefName, pTempDb);//由pDb指向的数据库中的所有
//模型空间实体都被复制到新的块表记录中,新的块表记录名称为blkDefName,Id为blockRefId
assert(es == Acad::eOk);
delete pTempDb;
pTempDb = NULL;
}
else
{
acutPrintf(TEXT("\n给定的DWG文件中,不存在指定名称的块表记录."));
}
pBlkTable->close();
delete pSourceDwg;
pSourceDwg = NULL;
return blockRefId;
}
(2)在CBlockUtil类中添加函数InsertDwgBlockDef,用于将指定的整个DWG文件作为图块加入到当前图形文件中作为块定义。
实现代码:
InsertDwgBlockDef函数的声明:
// 将DWG文件作为块定义加入到指定的图形数据库
// bOverwriteIfExist: 如果指定的图形数据库中已经定义了同名的块,是否覆盖原有的定义
static AcDbObjectId InsertDwgBlockDef(const TCHAR* dwgFileName,
const TCHAR* blkName, bool bOverwriteIfExist,
AcDbDatabase *pDb = acdbHostApplicationServices()->workingDatabase());
InsertDwgBlockDef函数的实现:
AcDbObjectId CBlockUtil::InsertDwgBlockDef(const TCHAR* dwgFileName,
const TCHAR* blkName, bool bOverwriteIfExist, AcDbDatabase *pDb)
{
//是否包含指定名称的块定义
AcDbObjectId blkDefId = GetBlkDefId(blkName, pDb);
if (blkDefId.isNull() || bOverwriteIfExist)
{
if (_taccess(dwgFileName, 0) != -1)//如果指定的文件不存在,返回-1
{
AcDbDatabase *pBlkDb = new AcDbDatabase(false);
Acad::ErrorStatus es = pBlkDb->readDwgFile(dwgFileName,
static_cast<AcDbDatabase::OpenMode>(_SH_DENYNO));
if (es == Acad::eOk)
{
es = pDb->insert(blkDefId, blkName, pBlkDb);//在执行此insert函数的数据库中
//创建新的块表记录;由pBlkDb指向的数据库中的所有模型空间实体都
//被复制到新的块表记录中,名称为blkName,Id为blkDefId
if (es != Acad::eOk)
{
CString strMsg;
strMsg.Format(TEXT("CBlockUtil::InsertDwgBlockDef函数,insert失败:%d."),
(int)es);
AfxMessageBox(strMsg);
}
}
else
{
CString strMsg;
strMsg.Format(TEXT("CBlockUtil::InsertDwgBlockDef函数,readDwg File失败:%d."),
(int)es);
AfxMessageBox(strMsg);
}
delete pBlkDb;
}
else
{
AfxMessageBox(TEXT("CBlockUtil::InsertDwgBlockDef函数,未找到指定的图块文件."));
}
}
return blkDefId;
}
其中,
GetBlkDefId函数的声明:
// 获得指定名称的块定义
static AcDbObjectId GetBlkDefId(const TCHAR* blkDefName,
AcDbDatabase *pDb = acdbHostApplicationServices()->workingDatabase());
GetBlkDefId函数的实现:
// 获得指定名称的块定义
AcDbObjectId CBlockUtil::GetBlkDefId(const TCHAR* blkDefName, AcDbDatabase *pDb)
{
AcDbBlockTable* pBlockTable = NULL;
Acad::ErrorStatus es = pDb->getBlockTable(pBlockTable, AcDb::kForRead);
AcDbObjectId blkDefId;
es = pBlockTable->getAt(blkDefName, blkDefId);
pBlockTable->close();
if (es == Acad::eOk)
{
return blkDefId;
}
else
{
return AcDbObjectId::kNull;
}
}
(3)注册函命令InsertBlkRefFromOtherDwg,将外部图形文件中的块定义复制到当前图形文件,然后在图形窗口中插入这个块定义的块参照。
注册函数InsertBlkRefFromOtherDwg的实现代码:
static void AAAMyGroupInsertBlkRefFromOtherDwg() {
CString fileName = TEXT("C:\\'包含图块.dwg");
if (_taccess(fileName, 0) != -1)
{
AcDbObjectId blkDefId = CBlockUtil::CopyBlockDefFromOtherDwg(fileName,
TEXT("测试图块"));
if (blkDefId.isValid())
{
CBlockUtil::InsertBlockRef(blkDefId, AcGePoint3d(100, 100, 0), 1, 0);
}
}
else
{
acutPrintf(TEXT("\n指定的图形文件不存在"));
}
}
其中,
①
InsertBlockRef函数的声明:
// 插入块参照
static AcDbObjectId InsertBlockRef(AcDbObjectId blkDefId, const AcGePoint3d &insertPoint,
double scale = 1, double rotation = 0);
InsertBlockRef函数的实现:
// 插入块参照
AcDbObjectId CBlockUtil::InsertBlockRef(AcDbObjectId blkDefId, const AcGePoint3d &insertPoint, double scale,
double rotation)
{
// 设置图块的插入点、旋转角度、比例等等
AcDbBlockReference *pBlkRef = new AcDbBlockReference(insertPoint, blkDefId);
pBlkRef->setRotation(rotation);
SetScaleFactor(pBlkRef, scale);
// 把新建的图块参照实体加入到新建的块表记录中,并取得插入图块的实体Id,用于返回值
return CDwgDatabaseUtil::PostToModelSpace(pBlkRef);
}
②
SetScaleFactor函数的声明:
// 设置块参照的缩放比例
static void SetScaleFactor(AcDbBlockReference *pBlkRef, double scale);
SetScaleFactor函数的实现:
// 修改块参照的插入比例
void CBlockUtil::SetScaleFactor( AcDbBlockReference *pBlkRef, double scale )
{
assert (pBlkRef);
AcGeScale3d geScale(scale, scale, scale);
pBlkRef->setScaleFactors(geScale);
}
③
PostToModelSpace函数的声明:
// 将实体添加到模型空间
static AcDbObjectId PostToModelSpace(AcDbEntity *pEnt,
AcDbDatabase *pDb = acdbHostApplicationServices()->workingDatabase());
PostToModelSpace函数的声明:
AcDbObjectId CDwgDatabaseUtil::PostToModelSpace(AcDbEntity *pEnt, AcDbDatabase *pDb)
{
// 检查输入参数的有效性
assert(pEnt); // 等效于assert (pEnt != NULL);
// 获得当前图形数据库的块表
AcDbBlockTable *pBlkTbl = NULL;
pDb->getBlockTable(pBlkTbl, AcDb::kForRead);
// 获得模型空间对应的块表记录
AcDbBlockTableRecord *pBlkTblRcd = NULL;
pBlkTbl->getAt(ACDB_MODEL_SPACE, pBlkTblRcd, AcDb::kForWrite);
pBlkTbl->close();
// 将实体添加到模型空间的块表记录
AcDbObjectId entId;
Acad::ErrorStatus es = pBlkTblRcd->appendAcDbEntity(entId, pEnt);
if (es != Acad::eOk)
{
pBlkTblRcd->close();
delete pEnt; // 添加失败时,要delete
pEnt = NULL;
return AcDbObjectId::kNull;
}
// 关闭模型空间块表记录和实体
pBlkTblRcd->close();
pEnt->close();
return entId;
}
(4)注册命令InsertDwgBlockRef,将某个DWG文件作为图块插入到当前的模型空间。
实现代码为:
注册函数InsertDwgBlockRef 的实现:
static void AAAMyGroupInsertDwgBlockRef() {
CString fileName = TEXT("C:\\作为图块的文件.dwg");
if (_taccess(fileName, 0) != -1)
{
AcDbObjectId blkDefId = CBlockUtil::InsertDwgBlockDef(fileName,
TEXT("外部DWG图块"), true);
if (blkDefId.isValid())
{
CBlockUtil::InsertBlockRef(blkDefId, AcGePoint3d(200, 100, 0), 1, 0);
}
}
else
{
acutPrintf(TEXT("\n指定的图形文件不存在."));
}
}
思路总结:
————————————————
版权声明:本文为CSDN博主「李燕良」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_40416052/article/details/82933824
文章评论