[ObjectARX]-在图形数据库之间传递数据 Wblock

(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(_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(_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指定的图形文件不存在."));
		}

	}

思路总结: 

 [ObjectARX]-在图形数据库之间传递数据 Wblock_第1张图片

完整的项目源代码:

     https://pan.baidu.com/s/1nIM7NcpE__IZ8n1GTga6AA

<未完待续>

你可能感兴趣的:(ObjectARX二次开发)