|
在编程中,某些时候不可避免地要向图形中添加一些用户数据,例如,将一条直线解释为输电线、道路中心线,或者其他类型的对象,也可能要将当前图形的编号随图形一起保存起来。
要向图形中的实体追加一些数据,可以使用扩展数据或者扩展记录;要向图形本身追加一些数据,则可以使用命名对象字典。
1. 说明
对于同一种类型的实体,可能将其作为管线、道路中心线和建筑物轮廓线等。为了实现这个目的,就可以在实体上追加扩展数据,要获得某个实体类型的时候,就可以读取其扩展数据得到类型信息。
本篇演示了向实体追加扩展数据和显示一个实体的扩展数据,并且加入了容错的处理:
向已经包含扩展数据的实体添加扩展数据,程序会自动退出;
要求显示不包含任何扩展数据的实体的扩展数据,程序同样会退出。
2. 思路
扩展数据能被添加到任何实体上,由一个结果缓冲区链表组成,并且随 AutoCAD 图形一起保存(AutoCAD 不会使用扩展数据)。在许多情况下,扩展数据是向实体追加用户数据的一个有效途径,但是每个实体上所附加的扩展数据不能超过16K 。
AcDbObject 类的 setXData 函数用于设置一个对象的扩展数据,其定义为:
virtual Acad::ErrorStatus
AcDbObject::setXData(const resbuf* xdata);
//AcDbObject 类的 xData 函数用于获取一个对象的扩展数据,其定义为:
virtual resbuf*
AcDbObject::xData(const char* regappName = NULL) const;
任何一个应用程序都能将扩展数据附加到实体上,因此所有的扩展数据都需要一个唯一的应用程序名称,该名称不超过31 个字符。为了注册一个应用程序,可以使用全局函数acdbRegApp。
3. 步骤
(1) 添加一个新类,命名为 CXData。添加一个新函数 AddXData(),用于向实体追加指定的扩展数据.
在构建存储扩展数据的结果缓冲区时,除了应用程序名称对应的数据类型为 AcDb::kDxfRegAppName 之外,其他的数据类型前缀均为 AcDb::kDxfXd ,所有的与扩展数据有关的数据类型均带有这个前缀。 在函数结束之前,记得删除结果缓冲区。
其实现函数为:
//向实体追加指定的扩展数据
static void AddXData(); //向实体追加指定的扩展数据
//向实体追加指定的扩展数据
void CXData::AddXData()
{
//提示用户选择所要添加扩展数据的图形对象
ads_name en;
ads_point pt;
if(acedEntSel(_T("\n选择所要添加的扩展数据的实体:"), en, pt) != RTNORM)
return;
AcDbObjectId entId;
Acad::ErrorStatus es = acdbGetObjectId(entId, en);
//扩展数据的内容
struct resbuf* pRb;
TCHAR appName[] = {_T("XData")};
TCHAR typeName[] = {_T("道路中心线")};
//注册应用程序的内容
acdbRegApp(_T("XData"));
//创建结果缓冲区链表
pRb = acutBuildList(AcDb::kDxfRegAppName, appName, //应用程序名称
AcDb::kDxfXdAsciiString, typeName, //字符串
AcDb::kDxfXdInteger32, 2, //整数
AcDb::kDxfXdReal, 3.14, //实数
AcDb::kDxfXdWorldXCoord, pt, //点坐标值
RTNONE);
//为选择的实体添加扩展函数
AcDbEntity *pEnt;
acdbOpenAcDbEntity(pEnt, entId, AcDb::kForWrite);
struct resbuf *pTemp;
pTemp = pEnt->xData(_T("XData"));
//判断: 如果已经包含了扩展数据,就不再添加新的扩展数据
if (pTemp != NULL)
{
acutRelRb(pTemp);
acutPrintf(_T("\n所选择的实体已经包含了扩展数据! "));
}else
{
pEnt->setXData(pRb);
}
//关闭,释放分配给结果缓冲区或结果缓冲区链表的内存
pEnt->close();
acutRelRb(pRb);
}
(2) 查看指定的实体的扩展数据
使用 AcDbObject 类的 xData 函数能够获得一个结果缓冲区链表,该实体的所有扩展数据都保存在该链表中,因此可以通过遍历结果缓冲区的方法获得扩展数据。
// 查看实体的扩展数据
static void ViewXData(); // 查看实体的扩展数据
// 查看实体的扩展数据
void CXData::ViewXData()
{
// 提示用户选择所要查看扩展数据的图形对象
ads_name en;
ads_point pt;
if(acedEntSel(_T("\n选择所要查看扩展数据的实体: "), en, pt) != RTNORM)
return;
AcDbObjectId entId;
Acad::ErrorStatus es = acdbGetObjectId(entId, en);
// 打开图形对象,查看是否包含扩展数据
AcDbEntity *pEnt;
acdbOpenAcDbEntity(pEnt, entId, AcDb::kForRead);
struct resbuf *pRb;
pRb = pEnt->xData(_T("XData"));
pEnt->close();
if (pRb != NULL)
{
// 在命令行显示所有的扩展数据
struct resbuf *pTemp;
pTemp = pRb;
// 首先要跳过应用程序的名称这一项
pTemp = pTemp->rbnext;
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);
}else
{
acutPrintf(_T("\n所选择的实体不包含任何的扩展数据! "));
}
}
(3) 在acrxEntryPoint.cpp中
ACED_ARXCOMMAND_ENTRY_AUTO(CArxConfigApp, MidasMyGroup, MyAddXData, MyAddXData, ACRX_CMD_MODAL, NULL) //添加扩展数据
ACED_ARXCOMMAND_ENTRY_AUTO(CArxConfigApp, MidasMyGroup, MyViewXData, MyViewXData, ACRX_CMD_MODAL, NULL) //查看扩展数据
//当前项目中注册命令 AddXData(添加扩展数据)
static void MidasMyGroupMyAddXData()
{
CXData::AddXData();
}
//当前项目中注册命令 ViewXData(查看扩展数据)
static void MidasMyGroupMyViewXData()
{
CXData::ViewXData();
}
|
|