qq1254582201 发表于 2024-9-5 17:16:30

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]
查看完整版本: objectARX开发:扩展数据XData、扩展记录XRecord和有名对象字典NameDict