objectARX开发:扩展数据XData、扩展记录XRecord和有名对象字典NameDict
本帖最后由 qq1254582201 于 2024-9-5 17:18 编辑摘要
本文详细介绍了AutoCAD开发中扩展数据XData、扩展记录XRecord以及有名对象字典NameDict的使用。XData用于向实体添加用户数据,但有限;XRecord存储能力更强,常用于替代XData;而NameDict作为图形数据库的一部分,用于保存与实体无关的设计参数。文章涵盖如何添加、查看和删除这些数据,并提供了源码地址供进一步研究。
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, pTemp->resval.rpoint,
pTemp->resval.rpoint);
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、实体–扩展记录Data
扩展记录与扩展数据类似,但是其数据存储量和能够存储的数据类型都要多于扩展数据。扩展记录可以保存在实体的扩展字典中。扩展字典隶属于特定的实体,每个实体只能包含一个扩展字典,它为实体保存自定义数据提供了一种途径,实际上, 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, pTemp->resval.rpoint,
pTemp->resval.rpoint);
acutRelRb(pRb);
}
}
}
3)删除扩展记录
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、源码地址
下载地址
转载自<四>objectARX开发:扩展数据XData、扩展记录XRecord和有名对象字典NameDict_arx2017开发输入命令输出xdata-CSDN博客
页:
[1]