【CAD二次开发】-ObjectARX-扩展数据 (Xdata)

基本思路:

(1)创建一个新项目,命名为Xdata.注册一个命令AddXData.

实现代码为:

static void AAAMyGroupAddXData() {
		// 提示用户选择所要添加扩展数据的图形对象
		AcDbEntity *pEnt = NULL;
		AcGePoint3d pickPoint;
		if (CSelectUtil::PromptSelectEntity(TEXT("\\n选择所要添加的扩展数据的实体:"),
			AcDbEntity::desc(),pEnt,pickPoint))
		{
			CString appName = TEXT("XDataApp");

			//注册应用程序名称
			acdbRegApp(appName);

			//创建结果缓冲区链表
			struct resbuf* rb = acutBuildList(AcDb::kDxfRegAppName, appName,
				//应用程序名称
				AcDb::kDxfXdAsciiString, TEXT("字符串测试数据"),//字符创
				AcDb::kDxfXdInteger32, 2,//整数
				AcDb::kDxfXdReal, 3.14,//实数
				AcDb::kDxfXdWorldXCoord, asDblArray(pickPoint),//点坐标值
				RTNONE);

			//为选择的实体添加扩展数据
			pEnt->setXData(rb);
			acutRelRb(rb);

			acutPrintf(TEXT("\\n成功为实体添加了扩展数据."));
			pEnt->close();
		}

	}
	// Modal Command with pickfirst selection
	// ACED_ARXCOMMAND_ENTRY_AUTO(CXdataApp, AAAMyGroup, MyPickFirst, MyPickFirstLocal, ACRX_CMD_MODAL | ACRX_CMD_USEPICKSET)
	static void AAAMyGroupMyPickFirst () {
		ads_name result ;
		int iRet =acedSSGet (ACRX_T("_I"), NULL, NULL, NULL, result) ;
		if ( iRet == RTNORM )
		{
			// There are selected entities
			// Put your command using pickfirst set code here
		}
		else
		{
			// There are no selected entities
			// Put your command code here
		}
	}

 创建一个类CSelectUtil,实现函数PromptSelectEntity:

函数声明:

	// 提示用户选择某个类型的实体
	// 注意:调用者必须关闭实体	
	static bool PromptSelectEntity(const TCHAR* prompt, AcRxClass* classDesc, AcDbEntity *&pEnt, AcGePoint3d &pickPoint,
		bool bOpenForWrite = true);
	static bool PromptSelectEntity(const TCHAR* prompt, const std::vector<AcRxClass*> &classDescs, AcDbEntity *&pEnt,
		AcGePoint3d &pickPoint, bool bOpenForWrite = true);

函数实现: 

bool CSelectUtil::PromptSelectEntity(const TCHAR* prompt, AcRxClass* classDesc, AcDbEntity *&pEnt,
	AcGePoint3d &pickPoint, bool bOpenForWrite /*= true*/)
{
	std::vector<AcRxClass*> descs;
	descs.push_back(classDesc);

	return PromptSelectEntity(prompt, descs, pEnt, pickPoint, bOpenForWrite);
}

bool CSelectUtil::PromptSelectEntity(const TCHAR* prompt, const std::vector<AcRxClass*> &classDescs, AcDbEntity *&pEnt,
	AcGePoint3d &pickPoint, bool bOpenForWrite/*= true*/ )
{
	ads_name ename;
RETRY:
	if (acedEntSel(prompt, ename, asDblArray(pickPoint)) != RTNORM)
	{
		pEnt = NULL;
		return false;
	}

	AcDbObjectId entId;
	acdbGetObjectId(entId, ename);

	// 判断选择的实体是否是指定类型的实体
	Acad::ErrorStatus es;
	if (bOpenForWrite)
	{
		es = acdbOpenObject(pEnt, entId, AcDb::kForWrite);
	}
	else
	{
		es = acdbOpenObject(pEnt, entId, AcDb::kForRead);
	}
	assert(es == Acad::eOk);
	bool bRet = false;
	for (int i = 0; i < (int)classDescs.size(); i++)
	{
		if (pEnt->isKindOf(classDescs[i]))
		{
			bRet = true;
			break;
		}
	}

	if (bRet)
	{
		return true;
	}
	else
	{
		pEnt->close();
		acutPrintf(TEXT("\\n选择的实体类型不合要求, 请再次选择..."));
		goto RETRY;
	}
}


(2)注册一个ViewXData命令,用于查看指定的实体的扩展数据。

实现函数为:

static void AAAMyGroupViewXData() {
		//提示用户选择所要查看扩展数据的图形对象
		AcDbEntity *pEnt = NULL;
		AcGePoint3d pickPoint;
		if (CSelectUtil::PromptSelectEntity(TEXT("\\n选择所要添加扩展数据的实体:"), AcDbEntity::desc(), pEnt, pickPoint))
		{
			CString appName = TEXT("XDataApp");

			//获取实体的扩展数据
			struct resbuf *pRb = pEnt->xData(appName);
			if (pRb != NULL)
			{
				//在命令行显示所有的扩展数据
				struct resbuf *pTemp = pRb; //使用临时的结果缓冲区指针进行
				                            //遍历,pRb不修改便于释放
				//首先要跳过数据名称这一项
				pTemp = pTemp->rbnext;
				acutPrintf(TEXT("\\n字符串类型的扩展数据是:%s"), pTemp->resval.rstring);

				pTemp = pTemp->rbnext;
				acutPrintf(_T("\\n整数类型的扩展数据是:%d"), pTemp->resval.rint);

				pTemp = pTemp->rbnext;
				acutPrintf(TEXT("\\n实数类型的扩展数据是:%.2f"), pTemp->resval.rreal);

				pTemp = pTemp->rbnext;
				acutPrintf(TEXT("\\n点坐标的数据类型的扩展数据是:(%.2f,%.2f,%.2f)"),
					pTemp->resval.rpoint[X], pTemp->resval.rpoint[Y],
					pTemp->resval.rpoint[Z]);

				acutRelRb(pRb);
			}
			else
			{
				acutPrintf(TEXT("\\n所选择的实体不包含任何的扩展数据!"));
			}
			pEnt->close();
		}

	}

(3)注册新命令DeleteXData,用于从实体中删除特定的扩展数据.

实现代码:

static void AAAMyGroupDeleteXData() {
		//提示用户选择所要删除扩展数据的图形对象
		AcDbEntity *pEnt = NULL;
		AcGePoint3d pickPoint;
		if (CSelectUtil::PromptSelectEntity(TEXT("\\n选择所要删除扩展数据的实体:"),
			AcDbEntity::desc(),pEnt,pickPoint))
		{
			CString appName = TEXT("XDataApp");
			//注册应用程序名称
			acdbRegApp(appName);

			//创建结果缓冲区链表
			struct resbuf *rb = acutBuildList(AcDb::kDxfRegAppName, appName, RTNONE);
			//应用程序名称

			//设置内容为空的结果缓冲区链表就是删除扩展数据
			pEnt->setXData(rb);
			acutRelRb(rb);

			acutPrintf(TEXT("\\n成功为实体删除了扩展数据."));

			pEnt->close();
		}

	}

完整的项目代码:

https://pan.baidu.com/s/1MSW-sefDViI244swYH8XFA

效果:

①先创建两条直线,执行AddXData命令,选择其中一条直线,为其添加扩展数据;

②执行ViewXData命令,查看扩展数据

③执行DeleteXData命令,删除扩展命令。

还没有结束!


 还有另一种查看扩展数据的方法:

①在CAD中加载ArxDbg.arx

如果你没有这个使用程序,我这里提供给您下载:

https://pan.baidu.com/s/1q5fJ94q2RcPNXgvmvbQYDA
包括从AutoCAD 2000到AutoCAD 2019的所有AutoCAD版本

②右键,选择EntityInfo

③根据提示选择实体,然后按回车键

④出现刚刚选择的三个实体,Xdata不可选说明没有扩展数据

 

 ⑤实体 圆有扩展数据

 

⑥点击Xdata,可看到其扩展数据:

 

Reference:

张帆《AutoCAD ObjectARX(VC)开发基础与实例教程》 

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

取消
昵称表情代码图片