解决方案

ObjectARX开发笔记(二)——使用Xdata向AutoCAD图形追加自定义数据

seo靠我 2023-09-25 09:51:22

1.自定义数据

ObjectARX开发过程中,有时会使用自定义数据,主要包括:

自定义对象——可以让用户按照自己希望的方式封装数据,并向AutoCAD中添加第三方实体类型,这些实体类型用于与AutoCADSEO靠我自身实体一样的特性,ObjectARX程序能够灵活控制自定义实体的显示。扩充数据——可以向图形本身或者图形中的实体追加一些数据。

扩充数据又分为Xdata(eXtension data)和 XrecorSEO靠我d(eXtension record)两种。

2.Xdata

AutoCAD数据库的任何对象都可以灵活的附加一定数量的扩展数(Xdata),供开发者使用。扩展数据的含义由开发者自行解释,AutoCAD只维SEO靠我护这些数据而不管其具体的含义。扩展数据是链表组,每个组是链表系列,以一个名字开头以做标识。这个名字是应用程序名。应用程序名通过acdbRegApp()进行注册,最长可达31个字符 所附着的数据链表不能SEO靠我超过16K。DXF组码只能采用1000~1071之间的组码值。

2.1 Xdata相关函数—acdbRegApp

定义

int acdbRegApp(const ACHAR * appname SEO靠我 );

作用

:在当前图形中注册一个应用程序名称,用于分组,存储,检索和修改实体的扩展数据。appname必须遵守符号表名称(例如图层名称)的规则,且不能和已经存在的RegApp重复。每个新名称将产生SEO靠我一个新的acdbRegApp记录。

返回值: appname注册成功,返回RTNORM;appname已存在,返回RTERROR;appname注册失败,返回一个表明失败原因的系统变量ERRNO。

2.2 SEO靠我Xdata相关函数—setXData

定义

virtual Acad::ErrorStatus setXData(const resbuf* xdata );

作用:设置一个对象的扩展数据SEO靠我

每个注册(regappname)链表以 restype = 1001 分界,并且resval.rstring应该是合法字符。RegappName必须是AcDbRegAppTable中存在的。如果xdSEO靠我ata中已经有该regappname组, 则新的链表将覆盖之 。要清除xdata中某个regappname的所有内容,只需建立一个以此regappname开头的空链表即可。

返回值

如果xdata成功添SEO靠我加到对象,则返回Acad :: eOk。如果对象的xdata区域中没有足够的空间,则返回Acad::eXdataSizeExceeded。如果xdata中的所有regappName均不存在,则返回AcSEO靠我ad :: eRegappIdNotFound。

2.3 Xdata相关函数—XData

定义

virtual resbuf* xData(const ACHAR* regappName = nullptSEO靠我r ) const;

作用

:获取一个对象中名为“regappName”的扩展数据。如果regappName == NULL,则返回所有xdata,否则仅返回指定名称为regappNameSEO靠我的xdata。如果需要多个regappName的xdata,则必须对该成员函数进行多次调用,每个regappName调用一次。

返回值: 返回包含对象xdata副本的resbuf结构的链接列表。

2.4 XSEO靠我data实例,添加、查看和删除Xdata

添加Xdata代码如下:

//添加Xdatastatic void MyGroupaddXdata() {//提示用户选择对象AcDbObject* pObj =SEO靠我 selectObject(AcDb::kForRead);if (!pObj) {acutPrintf(_T("Error selecting object\n"));return;}//获取XdaSEO靠我ta名称TCHAR appName[132], resString[200];appName[0] = resString[0] = _T(\0);acedGetString(NULL, _T("EnSEO靠我ter application name: "), appName);acedGetString(NULL, _T("Enter string to be added: "), resString);SEO靠我struct resbuf *pRb, *pTemp;pRb = pObj->xData(appName);if (pRb != NULL) {//如果Xdata已经存在,不执行任何操作for (pTSEO靠我emp = pRb; pTemp->rbnext != NULL;pTemp = pTemp->rbnext){ ; }} else {//如果Xdata不存在,向当前对象注册名为appName的XdSEO靠我ataacdbRegApp(appName);pRb = acutNewRb(AcDb::kDxfRegAppName);pTemp = pRb;pTemp->resval.rstring= (TCHSEO靠我AR*) malloc((_tcslen(appName) + 1) * sizeof(TCHAR));_tcscpy(pTemp->resval.rstring, appName);}//向新注册的SEO靠我Xdata添加自定义扩展数据pTemp->rbnext = acutNewRb(AcDb::kDxfXdAsciiString);pTemp = pTemp->rbnext;pTemp->resvalSEO靠我.rstring= (TCHAR*) malloc((_tcslen(resString) + 1) * sizeof(TCHAR));_tcscpy(pTemp->resval.rstring, rSEO靠我esString);//把对象从AcDb::kForRead 状态变成AcDb::kForWrite状态pObj->upgradeOpen();pObj->setXData(pRb);pObj->clSEO靠我ose();acutRelRb(pRb);}

查看Xdata代码如下:

//显示Xdata static void MyGroupprintXdata(){//提示用户选择对象AcDbObSEO靠我ject *pObj;if ((pObj = selectObject(AcDb::kForRead)) == NULL) {return;}//获取Xdata名称TCHAR appname[133]SEO靠我;if (acedGetString(NULL,_T("\nEnter the desired Xdata application name: "),appname) != RTNORM){returSEO靠我n;}// 根据Xdata名称appname,调用printList()函数输出Xdata信息struct resbuf *pRb;pRb = pObj->xData(appname);if (pRbSEO靠我 != NULL) {printList(pRb);acutRelRb(pRb);} else {acutPrintf(_T("\nNo xdata for this appname"));}pObjSEO靠我->close();}

删除Xdata代码如下:

//删除Xdatastatic void MyGroupdeleteXdata(){AcDbObject* pObj = selectObject(AcDSEO靠我b::kForRead);if (!pObj) {acutPrintf(_T("Error selecting object\n"));return;}//获取Xdata名称 TCHAR appNamSEO靠我e[132];appName[0] = _T(\0);acedGetString(NULL, _T("Enter application name: "), appName);//在pObj的XdatSEO靠我a中查找appNamestruct resbuf *pTemp = nullptr; pTemp = pObj -> xData(appName);if (pTemp != nullptr){// 删SEO靠我除名为appName的XdataacdbRegApp(appName);struct resbuf* pRb = acutBuildList(AcDb::kDxfRegAppName, appNameSEO靠我, RTNONE);pObj->upgradeOpen();pObj->setXData(pRb);acutRelRb(pRb);acutPrintf(TEXT("\nXdata deleted suSEO靠我ccessfully."));}else{//未找到需要删除的XdataacutPrintf(TEXT("\nNo Xdata found."));}acutRelRb(pTemp);pObj->clSEO靠我ose();}

还需要添加两个函数,printList()用于在命令窗口中打印Xdata信息;selectObject()用于提示用户选择实体。代码如下:

//在AutoCAD命令窗口中打印Xdata信息SEO靠我static void printList(struct resbuf* pRb){int rt, i;TCHAR buf[133];for (i = 0;pRb != NULL;i++, pRb =SEO靠我 pRb->rbnext) {if (pRb->restype < 1010) {rt = RTSTR;} else if (pRb->restype < 1040) {rt = RT3DPOINT;SEO靠我} else if (pRb->restype < 1060) {rt = RTREAL;} else if (pRb->restype < 1071) {rt = RTSHORT;} else ifSEO靠我 (pRb->restype == 1071) {rt = RTLONG;} else {rt = pRb->restype; }switch (rt) {case RTSHORT:if (pRb->SEO靠我restype == RTSHORT) {acutPrintf(_T("RTSHORT : %d\n"), pRb->resval.rint);} else {acutPrintf(_T("(%d .SEO靠我 %d)\n"), pRb->restype,pRb->resval.rint);};break;case RTREAL:if (pRb->restype == RTREAL) {acutPrintfSEO靠我(_T("RTREAL : %0.3f\n"),pRb->resval.rreal);} else {acutPrintf(_T("(%d . %0.3f)\n"), pRb->restype,pRbSEO靠我->resval.rreal);};break;case RTSTR:if (pRb->restype == RTSTR) {acutPrintf(_T("RTSTR : %s\n"),pRb->reSEO靠我sval.rstring);} else {acutPrintf(_T("(%d . \"%s\")\n"), pRb->restype,pRb->resval.rstring);};break;caSEO靠我se RT3DPOINT:if (pRb->restype == RT3DPOINT) {acutPrintf(_T("RT3DPOINT : %0.3f, %0.3f, %0.3f\n"),pRb-SEO靠我>resval.rpoint[X],pRb->resval.rpoint[Y],pRb->resval.rpoint[Z]);} else {acutPrintf(_T("(%d %0.3f %0.3SEO靠我f %0.3f)\n"),pRb->restype,pRb->resval.rpoint[X],pRb->resval.rpoint[Y],pRb->resval.rpoint[Z]);}break;SEO靠我case RTLONG:acutPrintf(_T("RTLONG : %dl\n"), pRb->resval.rlong);break;}if ((i == 23) && (pRb->rbnextSEO靠我 != NULL)){i = 0;acedGetString(0,_T("Press <ENTER> to continue..."), buf);}}}//提示用户选择实体static AcDbObSEO靠我ject* selectObject(AcDb::OpenMode openMode){int ss;ads_name en;ads_point pt;acedInitGet(RSG_OTHER, _SEO靠我T("Handle _Handle"));ss = acedEntSel(_T("\nSelect an Entity or enter")_T(" H to enter its handle: ")SEO靠我, en, pt);TCHAR handleStr[132];AcDbObjectId eId;switch (ss) {case RTNORM: break;case RTKWORD:if ((acSEO靠我edGetString(Adesk::kFalse,_T("Enter Valid Object Handle: "),handleStr) == RTNORM)&& (acdbHandEnt(hanSEO靠我dleStr, en) == RTNORM)){break;}default:acutPrintf(_T("Nothing Selected, Return Code==%d\n"),ss);retuSEO靠我rn NULL;}Acad::ErrorStatus retStat;retStat = acdbGetObjectId(eId, en);if (retStat != Acad::eOk) {acuSEO靠我tPrintf(_T("\nacdbGetObjectId failed"));acutPrintf(_T("\nen==(%lx,%lx), retStat==%d\n"),en[0], en[1]SEO靠我, eId);return NULL;}AcDbObject* obj;if ((retStat = acdbOpenObject(obj, eId, openMode))!= Acad::eOk){SEO靠我acutPrintf(_T("acdbOpenEntity failed: ename:(%lx,%lx),")_T(" mode:%d retStat:%d"), en[0], en[1],openSEO靠我Mode, retStat);return NULL;}return obj;}

3.代码效果

使用“addXdata”命令选择实体并添加扩展数据,“printXdata”命令在AutoCAD的命令窗口显SEO靠我示添加的扩展数据,“deleteXdata”命令删除扩展数据。如下图所示,使用Xdata向图中被选中直线追加了自定义数据。

4.源代码

源代码:xData

提取码:4bbm

参考文档

[1]:Autodesk SEO靠我ObjectARX for AutoCAD 2015: Developer Guide.
“SEO靠我”的新闻页面文章、图片、音频、视频等稿件均为自媒体人、第三方机构发布或转载。如稿件涉及版权等问题,请与 我们联系删除或处理,客服邮箱:html5sh@163.com,稿件内容仅为传递更多信息之目的,不代表本网观点,亦不代表本网站赞同 其观点或证实其内容的真实性。

网站备案号:浙ICP备17034767号-2