明经CAD社区

 找回密码
 注册

QQ登录

只需一步,快速开始

搜索
查看: 1092|回复: 0

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

[复制链接]
发表于 2024-9-5 17:16:30 | 显示全部楼层 |阅读模式
本帖最后由 qq1254582201 于 2024-9-5 17:18 编辑

摘要
本文详细介绍了AutoCAD开发中扩展数据XData、扩展记录XRecord以及有名对象字典NameDict的使用。XData用于向实体添加用户数据,但有限;XRecord存储能力更强,常用于替代XData;而NameDict作为图形数据库的一部分,用于保存与实体无关的设计参数。文章涵盖如何添加、查看和删除这些数据,并提供了源码地址供进一步研究。
1、实体-扩展数据XData
扩展数据能被添加到任何实体上,由一个结果缓冲区链表组成,并且随AutoCAD图形一起保存(AutoCAD不会使用扩展数据)。在许多情况下,扩展数据是向实体追加用户数据的一个有效途径,但是每个实体上所附加的扩展数据不能超过16K。
1)添加扩展数据
  1. static void ZYMyGroupAddXData()
  2.   {
  3.     // Put your command code here
  4.     // 提示用户选择所要添加扩展数据的图形对象
  5.     AcDbEntity *pEnt = nullptr;
  6.     AcGePoint3d pickPoint;
  7.     if (CSelectUtil::PromptSelectEntity(TEXT("\n选择所要添加扩展数据的实体:"), AcDbEntity::desc(), pEnt, pickPoint))
  8.     {
  9.       CString appName = TEXT("CustomXDataApp");

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

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

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

  22.       acutPrintf(TEXT("\n成功为实体添加了扩展数据!"));

  23.       pEnt->close();
  24.     }
  25.   }
复制代码
2)查看扩展数据
  1. static void ZYMyGroupViewXData()
  2.   {
  3.     // 提示用户选择所要查看扩展数据的图形对象
  4.     AcDbEntity *pEnt = NULL;
  5.     AcGePoint3d pickPoint;
  6.     if (CSelectUtil::PromptSelectEntity(TEXT("\n选择所要查看扩展数据的实体:"), AcDbEntity::desc(), pEnt, pickPoint))
  7.     {
  8.       CString appName = TEXT("CustomXDataApp");

  9.       // 获取实体的扩展数据
  10.       struct resbuf *pRb = pEnt->xData(appName);
  11.       if (pRb != NULL)
  12.       {
  13.         // 在命令行显示所有的扩展数据
  14.         struct resbuf *pTemp = pRb;    // 使用临时的结果缓冲区指针进行遍历,pRb不修改便于释放

  15.         // 首先要跳过应用程序的名称这一项
  16.         pTemp = pTemp->rbnext;
  17.         acutPrintf(TEXT("\n字符串类型的扩展数据是: %s"), pTemp->resval.rstring);

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

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

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

  26.         acutRelRb(pRb);
  27.       }
  28.       else
  29.       {
  30.         acutPrintf(TEXT("\n所选择的实体不包含任何的扩展数据!"));
  31.       }

  32.       pEnt->close();
  33.     }
  34.   }
复制代码
3)删除扩展数据
  1. static void ZYMyGroupDeleteXData()
  2.   {
  3.     // 提示用户选择所要删除扩展数据的图形对象
  4.     AcDbEntity *pEnt = NULL;
  5.     AcGePoint3d pickPoint;
  6.     if (CSelectUtil::PromptSelectEntity(TEXT("\n选择所要删除扩展数据的实体:"), AcDbEntity::desc(), pEnt, pickPoint))
  7.     {
  8.       CString appName = TEXT("CustomXDataApp");

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

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

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

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

  17.       pEnt->close();
  18.     }
  19.   }
复制代码
2、实体–扩展记录Data
  扩展记录与扩展数据类似,但是其数据存储量和能够存储的数据类型都要多于扩展数据。扩展记录可以保存在实体的扩展字典中。扩展字典隶属于特定的实体,每个实体只能包含一个扩展字典,它为实体保存自定义数据提供了一种途径,实际上, Autodesk 也建议开发者用扩展字典和扩展记录来代替传统的扩展数据。有名对象字典直接保存在图形数据库中,不与特定的实体有关,因此可用于保存与实体无关的设计参数。字典与符号表类似,其中包含一个惟一的字符串关键字索引和对象 ID 号,通过关键字来访问字典中保存的内容。
1)添加扩展记录
  1. static void ZYMyGroupAddXRecord()
  2.   {
  3.     // 提示用户选择所要添加扩展记录的图形对象
  4.     AcDbEntity *pEnt = NULL;
  5.     AcGePoint3d pickPoint;
  6.     if (CSelectUtil::PromptSelectEntity(TEXT("\n选择所要添加扩展记录的实体:"), AcDbEntity::desc(), pEnt, pickPoint))
  7.     {
  8.       // 向实体中添加扩展字典
  9.       pEnt->createExtensionDictionary();
  10.       AcDbObjectId dictObjId = pEnt->extensionDictionary();
  11.       pEnt->close();

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

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

  22.       // 设置扩展记录的内容
  23.       struct resbuf* pRb = acutBuildList(AcDb::kDxfText, TEXT("测试字符串数据"),
  24.         AcDb::kDxfInt32, 12,
  25.         AcDb::kDxfReal, 3.14,
  26.         AcDb::kDxfXCoord, asDblArray(pickPoint),
  27.         RTNONE);
  28.       pXrec->setFromRbChain(*pRb);  // 扩展数据内容填充扩展记录对象
  29.       pXrec->close();
  30.       acutRelRb(pRb);
  31.     }
  32.   }
复制代码
2)查看扩展记录
  1. static void ZYMyGroupViewXRecord()
  2.   {
  3.     // 提示用户选择所要查看扩展记录的图形对象
  4.     AcDbEntity *pEnt = NULL;
  5.     AcGePoint3d pickPoint;
  6.     if (CSelectUtil::PromptSelectEntity(TEXT("\n选择所要查看扩展记录的实体:"), AcDbEntity::desc(), pEnt, pickPoint))
  7.     {
  8.       // 获得实体的扩展字典
  9.       AcDbObjectId dictObjId = pEnt->extensionDictionary();
  10.       pEnt->close();
  11.       if (dictObjId.isNull())
  12.       {
  13.         acutPrintf(TEXT("\n所选择的实体不包含扩展字典!"));
  14.         return;
  15.       }

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

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

  26.         pDict->close();
  27.       }

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

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

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

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

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

  41.         acutRelRb(pRb);
  42.       }
  43.     }
  44.   }
复制代码
3)删除扩展记录
3、图形数据库–有名对象字典
   AutoCAD 每个图形数据库中都包含一个有名对象字典,默认情况下该字典中包含了组、多线样式、布局和打印等信息。例如,用户在 AutoCAD 创建一个组,就会有一个代表改组的元素被添加到组字典中。如果需要在有名对象字典中保存自己的数据,一般可以在有名对象字典中添加一个根字典,然后再向根字典中添加新的字典,进而在新字典中保存数据。这样的好处是不会与有名对象字典的基本字典相混淆。使用 AcDbDatabase 对象的 getNamedObjectsDictionary 函数可以获得图形的有名对象字典(根字典),可以通过 setAt 函数向根字典添加一个字典,或者通过 getAt 函数获得其中的一个字典。获得字典之后,向字典中保存数据的方法与扩展字典完全一致。
1)添加有名对象字典
  1. static void ZYMyGroupAddNameDict()
  2.   {
  3.     // 获得有名对象字典,向其中添加指定的字典项
  4.     AcDbDictionary *pNameObjDict = NULL;//,
  5.     acdbHostApplicationServices()->workingDatabase()
  6.       ->getNamedObjectsDictionary(pNameObjDict, AcDb::kForWrite);
  7.     // 检查所要添加的字典项是否已经存在
  8.     AcDbObjectId dictObjId;
  9.     AcDbDictionary *pDict = NULL;
  10.     if (pNameObjDict->getAt(TEXT("MyDict"), (AcDbObject*&)pDict, AcDb::kForWrite) == Acad::eKeyNotFound)
  11.     {
  12.       pDict = new AcDbDictionary;
  13.       pNameObjDict->setAt(TEXT("MyDict"), pDict, dictObjId);
  14.       pDict->close();
  15.     }
  16.     pNameObjDict->close();

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

  25.       AcDbObjectId objectId;
  26.       Acad::ErrorStatus es = pDict->setAt(TEXT("BlockKey"), pBlockRecord, objectId);
  27.       pBlockRecord->close();
  28.       pDict->close();
  29.     }
  30.   }
复制代码
2)查看有名对象字典
  1. static void ZYMyGroupViewNameDict()
  2.   {
  3.     // 获得对象有名字典中指定的字典项
  4.     AcDbDictionary *pNameObjDict = NULL;
  5.     Acad::ErrorStatus es;
  6.     acdbHostApplicationServices()->workingDatabase()
  7.       ->getNamedObjectsDictionary(pNameObjDict, AcDb::kForRead);
  8.     AcDbDictionary *pDict = NULL;
  9.     es = pNameObjDict->getAt(TEXT("MyDict"), (AcDbObject*&)pDict, AcDb::kForRead);
  10.     pNameObjDict->close();

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

  17.     // 获得指定的对象字典中的对象
  18.     AcDbBlockTableRecord *pBlockRecord = NULL;
  19.     if (pDict->getAt(TEXT("BlockKey"), (AcDbObject*&)pBlockRecord, AcDb::kForRead) == Acad::eOk)
  20.     {
  21.       CString sName;
  22.       ACHAR* chName = new ACHAR;
  23.       pBlockRecord->pathName(chName);
  24.       pBlockRecord->close();
  25.       acutPrintf(TEXT("\n当前文件链接的文件为: %s"), chName);
  26.       if (chName)
  27.       {
  28.         delete chName;
  29.         chName = nullptr;
  30.       }
  31.     }
  32.     pDict->close();
  33.   }
复制代码
4、源码地址
下载地址
转载自<四>objectARX开发:扩展数据XData、扩展记录XRecord和有名对象字典NameDict_arx2017开发输入命令输出xdata-CSDN博客


评分

参与人数 1明经币 +1 收起 理由
gzxl + 1 可以啊,希望更多人能学习及分享ObjectARX

查看全部评分

您需要登录后才可以回帖 登录 | 注册

本版积分规则

小黑屋|手机版|CAD论坛|CAD教程|CAD下载|联系我们|关于明经|明经通道 ( 粤ICP备05003914号 )  
©2000-2023 明经通道 版权所有 本站代码,在未取得本站及作者授权的情况下,不得用于商业用途

GMT+8, 2024-11-22 20:04 , Processed in 0.182793 second(s), 23 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表