<四>objectARX开发:扩展数据XData、扩展记录XRecord和有名对象字典NameDict

本文详细介绍了AutoCAD开发中扩展数据XData、扩展记录XRecord以及有名对象字典NameDict的使用。XData用于向实体添加用户数据,但有限制;XRecord存储能力更强,常用于替代XData;而NameDict作为图形数据库的一部分,用于保存与实体无关的设计参数。文章涵盖如何添加、查看和删除这些数据,并提供了源码地址供进一步研究。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1、实体–扩展数据XData

  扩展数据能被添加到任何实体上,由一个结果缓冲区链表组成,并且随 AutoCAD 图形
一起保存(AutoCAD 不会使用扩展数据)。在许多情况下,扩展数据是向实体追加用户数据
的一个有效途径,但是每个实体上所附加的扩展数据不能超过16K。

1)添加扩展数据

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

			// 注册应用程序名称
			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();
		}
	}

2)查看扩展数据

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

			// 获取实体的扩展数据
			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(TEXT("\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)删除扩展数据

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

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

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

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

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

			pEnt->close();
		}
	}

2、实体–扩展记录

  扩展记录与扩展数据类似,但是其数据存储量和能够存储的数据类型都要多于扩展数
据。扩展记录可以保存在实体的扩展字典中。扩展字典隶属于特定的实体,每个实体只能包含一个扩展字典,它为实体保存自定义数据提供了一种途径,实际上, Autodesk 也建议开发者用扩展字典和扩展记录来代替传统的扩展数据。有名对象字典直接保存在图形数据库中,不与特定的实体有关,因此可用于保存与实体无关的设计参数。字典与符号表类似,其中包含一个惟一的字符串关键字索引和对象 ID 号,通过关键字来访问字典中保存的内容。
1)添加扩展记录

static void ZYMyGroupAddXRecord()
	{
		// 提示用户选择所要添加扩展记录的图形对象
		AcDbEntity *pEnt = NULL;
		AcGePoint3d pickPoint;
		if (CSelectUtil::PromptSelectEntity(TEXT("\n选择所要添加扩展记录的实体:"), AcDbEntity::desc(), pEnt, pickPoint))
		{
			// 向实体中添加扩展字典
			pEnt->createExtensionDictionary();
			AcDbObjectId dictObjId = pEnt->extensionDictionary();
			pEnt->close();

			// 创建扩展记录
			AcDbXrecord *pXrec = new AcDbXrecord;

			// 向扩展字典中添加一条记录
			AcDbObjectId xRecObjId;
			AcDbDictionary *pDict = NULL;
			if (acdbOpenObject(pDict, dictObjId, AcDb::kForWrite) == Acad::eOk)
			{
				pDict->setAt(TEXT("XRecord"), pXrec, xRecObjId);
				pDict->close();
			}

			// 设置扩展记录的内容
			struct resbuf* pRb = acutBuildList(AcDb::kDxfText, TEXT("测试字符串数据"),
				AcDb::kDxfInt32, 12,
				AcDb::kDxfReal, 3.14,
				AcDb::kDxfXCoord, asDblArray(pickPoint),
				RTNONE);
			pXrec->setFromRbChain(*pRb);	// 扩展数据内容填充扩展记录对象
			pXrec->close();
			acutRelRb(pRb);
		}
	}

2)查看扩展记录

static void ZYMyGroupViewXRecord()
	{
		// 提示用户选择所要查看扩展记录的图形对象
		AcDbEntity *pEnt = NULL;
		AcGePoint3d pickPoint;
		if (CSelectUtil::PromptSelectEntity(TEXT("\n选择所要查看扩展记录的实体:"), AcDbEntity::desc(), pEnt, pickPoint))
		{
			// 获得实体的扩展字典
			AcDbObjectId dictObjId = pEnt->extensionDictionary();
			pEnt->close();
			if (dictObjId.isNull())
			{
				acutPrintf(TEXT("\n所选择的实体不包含扩展字典!"));
				return;
			}

			// 打开扩展字典,获得与关键字"XRecord"关联的扩展记录
			AcDbDictionary *pDict = NULL;
			AcDbXrecord *pXrec = NULL;
			struct resbuf *pRb = NULL;
			if (acdbOpenObject(pDict, dictObjId, AcDb::kForRead) == Acad::eOk)
			{
				pDict->getAt(TEXT("XRecord"), (AcDbObject*&)pXrec, AcDb::kForRead);

				// 获得扩展记录的数据链表并关闭扩展数据对象			
				pXrec->rbChain(&pRb);
				pXrec->close();

				pDict->close();
			}

			if (pRb != NULL)
			{
				// 在命令行显示扩展记录内容
				struct resbuf *pTemp = pRb;

				acutPrintf(TEXT("\n字符串类型的扩展数据是:%s"), pTemp->resval.rstring);

				pTemp = pTemp->rbnext;
				acutPrintf(TEXT("\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);
			}
		}
	}

3、图形数据库–有名对象字典

  AutoCAD 每个图形数据库中都包含一个有名对象字典,默认情况下该字典中包含了组、多线样式、布局和打印等信息。例如,用户在 AutoCAD 创建一个组,就会有一个代表改组的元素被添加到组字典中。如果需要在有名对象字典中保存自己的数据,一般可以在有名对象字典中添加一个根字典,然后再向根字典中添加新的字典,进而在新字典中保存数据。这样的好处是不会与有名对象字典的基本字典相混淆。使用 AcDbDatabase 对象的 getNamedObjectsDictionary 函数可以获得图形的有名对象字典(根字典),可以通过 setAt 函数向根字典添加一个字典,或者通过 getAt 函数获得其中的一个字典。获得字典之后,向字典中保存数据的方法与扩展字典完全一致。

1)添加有名对象字典

static void ZYMyGroupAddNameDict()
	{
		// 获得有名对象字典,向其中添加指定的字典项
		AcDbDictionary *pNameObjDict = NULL;//, 
		acdbHostApplicationServices()->workingDatabase()
			->getNamedObjectsDictionary(pNameObjDict, AcDb::kForWrite);
		// 检查所要添加的字典项是否已经存在
		AcDbObjectId dictObjId;
		AcDbDictionary *pDict = NULL;
		if (pNameObjDict->getAt(TEXT("MyDict"), (AcDbObject*&)pDict, AcDb::kForWrite) == Acad::eKeyNotFound)
		{
			pDict = new AcDbDictionary;
			pNameObjDict->setAt(TEXT("MyDict"), pDict, dictObjId);
			pDict->close();
		}
		pNameObjDict->close();

		// 向新建的字典中添加一个块记录对象
		if (acdbOpenObject(pDict, dictObjId, AcDb::kForWrite) == Acad::eOk)
		{
			CString sLinkName = _T("linkFilePath");
			CString sLinkPath = _T("C:\\Users\\zhangly-e\\Desktop\ggf.dwg");
			AcDbBlockTableRecord* pBlockRecord = new AcDbBlockTableRecord();
			pBlockRecord->setName(sLinkName);
			pBlockRecord->setPathName(sLinkPath);

			AcDbObjectId objectId;
			Acad::ErrorStatus es = pDict->setAt(TEXT("BlockKey"), pBlockRecord, objectId);
			pBlockRecord->close();
			pDict->close();
		}
	}

2)查看有名对象字典

static void ZYMyGroupViewNameDict()
	{
		// 获得对象有名字典中指定的字典项
		AcDbDictionary *pNameObjDict = NULL;
		Acad::ErrorStatus es;
		acdbHostApplicationServices()->workingDatabase()
			->getNamedObjectsDictionary(pNameObjDict, AcDb::kForRead);
		AcDbDictionary *pDict = NULL;
		es = pNameObjDict->getAt(TEXT("MyDict"), (AcDbObject*&)pDict, AcDb::kForRead);
		pNameObjDict->close();

		// 如果不存在指定的字典项,退出程序
		if (es == Acad::eKeyNotFound)
		{
			acutPrintf(TEXT("\n不存在字典项MyDict."));
			return;
		}

		// 获得指定的对象字典中的对象
		AcDbBlockTableRecord *pBlockRecord = NULL;
		if (pDict->getAt(TEXT("BlockKey"), (AcDbObject*&)pBlockRecord, AcDb::kForRead) == Acad::eOk)
		{
			CString sName;
			ACHAR* chName = new ACHAR;
			pBlockRecord->pathName(chName);
			pBlockRecord->close();
			acutPrintf(TEXT("\n当前文件链接的文件为: %s"), chName);
			if (chName)
			{
				delete chName;
				chName = nullptr;
			}
		}
		pDict->close();
	}

4、源码地址

下载源码

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

欧特克_Glodon

很高兴能帮助到您!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值