ObjectARX开发过程中,有时会使用自定义数据,主要包括:
定义:
int acdbRegApp(
const ACHAR * appname
);
作用:在当前图形中注册一个应用程序名称,用于分组,存储,检索和修改实体的扩展数据。appname必须遵守符号表名称(例如图层名称)的规则,且不能和已经存在的RegApp重复。每个新名称将产生一个新的acdbRegApp记录。
返回值:
定义:
virtual Acad::ErrorStatus setXData(
const resbuf* xdata
);
作用:设置一个对象的扩展数据。
返回值:
定义:
virtual resbuf* xData(
const ACHAR* regappName = nullptr
) const;
作用:获取一个对象中名为“regappName”的扩展数据。如果regappName == NULL,则返回所有xdata,否则仅返回指定名称为regappName的xdata。如果需要多个regappName的xdata,则必须对该成员函数进行多次调用,每个regappName调用一次。
返回值:
添加Xdata代码如下:
//添加Xdata
static void MyGroupaddXdata()
{
//提示用户选择对象
AcDbObject* pObj = selectObject(AcDb::kForRead);
if (!pObj) {
acutPrintf(_T("Error selecting object\n"));
return;
}
//获取Xdata名称
TCHAR appName[132], resString[200];
appName[0] = resString[0] = _T('\0');
acedGetString(NULL, _T("Enter application name: "), appName);
acedGetString(NULL, _T("Enter string to be added: "), resString);
struct resbuf *pRb, *pTemp;
pRb = pObj->xData(appName);
if (pRb != NULL)
{
//如果Xdata已经存在,不执行任何操作
for (pTemp = pRb; pTemp->rbnext != NULL;pTemp = pTemp->rbnext)
{
;
}
}
else
{
//如果Xdata不存在,向当前对象注册名为appName的Xdata
acdbRegApp(appName);
pRb = acutNewRb(AcDb::kDxfRegAppName);
pTemp = pRb;
pTemp->resval.rstring
= (TCHAR*) malloc((_tcslen(appName) + 1) * sizeof(TCHAR));
_tcscpy(pTemp->resval.rstring, appName);
}
//向新注册的Xdata添加自定义扩展数据
pTemp->rbnext = acutNewRb(AcDb::kDxfXdAsciiString);
pTemp = pTemp->rbnext;
pTemp->resval.rstring
= (TCHAR*) malloc((_tcslen(resString) + 1) * sizeof(TCHAR));
_tcscpy(pTemp->resval.rstring, resString);
//把对象从AcDb::kForRead 状态变成AcDb::kForWrite状态
pObj->upgradeOpen();
pObj->setXData(pRb);
pObj->close();
acutRelRb(pRb);
}
查看Xdata代码如下:
//显示Xdata
static void MyGroupprintXdata()
{
//提示用户选择对象
AcDbObject *pObj;
if ((pObj = selectObject(AcDb::kForRead)) == NULL) {
return;
}
//获取Xdata名称
TCHAR appname[133];
if (acedGetString(NULL,
_T("\nEnter the desired Xdata application name: "),
appname) != RTNORM)
{
return;
}
// 根据Xdata名称appname,调用printList()函数输出Xdata信息
struct resbuf *pRb;
pRb = pObj->xData(appname);
if (pRb != NULL)
{
printList(pRb);
acutRelRb(pRb);
} else {
acutPrintf(_T("\nNo xdata for this appname"));
}
pObj->close();
}
删除Xdata代码如下:
//删除Xdata
static void MyGroupdeleteXdata()
{
AcDbObject* pObj = selectObject(AcDb::kForRead);
if (!pObj) {
acutPrintf(_T("Error selecting object\n"));
return;
}
//获取Xdata名称
TCHAR appName[132];
appName[0] = _T('\0');
acedGetString(NULL, _T("Enter application name: "), appName);
//在pObj的Xdata中查找appName
struct resbuf *pTemp = nullptr;
pTemp = pObj -> xData(appName);
if (pTemp != nullptr)
{
// 删除名为appName的Xdata
acdbRegApp(appName);
struct resbuf* pRb = acutBuildList(AcDb::kDxfRegAppName, appName, RTNONE);
pObj->upgradeOpen();
pObj->setXData(pRb);
acutRelRb(pRb);
acutPrintf(TEXT("\nXdata deleted successfully."));
}
else
{
//未找到需要删除的Xdata
acutPrintf(TEXT("\nNo Xdata found."));
}
acutRelRb(pTemp);
pObj->close();
}
还需要添加两个函数,printList()用于在命令窗口中打印Xdata信息;selectObject()用于提示用户选择实体。代码如下:
//在AutoCAD命令窗口中打印Xdata信息
static void printList(struct resbuf* pRb)
{
int rt, i;
TCHAR buf[133];
for (i = 0;pRb != NULL;i++, pRb = pRb->rbnext)
{
if (pRb->restype < 1010)
{
rt = RTSTR;
}
else if (pRb->restype < 1040)
{
rt = RT3DPOINT;
}
else if (pRb->restype < 1060)
{
rt = RTREAL;
}
else if (pRb->restype < 1071)
{
rt = RTSHORT;
}
else if (pRb->restype == 1071)
{
rt = RTLONG;
}
else
{
rt = pRb->restype;
}
switch (rt)
{
case RTSHORT:
if (pRb->restype == RTSHORT)
{
acutPrintf(
_T("RTSHORT : %d\n"), pRb->resval.rint);
}
else
{
acutPrintf(_T("(%d . %d)\n"), pRb->restype,
pRb->resval.rint);
};
break;
case RTREAL:
if (pRb->restype == RTREAL)
{
acutPrintf(_T("RTREAL : %0.3f\n"),
pRb->resval.rreal);
}
else
{
acutPrintf(_T("(%d . %0.3f)\n"), pRb->restype,
pRb->resval.rreal);
};
break;
case RTSTR:
if (pRb->restype == RTSTR)
{
acutPrintf(_T("RTSTR : %s\n"),
pRb->resval.rstring);
}
else
{
acutPrintf(_T("(%d . \"%s\")\n"), pRb->restype,
pRb->resval.rstring);
};
break;
case RT3DPOINT:
if (pRb->restype == RT3DPOINT)
{
acutPrintf(
_T("RT3DPOINT : %0.3f, %0.3f, %0.3f\n"),
pRb->resval.rpoint[X],
pRb->resval.rpoint[Y],
pRb->resval.rpoint[Z]);
}
else {
acutPrintf(_T("(%d %0.3f %0.3f %0.3f)\n"),
pRb->restype,
pRb->resval.rpoint[X],
pRb->resval.rpoint[Y],
pRb->resval.rpoint[Z]);
}
break;
case RTLONG:
acutPrintf(_T("RTLONG : %dl\n"), pRb->resval.rlong);
break;
}
if ((i == 23) && (pRb->rbnext != NULL))
{
i = 0;
acedGetString(0,
_T("Press to continue..." ), buf);
}
}
}
//提示用户选择实体
static AcDbObject* selectObject(AcDb::OpenMode openMode)
{
int ss;
ads_name en;
ads_point pt;
acedInitGet(RSG_OTHER, _T("Handle _Handle"));
ss = acedEntSel(_T("\nSelect an Entity or enter")_T(" 'H' to enter its handle: "), en, pt);
TCHAR handleStr[132];
AcDbObjectId eId;
switch (ss)
{
case RTNORM:
break;
case RTKWORD:
if ((acedGetString(Adesk::kFalse,
_T("Enter Valid Object Handle: "),
handleStr) == RTNORM)
&& (acdbHandEnt(handleStr, en) == RTNORM))
{
break;
}
default:
acutPrintf(_T("Nothing Selected, Return Code==%d\n"),ss);
return NULL;
}
Acad::ErrorStatus retStat;
retStat = acdbGetObjectId(eId, en);
if (retStat != Acad::eOk) {
acutPrintf(_T("\nacdbGetObjectId failed"));
acutPrintf(_T("\nen==(%lx,%lx), retStat==%d\n"),
en[0], en[1], eId);
return NULL;
}
AcDbObject* obj;
if ((retStat = acdbOpenObject(obj, eId, openMode))
!= Acad::eOk)
{
acutPrintf(_T("acdbOpenEntity failed: ename:(%lx,%lx),")
_T(" mode:%d retStat:%d"), en[0], en[1],
openMode, retStat);
return NULL;
}
return obj;
}
使用“addXdata”命令选择实体并添加扩展数据,“printXdata”命令在AutoCAD的命令窗口显示添加的扩展数据,“deleteXdata”命令删除扩展数据。如下图所示,使用Xdata向图中被选中直线追加了自定义数据。
源代码:xData
提取码:4bbm
参考文档
[1]:Autodesk ObjectARX for AutoCAD 2015: Developer Guide.