用了很久的wblockCloneObjects函数进行跨图纸的图块拷贝,但一直对调用这个函数的AcDbDatabase应该是源图纸的还是目标图纸的不是很明白,在查到的资料中大多都是关于参数的说明:
ACDBCORE2D_PORT Acad::ErrorStatus wblockCloneObjects(
const AcDbObjectIdArray& objectIds,
const AcDbObjectId& owner,
AcDbIdMapping& idMap,
AcDb::DuplicateRecordCloning drc,
bool deferXlation = false);
其中各个参数的意义如下:
- objectIds:类型为AcDbObjectIdArray的输入参数,指定需要拷贝的对象数组;
- owner:类型为AcDbObjectId的输入参数,指定目标数据库中新对象的所属者对象id;
- idMap:类型为AcDbIdMapping的输入/输出参数,用于存储源数据库中拷贝对象id与目标数据库中新对象id之间的映射关系;
- drc:类型为AcDb::DuplicateRecordCloning的输入参数,指定重复记录处理方式,包括kDrcIgnore、kDrcReplace、kDrcMangleName等;
- deferXlation:类型为bool的输入参数,表示是否延迟翻译,即是否在函数执行期间检查块内嵌块和参照等对象。 该函数的返回值为Acad::ErrorStatus类型,表示函数执行的状态码,包括但不限于Acad::eOk、Acad::eNotImplementedYet、Acad::eOutOfRange等。
于是写了一个测试函数对调用函数的AcDbDatabase进行了测试,只是没想到测试结果有点出乎意料,似乎调用的AcDbDatabase只要是一个有效值就可以,可以是源图纸的DB,也可以目标图纸的DB,也可以是第三方的DB:
// 测试wblockCloneObjects函数
void WblockCloneTest()
{
// 获取当前图纸块表中所有的图块
acDocManager->lockDocument(acDocManager->curDocument());
AcDbDatabase* pDb = acdbCurDwg();
AcDbBlockTable* pBlkTab = NULL;
Acad::ErrorStatus es = pDb->getBlockTable(pBlkTab, AcDb::kForRead);
if (Acad::eOk != es)
{
acutPrintf(L"\n【ERR 01】:%s\n", acadErrorStatusText(es));
return;
}
AcDbBlockTableIterator* pIter = NULL;
es = pBlkTab->newIterator(pIter);
pBlkTab->close(); // 在这里就关闭块表并不影响指针便利访问
if (Acad::eOk != es)
{
acutPrintf(L"\n【ERR 02】:%s\n", acadErrorStatusText(es));
return;
}
AcDbObjectIdArray arsIdBlk;
for ( pIter->start(); !pIter->done(); pIter->step() )
{
AcDbBlockTableRecord* pRec = NULL;
es = pIter->getRecord(pRec, AcDb::kForRead);
if ( Acad::eOk != es )
{
acutPrintf(L"\n【ERR 03】:%s\n", acadErrorStatusText(es));
continue;
}
AcString sName;
es = pRec->getName(sName);
if (Acad::eOk == es)
{
acutPrintf(L"\n【块名称】:%s", sName);
// 图纸自带的模型空间和图纸空间需要剔除不拷贝
if (sName != ACDB_MODEL_SPACE && sName.find(ACDB_PAPER_SPACE) == CB_ERR)
{
arsIdBlk.append(pRec->id());
}
}
pRec->close();
}
delete pIter;
// 拷贝图纸(使用目标DB调用拷贝函数)
AcDbDatabase* pDbNew1 = new AcDbDatabase;
AcDbBlockTable* pTab1 = NULL;
es = pDbNew1->getBlockTable(pTab1, AcDb::kForRead);
if (Acad::eOk != es)
{
delete pDbNew1;
acutPrintf(L"\n【ERR 04】:%s\n", acadErrorStatusText(es));
return;
}
AcDbObjectId idTab1 = pTab1->id();
pTab1->close();
AcDbIdMapping idMap1;
es = pDbNew1->wblockCloneObjects(arsIdBlk, idTab1, idMap1, AcDb::kDrcIgnore);
if (Acad::eOk != es)
{
delete pDbNew1;
acutPrintf(L"\n【ERR 05】:%s\n", acadErrorStatusText(es));
return;
}
pDbNew1->saveAs(L"\nE:\\ARX练习\\001\\001.dwg");
delete pDbNew1;
// 拷贝图纸(使用源DB调用拷贝函数)
AcDbDatabase* pDbNew2 = new AcDbDatabase;
AcDbBlockTable* pTab2 = NULL;
es = pDbNew2->getBlockTable(pTab2, AcDb::kForRead);
if (Acad::eOk != es)
{
delete pDbNew2;
acutPrintf(L"\n【ERR 06】:%s\n", acadErrorStatusText(es));
return;
}
AcDbObjectId idTab2 = pTab2->id();
pTab2->close();
AcDbIdMapping idMap2;
es = pDb->wblockCloneObjects(arsIdBlk, idTab2, idMap2, AcDb::kDrcIgnore);
if (Acad::eOk != es)
{
delete pDbNew2;
acutPrintf(L"\n【ERR 07】:%s\n", acadErrorStatusText(es));
return;
}
pDbNew2->saveAs(L"\nE:\\ARX练习\\001\\002.dwg");
// 拷贝图纸(使用完全无关的DB调用拷贝函数)
AcDbDatabase* pDbNew3 = new AcDbDatabase;
AcDbBlockTable* pTab3 = NULL;
es = pDbNew3->getBlockTable(pTab3, AcDb::kForRead);
if (Acad::eOk != es)
{
delete pDbNew2;
delete pDbNew3;
acutPrintf(L"\n【ERR 08】:%s\n", acadErrorStatusText(es));
return;
}
AcDbObjectId idTab3 = pTab3->id();
pTab3->close();
AcDbIdMapping idMap3;
es = pDbNew2->wblockCloneObjects(arsIdBlk, idTab3, idMap3, AcDb::kDrcIgnore);
if (Acad::eOk != es)
{
delete pDbNew2;
delete pDbNew3;
acutPrintf(L"\n【ERR 09】:%s\n", acadErrorStatusText(es));
return;
}
pDbNew3->saveAs(L"\nE:\\ARX练习\\001\\003.dwg");
delete pDbNew2;
delete pDbNew3;
acDocManager->unlockDocument(acDocManager->curDocument());
}
额……(我不能上传图片)(嘻嘻,换了个浏览器我又可以上传图片了)
我在当前图纸中创建了三个图块(“001-1”,“002-1”, “003-1”):
命令: TWB01
【块名称】:*Model_Space
【块名称】:*Paper_Space
【块名称】:*Paper_Space0
【块名称】:001-1
【块名称】:002-1
【块名称】:003-1
命令执行结束,上面是命令行输出的所有的图块名称。另外图纸也全部都生成成功,每一张图纸中都包含了上面最后三个图块(如下图所示)。
所以我在猜想只要参数是正确的,无论使用哪一个DB,都会正确的拷贝到“owner”的图纸上;不知道是否有厉害的人能解释一下这个现象呢。
PS:这个函数处理中只拷贝了图块到新的图纸中,没有考虑图块属性以及样式,也不考虑块引用的拷贝。