|
说明
扩展记录与扩展数据类似,但是其数据存储量和能够存储的数据类型都要多于扩展数据。扩展记录可以保存在实体的扩展字典或有名对象字典中。
扩展字典隶属于特定的实体,每个实体只能包含一个扩展字典,它为实体保存自定义数据提供了一种途径,实际上,Autodesk 也建议开发者用扩展字典和扩展记录来代替传统的扩展数据。有名对象字典直接保存在图形数据库中,不与特定的实体有关,因此可用于保存与实体无关的设计参数。
字典与符号表类似,其中包含一个惟一的字符串关键字索引和对象 ID 号,通过关键字来访问字典中保存的内容。
本节的实例分别在实体和图形中保存与上节实例相同的数据,让读者对比扩展数据和扩展记录使用的异同,更好地理解这两种保存数据的机制。
2. 思路
(1) 访问实体的扩展字典
扩展字典与特定的实体关联,但是一个实体在默认情况下不包含扩展字典,如果要利用扩展字典保存与实体关联的数据,可以使用 createExtensionDictionary 函数为实体建立扩展字典,如果实体已经包含扩展字典,该函数的调用不会产生任何影响。
创建扩展字典之后,就可以使用 extensionDictionary 函数获得实体的扩展字典, AcDbDictionary 对象的 setAt 函数可以为字典添加一个元素,该元素既可以是 AcDbXrecord , 也可以是其他类型的对象。如果添加了 AcDbXrecord (扩展记录),就可以使用 acutBuildList函数构建一个保存数据的结果缓冲区链表,然后使用 setFromRbChain 函数将结果缓冲区链表添加到扩展及记录中,这样就使用扩展记录保存了数据。
如果要访问实体扩展字典中保存的扩展记录,可以使用 extensionDictionary 函数获得实体的扩展字典,然后通过字典的 getAt 函数得到指定的元素(扩展记录),使用 AcDbXrecord类的 rbChain 函数得到保存数据的结果缓冲区链表,并且遍历该链表获得保存的数据。
(2) 访问有名对象字典
AutoCAD 每个图形数据库中都包含一个有名对象字典,默认情况下该字典中包含了组、多线样式、布局和打印等信息。例如,用户在 AutoCAD 创建一个组,就会有一个代表改组的元素被添加到组字典中。
如果需要在有名对象字典中保存自己的数据,一般可以在有名对象字典中添加一个根字典,然后再向根字典中添加新的字典,进而在新字典中保存数据。这样的好处是不会与有名对象字典的基本字典相混淆。
使用 AcDbDatabase 对象的 getNamedObjectsDictionary 函数可以获得图形的有名对象字典 (根字典),可以通过 setAt 函数向根字典添加一个字典,或者通过 getAt 函数获得其中的一个字典。获得字典之后,向字典中保存数据的方法与扩展字典完全一致。
3. 步骤
(1) 提示用户选择一个实体,并将一些附加的数据保存到该实体的扩展字典中
// 添加到扩展字典
static void AddXRecord(); // 提示用户选择一个实体,并将一些附加的数据保存到该实体的扩展字典中
// 添加到扩展字典
// 提示用户选择一个实体,并将一些附加的数据保存到该实体的扩展字典中
void CXData::AddXRecord()
{
// 提示用户选择所要添加扩展记录的图形对象
ads_name en;
ads_point pt;
if (acedEntSel(_T("\n选择所要添加扩展记录的实体:"), en, pt) != RTNORM)
return;
AcDbObjectId entId; // 要添加扩展记录的实体ID
Acad::ErrorStatus es = acdbGetObjectId(entId, en);
AcDbXrecord *pXrec = new AcDbXrecord;
AcDbObject *pObj;
AcDbObjectId dictObjId, xRecObjId;
AcDbDictionary *pDict;
// 要在扩展记录中保存的字符串
TCHAR entType[] = {_T("直线")};
struct resbuf* pRb;
// 向实体中添加扩展字典
acdbOpenObject(pObj, entId, AcDb::kForWrite);
pObj->createExtensionDictionary();
dictObjId = pObj->extensionDictionary();
pObj->close();
// 向扩展字典中添加一条记录
acdbOpenObject(pDict, dictObjId, AcDb::kForWrite);
pDict->setAt(_T("XRecord"), pXrec, xRecObjId);
pDict->close();
// 设置扩展记录的内容
pRb = acutBuildList(AcDb::kDxfText, entType,
AcDb::kDxfInt32, 12,
AcDb::kDxfReal, 3.14,
AcDb::kDxfXCoord, pt,
RTNONE);
pXrec->setFromRbChain(*pRb);
pXrec->close();
acutRelRb(pRb);
}
/*
// AcDbXrecord 类的成员函数 setFromRbChain 的定义:
Acad::ErrorStatus setFromRbChain(
const resbuf& pRb,
AcDbDatabase* auxDb = NULL);
// 因此,传递的第一个参数必须是 pRb 所指向的结果缓冲区对象,也就是*pRb。
*/
(2) 提示用户选择图形对象,如果选中的实体包含扩展字典,就查看扩展字典中“Xrecord”元素所保存的数据
// 查看扩展字典保存的数据
static void ViewXRecord();
// 查看扩展字典保存的数据
// 提示用户选择图形对象,如果选中的实体包含扩展字典,就查看扩展字典中“Xrecord”元素所保存的数据
void CXData::ViewXRecord()
{
// 提示用户选择所要查看扩展记录的图形对象
ads_name en;
ads_point pt;
if (acedEntSel(_T("\n选择所要查看扩展记录的实体:"), en, pt) != RTNORM)
return;
AcDbObjectId entId;
Acad::ErrorStatus es = acdbGetObjectId(entId, en);
// 打开图形对象,获得实体扩展字典的ObjectId
AcDbEntity *pEnt;
acdbOpenAcDbEntity(pEnt, entId, AcDb::kForRead);
AcDbObjectId dictObjId = pEnt->extensionDictionary();
pEnt->close();
// 查看实体是否包含扩展字典
if (dictObjId == AcDbObjectId::kNull)
{
acutPrintf(_T("\n所选择的实体不包含扩展字典!"));
return;
}
// 打开扩展字典,获得与关键字“XRecord”关联的扩展记录
AcDbDictionary *pDict;
AcDbXrecord *pXrec;
acdbOpenObject(pDict, dictObjId, AcDb::kForRead);
pDict->getAt(_T("XRecord"), (AcDbObject*&)pXrec, AcDb::kForRead);
pDict->close();
// 获得扩展记录的数据链表并关闭扩展数据对象
struct resbuf *pRb;
pXrec->rbChain(&pRb);
pXrec->close();
if (pRb != NULL)
{
// 在命令行显示扩展记录内容
struct resbuf *pTemp;
pTemp = pRb;
acutPrintf(_T("\n字符串类型的扩展数据是:%s"), pTemp->resval.rstring);
pTemp = pTemp->rbnext;
acutPrintf(_T("\n整数类型的扩展数据是:%d"), pTemp->resval.rint);
pTemp = pTemp->rbnext;
acutPrintf(_T("\n实数类型的扩展数据是:%.2f"), pTemp->resval.rreal);
pTemp = pTemp->rbnext;
acutPrintf(_T("\n点坐标类型的扩展数据是:(%.2f, %.2f, %.2f)"),
pTemp->resval.rpoint[X], pTemp->resval.rpoint[Y], pTemp->resval.rpoint[Z]);
acutRelRb(pRb);
}
}
/*
//AcDbXrecord 类的 rbChain 函数定义为:
Acad::ErrorStatus rbChain(
resbuf** ppRb,
AcDbDatabase* auxDb = NULL) const;
//第一个参数是一个指针的指针,帮助系统中已经说明要输入一个指向结果缓冲区的指针的地址
//(Input the address of a pointer to resbuf structure),因此应该输入&pRb 作为参数值。
*/
(3) 向当前的图形数据库中添加一个字典,并在其中保存自定义数据
//向当前的图形数据库中添加一个字典,并在其中保存自定义数据
static void AddNameDict(); // 向当前的图形数据库中添加一个字典,并在其中保存自定义数据
//向当前的图形数据库中添加一个字典,并在其中保存自定义数据
void CXData::AddNameDict()
{
// 要在扩展记录中保存的字符串
TCHAR entType[] = {_T("直线")};
struct resbuf *pRb;
// 获得有名对象字典,向其中添加指定的字典项
AcDbDictionary *pNameObjDict, *pDict;
acdbHostApplicationServices()->workingDatabase()->getNamedObjectsDictionary(pNameObjDict, AcDb::kForWrite);
// 检查所要添加的字典项是否已经存在
AcDbObjectId dictObjId;
if (pNameObjDict->getAt(_T("MyDict"), (AcDbObject*&)pDict, AcDb::kForWrite) == Acad::eKeyNotFound)
{
pDict = new AcDbDictionary;
pNameObjDict->setAt(_T("MyDict"), pDict, dictObjId);
pDict->close();
}
pNameObjDict->close();
// 向新建的字典中添加一个扩展记录
AcDbObjectId xrecObjId;
AcDbXrecord *pXrec = new AcDbXrecord;
acdbOpenObject(pDict, dictObjId, AcDb::kForWrite);
pDict->setAt(_T("XRecord"), pXrec, xrecObjId);
pDict->close();
// 设置扩展记录的内容
ads_point pt;
pt[X] = 100;
pt[Y] = 100;
pt[Z] = 0;
pRb = acutBuildList(AcDb::kDxfText, entType,
AcDb::kDxfInt32, 12,
AcDb::kDxfReal, 3.14,
AcDb::kDxfXCoord, pt,
RTNONE);
pXrec->setFromRbChain(*pRb);
pXrec->close();
acutRelRb(pRb);
}
从上面的代码可以看出,在有名对象字典中保存数据与在扩展字典中保存数据相比,仅仅是获得字典的方法有所不同。
(4) 检查当前图形中是否包含指定的用户字典,并在命令窗口中显示字典中保存的自定义数据
// 检查当前图形中是否包含指定的用户字典,并在命令窗口中显示字典中保存的自定义数据
static void ViewNameDict(); // 检查当前图形中是否包含指定的用户字典,并在命令窗口中显示字典中保存的自定义数据
// 检查当前图形中是否包含指定的用户字典,并在命令窗口中显示字典中保存的自定义数据
void CXData::ViewNameDict()
{
// 获得对象有名字典中指定的字典项
AcDbDictionary *pNameObjDict, *pDict;
Acad::ErrorStatus es;
acdbHostApplicationServices()->workingDatabase()->getNamedObjectsDictionary(pNameObjDict, AcDb::kForRead);
es = pNameObjDict->getAt(_T("MyDict"), (AcDbObject*&)pDict, AcDb::kForRead);
pNameObjDict->close();
// 如果不存在指定的字典项,退出程序
if (es == Acad::eKeyNotFound)
return;
// 获得指定的对象字典
AcDbXrecord *pXrec;
pDict->getAt(_T("XRecord"), (AcDbObject*&)pXrec, AcDb::kForRead);
pDict->close();
// 获得扩展记录的数据链表并关闭扩展数据对象
struct resbuf *pRb;
pXrec->rbChain(&pRb);
pXrec->close();
if (pRb != NULL)
{
// 在命令行显示扩展记录内容
struct resbuf *pTemp;
pTemp = pRb;
acutPrintf(_T("\n字符串类型的扩展数据是:%s"), pTemp->resval.rstring);
pTemp = pTemp->rbnext;
acutPrintf(_T("\n整数类型的扩展数据是:%d"), pTemp->resval.rint);
pTemp = pTemp->rbnext;
acutPrintf(_T("\n实数类型的扩展数据是:%.2f"), pTemp->resval.rreal);
pTemp = pTemp->rbnext;
acutPrintf(_T("\n点坐标类型的扩展数据是:(%.2f, %.2f, %.2f)"),
pTemp->resval.rpoint[X], pTemp->resval.rpoint[Y], pTemp->resval.rpoint[Z]);
acutRelRb(pRb);
}
}
(5) 在acrxEntryPoint.cpp中
ACED_ARXCOMMAND_ENTRY_AUTO(CArxConfigApp, MidasMyGroup, MyAddXRecord, MyAddXRecord, ACRX_CMD_MODAL, NULL) //添加扩展字典
ACED_ARXCOMMAND_ENTRY_AUTO(CArxConfigApp, MidasMyGroup, MyViewXRecord, MyViewXRecord, ACRX_CMD_MODAL, NULL) //查看扩展字典
ACED_ARXCOMMAND_ENTRY_AUTO(CArxConfigApp, MidasMyGroup, MyAddNameDict, MyAddNameDict, ACRX_CMD_MODAL, NULL) //添加自定义数据
ACED_ARXCOMMAND_ENTRY_AUTO(CArxConfigApp, MidasMyGroup, MyViewNameDict, MyViewNameDict, ACRX_CMD_MODAL, NULL) //查看自定义数据
//当前项目中注册命令 AddXRecord(添加扩展数据)
static void MidasMyGroupMyAddXRecord()
{
CXData::AddXRecord();
}
//当前项目中注册命令 ViewXRecord(查看扩展数据)
static void MidasMyGroupMyViewXRecord()
{
CXData::ViewXRecord();
}
//当前项目中注册命令 AddNameDict(添加扩展数据)
static void MidasMyGroupMyAddNameDict()
{
CXData::AddNameDict();
}
//当前项目中注册命令 ViewNameDict(查看扩展数据)
static void MidasMyGroupMyViewNameDict()
{
CXData::ViewNameDict();
}
现在, 即使在执行ViewXRecord 和 ViewNameDict 命令之前保存并关闭了图形,再次打开图形仍然可以查询到这些数据。实际上,扩展记录所保存的数据已经被保存在图形 数据库中,可以使用数据库监视器来查看有名对象字典和扩展字典中保存数据的结构。
|
|