| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> 开发工具 -> ObjectARX2016 OPM面板全攻略 -> 正文阅读 |
|
[开发工具]ObjectARX2016 OPM面板全攻略 |
显示多项扩展属性? ? 利用OPM技术实现动态属性的方法在网上并不是很多,对于初步接触这个内容的人来说,还是存在很多困惑,首先创建的项目在初次编译时就会出现很多问题,诸如:
5>C:\ Program Files (x86)\Microsoft Visual Studio 11.0\VC\atlmfc\include\atlwinverapi.h(29): fatal error C1189: #error :? This file requires _WIN32_WINNT to be #defined at least to 0x0403. Value 0x0501 or higher is recommended.还有:如何把多个属性放置在同一个自定义的标签下面?如何在属性栏内显示一个值?而不是显示CAD内置的预定义的值。如何设置列表框中的多个选项?本文不再介绍ObjectARX2016环境安装及配置方法,这部分内容读者可参考win7下Visual Studio 2012 update4、AutoCAD 2016和二次开发插件ObjectARX2016环境安装及配置_Selenitic_G的博客-CSDN博客《win7下Visual Studio 2012 update4、AutoCAD 2016和二次开发插件ObjectARX2016环境安装及配置》。也不介绍动态属性(OPM)的实现方法与运行机制,这部分内容读者可参考Microsoft Word - Autocad 与动态属性.doc - 豆丁网《Microsoft Word - Autocad 与动态属性.doc?》。本文通过一个完整的实例,详细介绍在自定义的标签下显示CAD实体上的多项扩展属性。 1.项目需求? ? 在CAD图中有一个“地块”图层,这个图层中的所有实体均代表地籍宗地,实体类型包括AcDbPolyline、AcDbHatch两种,宗地上赋有扩展属性如下表:
? ? 在CAD特性面板中创建一个分类标签“土地权属信息”,在这个标签下添加宗地简码、权利人、证件编号、权属性质、土地用途、共有人、宗地面积、宗地备注等八项属性。其中1、2、3、6、7、8六项为文本框,4、5二项为列表框。 ? ? 第4项权属性质的列表框有9个选项,分别是:10/国有土地所有权、30/集体土地所有权、31/村民小组、32/村集体经济组织、33/乡集体经济组织、34/其它农民集体经济组织、40/集体土地使用权、其他。 ? ? 第5项土地用途的列表框有15个选项,分别是: 071/城镇住宅用地、072/农村宅基地、081/机关团体用地、082/新闻出版用地、083/科教用地、061/工业用地、062/采矿用地、063/仓储用地、094/宗教用地、095/殡葬用地、101/铁路用地、102/公路用地、103/街巷用地、104/农村道路、其他。 2.创建项目及项目属性设轩2.1 Visual Studio 2012设置Visual Studio 2012设置见下图: ? 2.2创建项目myOPM创建项目的流程如下: ? ? 3.3项目属性设置? 右键点击解决方案中的myOPM项目,在弹出框中点击属性,如下图,打开属性设置对话框。 ? 1常规: ? 2调试 ? 3 C++目录>包含目录 选中包含目录,点击右边的小箭头,点击编辑 ? 在弹出对话框中击文件夹按钮 ??? 点击右边的···按钮 ? 在弹出的文件对话框中选择ObjectARX按装目录下的inc文件夹,余类推。 4 C++目录>引用目录 ?5 C++目录>库目录 ? 6 C/C++>调试 ? 7 MIDL>输出 ? 9 "StdAfx.h"文件内容修改 ? 现在,用菜单生成>生成解决方案便成功了。 1>------ 已启动生成: 项目: myOPM, 配置: Debug x64 ------ 1>? general.cpp 1>???? 正在创建库 d:\Autodesk\ARX程序\myOPM\x64\/myOPM.lib 和对象 d:\Autodesk\ARX程序\myOPM\x64\/myOPM.exp 1>rxapi.lib(libinit.obj) : warning LNK4099: 未找到 PDB“rxapi_cl.pdb”(使用“rxapi.lib(libinit.obj)”或在“d:\Autodesk\ARX程序\myOPM\x64\rxapi_cl.pdb”中寻找);正在链接对象,如同没有调试信息一样
========== 生成: 成功 1 个,失败 0 个,最新 0 个,跳过 0 个 ========== 3.添加属性项3.1添加文本框属性项右键点击项目>添加>类。(如下图) ? 在上图所示的窗口中,只需要填写第一个编辑框,指定一个名称,其余编辑框将自动完成,指定名称后,按下一步。 ? 勾选Support for ICategorizeProperty(支持分类属性) ?DBX Classname,填写 AcDbEntiy,然后 Finish。 3.2关于OPM/Property Palette Interfaces Support选项Support for ICategorizeProperty??? 支持分类属性 No addtional support???? 没有额外的支持(常规分类下的文本框) Support for IDnamicEnumProperty??? 支持列表框属性 Support for IDynamicDialogProperty 支持对话框属性 ?
选择No addtional support
选择Support for IDnamicEnumProperty
选择Support for IDynamicDialogProperty
选择Support for ICategorizeProperty No addtional support
选择Support for ICategorizeProperty Support for IDnamicEnumProperty
选择Support for ICategorizeProperty Support for IDynamicDialogProperty 3.3关于DBX Classname的填写如果要限定显示动态属性的实体类型,只里填写相应的实体类型名,如:AcDbLine、AcDbText、AcDbPolyline等,在本例中,表示地籍宗地的实体包括AcDbPolyline、AcDbHatch两种,所以填写实体的基类名称AcDbEntity。 3.4修改代码自定义分类里创建的文本框属性项,.cpp文件中会自动生成14个函数,其中要修改6个函数: //----------------------------------------------------------------------------- //----- ZDXX1.cpp : Implementation of CZDXX1 //----------------------------------------------------------------------------- #include "StdAfx.h" #include "ZDXX1.h" //修改项1.属性项的名称 STDMETHODIMP CZDXX1::GetDisplayName (BSTR *pBstrName) { ??? if ( pBstrName == NULL ) ??????? return (E_POINTER) ; ??? *pBstrName =::SysAllocString (L"宗地简码") ; ??? return (S_OK) ; } //修改项2.属性项的描述 STDMETHODIMP CZDXX1::GetDescription (BSTR *pBstrName) { ??? if ( pBstrName == NULL ) ??????? return (E_POINTER) ; ??? *pBstrName =::SysAllocString (L"宗地的后5位编码") ; ??? return (S_OK) ; } //修改项3.属性值的数据类型 STDMETHODIMP CZDXX1::GetCurrentValueType (VARTYPE *pVarType) { ??? if ( pVarType == NULL ) ??????? return (E_POINTER) ; ??? //*pVarType =VT_I2 ;?? //2字节整形 short ??? //*pVarType =VT_I4 ;?? //4字节整形 int ??? //*pVarType =VT_R4 ;?? //4字节浮点数 float ??? //*pVarType =VT_R8 ;?? //8字节浮点数 double ??? *pVarType =VT_BSTR ;?? //字符型 string??? ??? //*pVarType =VT_BOOL ; //逻辑值 bool ??? //*pVarType =VT_USERDEFINED ;?? //枚举类型 ??? return (S_OK) ; ??? //个预定义属性取值: ??? //*pVarType =VT_PREDEFINED;?? return (E_NOTIMPL); } //修改项4.获取属性项的值 STDMETHODIMP CZDXX1::GetCurrentValueData (IUnknown *pUnk, VARIANT *pVarData) { ??? if ( pUnk == NULL ) ??????? return (E_INVALIDARG) ; ??? if ( pVarData == NULL ) ??????? return (E_POINTER) ; ??? ::VariantInit (pVarData) ; ??? V_VT(pVarData) =VT_BSTR ;??? //定义控件的类型 string ??? LONG_PTR oldID; ??? ((IAcadObject *)pUnk)->get_ObjectID(&oldID);?? //利用 pUnk 获取当前选中实体对象的 ID ??? AcDbObjectId objID; ??? objID.setFromOldId(oldID); ??? //利用 ID 以读方式打开实体 ??? AcDbEntityPointer pEntPtr( objID, AcDb::kForRead ); ??? Acad::ErrorStatus es = pEntPtr.openStatus(); ??? if ( es != Acad::eOk)?? {?? return E_FAIL;? }??? //打开实体失败,返回 非 ??? //从实体中获取XData ??? vector<CString> OutDatas =GetDatas(appName,pEntPtr); ??? pEntPtr->close();??????????????? //关闭实体 ??? if(实体图层名 ==TEXT("地块") && OutDatas.size()==9)? //如果实体的图层="地块"、扩展属性的项数=9 ??? {?? //控件的值=扩展属性第二项(第一项的索引为0) ??????? pVarData->bstrVal = ::SysAllocString( OutDatas[1] ); ??????? return (S_OK) ; ??? } ??? else {return E_FAIL;} } //修改项5.修改属性项的内容 STDMETHODIMP CZDXX1::SetCurrentValueData (IUnknown *pUnk, const VARIANT varData) { ??? if ( pUnk == NULL ) ??????? return (E_INVALIDARG) ; ??? LONG_PTR oldID; ??? ((IAcadObject *)pUnk)->get_ObjectID(&oldID);???? //利用 pUnk 获取当前选中实体对象的 ID ??? AcDbObjectId objID; ??? objID.setFromOldId(oldID);?? ??? //根据Id来锁定文档 ??? AcAxDocLock docLock( objID, AcAxDocLock::kNormal ); ??? if ( docLock.lockStatus() != Acad::eOk ){return E_FAIL; }? //锁定文档失败,返回 非 ??? AcDbEntityPointer pEntPtr( objID, AcDb::kForWrite );?????? //利用 ID 以写方式打开对象 ??? Acad::ErrorStatus es = pEntPtr.openStatus(); ??? if ( es != Acad::eOk )? {?? return E_FAIL;? }??????????? //打开实体失败,返回 非 ??? vector<CString> OutDatas =GetDatas(appName,pEntPtr);??? //从实体中获取XData ??? if(实体图层名 ==TEXT("地块") && OutDatas.size()==9)????? //如果实体的图层="地块"、扩展属性的项数=9 ??? { ??????? bstr_t newVal( varData.bstrVal );?????????????? //获取文本框的值 ??? ??? OutDatas[1] = _tcsdup( (ACHAR*)newVal );??????? //利用文本框的值修改扩展属性的第2项 ??????? ModifyXData(pEntPtr,OutDatas);????????????????? //修改实体的扩展属性(关闭实体) ??? ??? return (S_OK) ;???? ??? } ??? else ??? { ??????? pEntPtr->close();??????????????? //关闭实体 ??????? return E_FAIL; ??? }?? } //修改项6.设定分类属性的标签名 STDMETHODIMP CZDXX1::GetCategoryName (PROPCAT propcat, LCID lcid, BSTR *pBstrName) { ??? if ( pBstrName == NULL ) ??????? return (E_POINTER) ; ??? if ( propcat != 0 ) ??????? return (E_INVALIDARG) ; ??? *pBstrName =::SysAllocString (L"土地权属信息") ; ??? return (S_OK) ; } 3.5配套代码本例要自定义分类<土地权属信息>下创建8个属性项,每个属性项都要获取和修改实体的扩展属性,其中二个列表框属性还要多次用到列表框条目,为了简化程序代码,需要做一些准备工作: 1.在StdAfx.h文件中声明几个全局变量和函数: //- Declare it as an extern here so that it becomes available in all modules extern AcApDataManager<CDocData> DocVars ; extern CString 实体图层名;???? //实体图层名 extern CString appName;??????? //注册应用程序名 extern CString 权属性质[9];??? //权属性质列表框项目 extern CString 土地用途[15];?? //土地用途列表框项目 #pragma pack (pop) using namespace std; using std::string; ??? // 提示用户选择某个类型的实体,注意:调用者必须关闭实体 bool PromptSelectEntity(const TCHAR* prompt, AcRxClass* classDesc, AcDbEntity *&pEnt, AcGePoint3d &pickPoint, ??? ?? bool bOpenForWrite = true); bool PromptSelectEntity(const TCHAR* prompt, const std::vector<AcRxClass*> &classDescs, AcDbEntity *&pEnt, ??? ?? AcGePoint3d &pickPoint, bool bOpenForWrite = true); vector<CString> GetDatas(CString appName,AcDbEntity *pEnt);???? //获取实体的扩展属性 void ModifyXData(AcDbEntity *pEnt,vector<CString> infoDatas);?? //修改实体的扩展属性 2.在StdAfx.cpp文件中定义几个全局变量和函数: #include "StdAfx.h" using namespace std; using std::string; CString 实体图层名;???? //实体图层名 CString appName;??????? //注册应用程序名 CString 权属性质[9];??? //权属性质列表框项目 CString 土地用途[15];?? //土地用途列表框项目 bool PromptSelectEntity(const TCHAR* prompt, AcRxClass* classDesc, AcDbEntity *&pEnt, ??? AcGePoint3d &pickPoint, bool bOpenForWrite /*= true*/) { ??? std::vector<AcRxClass*> descs; ??? descs.push_back(classDesc); ??? return PromptSelectEntity(prompt, descs, pEnt, pickPoint, bOpenForWrite); } bool PromptSelectEntity(const TCHAR* prompt, const std::vector<AcRxClass*> &classDescs, AcDbEntity *&pEnt, ??? AcGePoint3d &pickPoint, bool bOpenForWrite/*= true*/ ) { ??? ads_name ename; RETRY: ??? if (acedEntSel(prompt, ename, asDblArray(pickPoint)) != RTNORM) ??? { ??????? pEnt = NULL; ??????? return false; ??? } ??? AcDbObjectId entId; ??? acdbGetObjectId(entId, ename); ??? // 判断选择的实体是否是指定类型的实体 ??? Acad::ErrorStatus es; ??? if (bOpenForWrite) ??? { ??????? es = acdbOpenObject(pEnt, entId, AcDb::kForWrite); ??? } ??? else ??? { ??????? es = acdbOpenObject(pEnt, entId, AcDb::kForRead); ??? } ??? assert(es == Acad::eOk); ??? bool bRet = false; ??? for (int i = 0; i < (int)classDescs.size(); i++) ??? { ??????? if (pEnt->isKindOf(classDescs[i])) ??????? { ??????????? bRet = true; ??????????? break; ??????? } ??? } ??? if (bRet) ??? { ??????? return true; ??? } ??? else ??? { ??????? pEnt->close(); ??????? acutPrintf(TEXT("\n选择的实体类型不合要求, 请再次选择...")); ??????? goto RETRY; ??? } } //获取实体的扩展属性 vector<CString> GetDatas(CString appName,AcDbEntity *pEnt) { ??????? TCHAR *szLayerName=pEnt->layer();?????????? ??????? 实体图层名.Format(_T("%s"),szLayerName);?? //给全局变量(实体图层名)赋值,用于判断是否显示属性 ??? ??? vector<CString> outInfos;????????? //字符串数组 ??????? struct resbuf *pRb = pEnt->xData(appName);? //获取实体的扩展属性 ??? ??? struct resbuf *pTemp = pRb;?? //使用临时的结果缓冲区指针进行遍历pRb ??? ??? for (int i = 0;pTemp != NULL;i++, pTemp = pTemp->rbnext) ??? ??? { ??????????? CString str; ??????????? switch(pTemp->restype) ??????????? { ??????????? ??? case 1001:? //注册应用程译序名 ??????????? ??? case 1000:? //字符串类型属性项的文本 ?????????????????? ?outInfos.push_back(pTemp->resval.rstring);???????????????????? ?????????????????? ?break; ??????????????? case 1040:? //实数类型属性项的实数转为文本 ?????????????????? ?str.Format(TEXT("%.2f"), pTemp->resval.rreal); ?????????????????? ?outInfos.push_back(str);?? ?????????????????? ?break; ??????????????? default:break; ??????????? }?????? ??? ??? } ??? ??? acutRelRb(pRb);?? //释放pRb??????????? ??????? return outInfos; ??? } //修改实体的扩展属性 void ModifyXData(AcDbEntity *pEnt,vector<CString> infoDatas) { ??? // 提示用户选择所要添加扩展数据的图形对象?? ??? acdbRegApp(infoDatas[0]);??? //注册应用程序名称 ??? double a=_ttof(infoDatas[7]); ??? //创建结果缓冲区链表 ??? struct resbuf* rb = acutBuildList(AcDb::kDxfRegAppName, infoDatas[0], ??? ??????? AcDb::kDxfXdAsciiString, infoDatas[1],? //宗地简码 ??????? ??? AcDb::kDxfXdAsciiString, infoDatas[2],? //权利人 ??????? ??? AcDb::kDxfXdAsciiString, infoDatas[3],? //证件编号 ??????????? AcDb::kDxfXdAsciiString, infoDatas[4],? //权属性质 ??????????? AcDb::kDxfXdAsciiString, infoDatas[5],? //土地用途 ??????????? AcDb::kDxfXdAsciiString, infoDatas[6],? //共有人 ??????????? AcDb::kDxfXdReal,a,???????????????????? //宗地面积 ??????????? AcDb::kDxfXdAsciiString, infoDatas[8],? //宗地备注???????? ??????????? RTNONE); ??? pEnt->setXData(rb);?? //为选择的实体添加扩展数据 ??? acutRelRb(rb);??????? //释放 rb ??? pEnt->close();??????? //关闭实体 } 3.的acrxEntryPoint.cpp文件的On_kInitAppMsg初始化函数中添加初始化代码: public: ??? CmyOPMApp () : AcRxArxApp () {} ??? virtual AcRx::AppRetCode On_kInitAppMsg (void *pkt) { ??????? AcRx::AppRetCode retCode =AcRxArxApp::On_kInitAppMsg (pkt) ; ??????? appName=TEXT("TDQSXX");?? //提取扩展属性的注册应用程序名 ??????? //土地用途列表框选项初始化 ??????? 土地用途[0]=(TEXT("071/城镇住宅用地")); ??? ??? 土地用途[1]=(TEXT("072/农村宅基地")); ??? ??? 土地用途[2]=(TEXT("081/机关团体用地")); ??? ??? 土地用途[3]=(TEXT("082/新闻出版用地")); ??? ??? 土地用途[4]=(TEXT("083/科教用地")); ??????? 土地用途[5]=(TEXT("061/工业用地")); ??????? 土地用途[6]=(TEXT("062/采矿用地")); ??????? 土地用途[7]=(TEXT("063/仓储用地")); ??????? 土地用途[8]=(TEXT("094/宗教用地")); ??????? 土地用途[9]=(TEXT("095/殡葬用地")); ??????? 土地用途[10]=(TEXT("101/铁路用地")); ??????? 土地用途[11]=(TEXT("102/公路用地")); ??????? 土地用途[12]=(TEXT("103/街巷用地")); ??????? 土地用途[13]=(TEXT("104/农村道路")); ??????? 土地用途[14]=(TEXT("其他")); ??????? //权属性质列表框选项初始化 ??????? 权属性质[0]=(TEXT("10/国有土地所有权")); ??????? 权属性质[1]=(TEXT("20/国有土地使用权")); ??????? 权属性质[2]=(TEXT("30/集体土地所有权")); ??????? 权属性质[3]=(TEXT("31/村民小组")); ??????? 权属性质[4]=(TEXT("32/村集体经济组织")); ??????? 权属性质[5]=(TEXT("33/乡集体经济组织")); ??????? 权属性质[6]=(TEXT("34/其它农民集体经济组织")); ??????? 权属性质[7]=(TEXT("40/集体土地使用权")); ??????? 权属性质[8]=(TEXT("其他")); ??????? return (retCode) ; ?? } 4.为了调试程序的正确性,在acrxEntryPoint.cpp文件添加创建、查看和删除扩展属性的函数: static void GroupAddXData() { ??????? // 提示用户选择所要添加扩展数据的图形对象 ??????? AcDbEntity *pEnt = NULL; ??????? AcGePoint3d pickPoint; ??????? if (PromptSelectEntity(TEXT("\n选择所要添加的扩展数据的实体:"), ??????????? AcDbEntity::desc(),pEnt,pickPoint)) ??????? {?????????? ??????????? //注册应用程序名称 ??????????? acdbRegApp(appName); ??????????? //创建结果缓冲区链表 ??????????? struct resbuf* rb = acutBuildList(AcDb::kDxfRegAppName, appName, ??????????????? //应用程序名称 ??????????????? AcDb::kDxfXdAsciiString, TEXT("00159"),?????????????? //宗地简码 ??????????????? AcDb::kDxfXdAsciiString, TEXT("刘胜利"),????????????? //权利人 ??????????????? AcDb::kDxfXdAsciiString, TEXT("320102196906182735"),? //证件编号 ??????????????? AcDb::kDxfXdAsciiString, TEXT("31/村民小组"),???????? //权属性质 ??????????????? AcDb::kDxfXdAsciiString, TEXT("083/科教用地"),??????? //土地用途 ??????????????? AcDb::kDxfXdAsciiString, TEXT("刘小兰"),????????????? //共有人 ??????????????? AcDb::kDxfXdReal,186.27,????????????????????????????? //宗地面积 ??????????????? AcDb::kDxfXdAsciiString, TEXT("宗地备注"),??????????? //宗地备注? ??????????????? RTNONE); ??????????? //为选择的实体添加扩展数据 ??????????? pEnt->setXData(rb); ??????????? acutRelRb(rb); ??????????? acutPrintf(TEXT("\n成功为实体添加了扩展数据.")); ??????????? pEnt->close(); ??????? } ??? } ??? static void GroupViewXData() { ??????? CString DataTitle[9];?? //属性标题 ??????? //属性标题初始化 ??????? DataTitle[0]=TEXT("注册程序名"); ??????? DataTitle[1]=TEXT("宗地简码"); ??????? DataTitle[2]=TEXT("权利人"); ??????? DataTitle[3]=TEXT("证件编号"); ??????? DataTitle[4]=TEXT("权属性质"); ??????? DataTitle[5]=TEXT("土地用途"); ??????? DataTitle[6]=TEXT("共有人"); ??????? DataTitle[7]=TEXT("宗地面积"); ??????? DataTitle[8]=TEXT("宗地备注"); ??????? //提示用户选择所要查看扩展数据的图形对象 ??????? AcDbEntity *pEnt = NULL; ??????? AcGePoint3d pickPoint; ??????? if (PromptSelectEntity(TEXT("\n选择要查看扩展数据的实体:"), AcDbEntity::desc(), pEnt, pickPoint)) ??????? { ??????????? //struct resbuf *pRb = pEnt->xData(appName); ??????????? vector<CString> OutDatas =GetDatas(appName,pEnt);?? //从实体中获取XData ??????????? pEnt->close();??????????????? //关闭实体??? ??????? ??????????? for (int i = 0;i<OutDatas.size();i++) ??? ??????? { ??????????????? acutPrintf(TEXT("\n") +DataTitle[i]+TEXT("=")+OutDatas[i]); ??????????? ??? ??????? } ??????? } ??? } ??? //注册新命令DeleteXData,用于从实体中删除特定的扩展数据 ??? static void GroupDeleteXData() { ??????? //提示用户选择所要删除扩展数据的图形对象 ??????? AcDbEntity *pEnt = NULL; ??????? AcGePoint3d pickPoint; ??????? if (PromptSelectEntity(TEXT("\n选择所要删除扩展数据的实体:"), ??????????? AcDbEntity::desc(),pEnt,pickPoint)) ??????? {?????????? ??????????? acdbRegApp(appName);? //注册应用程序名称 ??????????? //利用扩展属性的应用程序名,称创建结果缓冲区链表 ??????????? struct resbuf *rb = acutBuildList(AcDb::kDxfRegAppName, appName, RTNONE); ??????????? //把内容为空的结果缓冲区链表赋值给实体,就是删除实体的扩展数据 ??????????? pEnt->setXData(rb); ??????????? acutRelRb(rb);???? //释放pRb ??????????? acutPrintf(TEXT("\n成功为实体删除了扩展数据.")); ??????????? pEnt->close(); ??????? } ?? } 5. 在acrxEntryPoint.cpp文件的底部注册三个命令: IMPLEMENT_ARX_ENTRYPOINT(CmyOPMApp) ACED_ARXCOMMAND_ENTRY_AUTO(CmyOPMApp, Group, AddXData, AddXData, ACRX_CMD_MODAL, NULL) ACED_ARXCOMMAND_ENTRY_AUTO(CmyOPMApp, Group, ViewXData, ViewXData, ACRX_CMD_MODAL, NULL) ACED_ARXCOMMAND_ENTRY_AUTO(CmyOPMApp, Group, DeleteXData, DeleteXData, ACRX_CMD_MODAL, NULL) 我们编译这个工程,然后加载到 AutoCAD 中。在 AutoCAD 创建一个图层“地块”,画一条封闭的多段线,用AddXData命令为多段线创建扩展属性,然后选中,并打开特性窗口(Ctrl + 1),就可以看到这个自已的动态属性了。 3.6添加列表框属性项(枚举属性)? 枚举属性共生成17个函数,其中有9个函数需修改: //----------------------------------------------------------------------------- //----- ZDXX4.cpp : Implementation of CZDXX4 //----------------------------------------------------------------------------- //修改项1.设定属性项的名称 STDMETHODIMP CZDXX4::GetDisplayName (BSTR *pBstrName) { ??? if ( pBstrName == NULL ) ??????? return (E_POINTER) ; ??? *pBstrName =::SysAllocString (L"权属性质") ; ??? return (S_OK) ; } //修改项2.属性项的提示描述文本 STDMETHODIMP CZDXX4::GetDescription (BSTR *pBstrName) { ??? if ( pBstrName == NULL ) ??????? return (E_POINTER) ; ??? *pBstrName =::SysAllocString (L"指定本宗地的土地权属性质") ; ??? return (S_OK) ; } //修改项3.属性值的数据类型 STDMETHODIMP CZDXX4::GetCurrentValueName (BSTR *pBstrName) { ??? if ( pBstrName == NULL ) ??????? return (E_POINTER) ; ??? return (E_NOTIMPL) ; ??? //当GetCurrentValueType函数定义的类型为预定义属性时,*pBstrName取值如下: ??? //对话框类型 ??? //*pBstrName =::SysAllocString (L"ACAD_COLOR") ;???? //内置的颜色对话框 ??? //*pBstrName =::SysAllocString (L"ACAD_LAYER") ;???? //内置的图层对话框 ??? //*pBstrName =::SysAllocString (L"ACAD_DISTANCE") ;? //内置的距离对话框 ??? //*pBstrName =::SysAllocString (L"ACAD_ANGLE") ;???? //内置的角度对话框 ??? //*pBstrName =::SysAllocString (L"ACAD_NOUNITS") ;?? //无单位的属性值 ??? //*pBstrName =::SysAllocString (L"ACAD_LWEIGHT") ;?? //内置的线宽对话框 } //修改项4.获取属性项的值 STDMETHODIMP CZDXX4::GetCurrentValueData (IUnknown *pUnk, VARIANT *pVarData) { ??? if ( pUnk == NULL ) ??????? return (E_INVALIDARG) ; ??? if ( pVarData == NULL ) ??????? return (E_POINTER) ; ??? //变体内容的初始化,??? ??? ::VariantInit( pVarData ); ??? V_VT( pVarData ) = VT_I4; //LONG型 ??? LONG_PTR oldID; ??? ((IAcadObject *)pUnk)->get_ObjectID(&oldID);?? //利用 pUnk 获取当前选中实体对象的 ID ??? AcDbObjectId objID; ??? objID.setFromOldId(oldID);? ??? AcDbEntityPointer pEntPtr( objID, AcDb::kForRead );?? //利用 ID 以读方式打开实体 ??? Acad::ErrorStatus es = pEntPtr.openStatus(); ??? if ( es != Acad::eOk)?? {?? return E_FAIL;? }???????? //打开实体失败,返回 非 ??? //从实体中获取XData ??? vector<CString> OutDatas =GetDatas( appName,pEntPtr);?? ??? pEntPtr->close();???? //关闭实体 ??? if(实体图层名 ==TEXT("地块") && OutDatas.size()==9)? //如果实体的图层="地块"、扩展属性的项数=9 ??? {?? //控件的值=扩展属性第二项(第一项的索引为0) ??????? bstr_t pBstr( OutDatas[4] );????? //扩展属性的第4项 ??????? pVarData->bstrVal = pBstr.copy(); ??????? long 列表框当前选项的编号=8; ??????? for(int i=0;i<8;i++) ??????? { ??????????? if(权属性质[i]==OutDatas[4])? { 列表框当前选项的编号=i; } ??????? } ??????? V_I4( pVarData ) =(LONG) 列表框当前选项的编号;??? ??? ??? return (S_OK) ; ??? } ??? return E_FAIL;? } //修改项5.修改属性项的值(从pUnk中取得ID打开实体;varData.lVal中的列表框当前项的索引值取得新的属性值,更改实体) STDMETHODIMP CZDXX4::SetCurrentValueData (IUnknown *pUnk, const VARIANT varData) { ??? //变体数据类型 VARIANT varData 其中: ??? //???????????? varData.vt 是数据类型; ??? //???????????? varData.lVal 是数据的值,本例中varData.lVal 是列表框当前项的索引值 ??? if ( pUnk == NULL ) ??????? return (E_INVALIDARG) ; ??? long i=varData.lVal;??? //修改了组合框的当前项,现在的当前项的索引值=i ??? LONG_PTR oldID; ??? ((IAcadObject *)pUnk)->get_ObjectID(&oldID); ??? AcDbObjectId objID; ??? objID.setFromOldId(oldID); ??? //根据Id来锁定文档 ??? AcAxDocLock docLock( objID, AcAxDocLock::kNormal ); ??? if ( docLock.lockStatus() != Acad::eOk ){return E_FAIL; } ??? //利用 ID 以写方式打开对象 ??? AcDbEntityPointer pEntPtr( objID, AcDb::kForWrite ); ??? Acad::ErrorStatus es = pEntPtr.openStatus(); ??? if ( es != Acad::eOk )? {return E_FAIL; } ??? //从实体中获取XData ??? vector<CString> OutDatas =GetDatas(appName,pEntPtr);??? //从实体中获取XData ??? if(实体图层名 ==TEXT("地块") && OutDatas.size()==9)????? //如果实体的图层="地块"、扩展属性的项数=9 ??? { ??????? OutDatas[4]=权属性质[i];????????????????? //当前组合框的值(i项)替换实体的属性值 ??????? ModifyXData(pEntPtr,OutDatas);??????????? //修改实体的扩展属性(关闭实体) ??? ??? m_pNotify->OnChanged ( pUnk ) ;?????????? //在这里通知特性窗口更新组合框的值 ??? ??? return (S_OK) ;???? ??? } ??? else ??? { ??????? pEntPtr->close();??????????????? //关闭实体 ??????? return E_FAIL; ??? }?????????? } //修改项6.设定分类属性的标签名 STDMETHODIMP CZDXX4::GetCategoryName (PROPCAT propcat, LCID lcid, BSTR *pBstrName) { ??? if ( pBstrName == NULL ) ??????? return (E_POINTER) ; ??? if ( propcat != 0 ) ??????? return (E_INVALIDARG) ; ??? *pBstrName =::SysAllocString (L"土地权属信息") ; ??? return (S_OK) ; } //----- IDynamicEnumProperty //枚举属性修改项1.pNumValues 为该枚举属性的个数,必须为正整数 STDMETHODIMP CZDXX4::GetNumPropertyValues (LONG *pNumValues) { ??? if ( pNumValues == NULL ) ??????? return (E_POINTER) ; ??? *pNumValues =9 ; ??? return (S_OK) ; } //枚举属性修改项2.按 index 的次序设置在 comboBox 内显示的条目文本 STDMETHODIMP CZDXX4::GetPropValueName (LONG index, BSTR *pBstrValueName) { ??? if ( pBstrValueName == NULL ) ??????? return (E_POINTER) ; ??? //根据index以次添加组合列表框的条目,内容在acrxEntryPoint.cpp>On_kInitAppMsg中初始化 ??? bstr_t bStr( 权属性质[index] ); ??? *pBstrValueName = bStr.copy();?? ??? return (S_OK) ; } //枚举属性修改项3.按 index 的次序显示在 comboBox 内添加条目 STDMETHODIMP CZDXX4::GetPropValueData (LONG index, VARIANT* pValue) { ??? if ( pValue == NULL ) ??????? return (E_POINTER) ; ??? ::VariantInit (pValue) ; ??? V_VT(pValue) =VT_I4 ;?? ??? V_I4(pValue) = (LONG) index;?? //获取当前选项的索引值 ??? return (S_OK) ; } 按同样的方法添加第5个属性项:参考代码中的说明完成代码的修改。 按3.1同样的方法添加第2、第3、第6、第7、第8等5个属性项,参考代码中的说明完成代码的修改。 我们编译这个工程,然后加载到 AutoCAD 中。在 AutoCAD 创建一个图层“地块”,画一条封闭的多段线,用AddXData命令为多段线创建扩展属性,然后选中,并打开特性窗口(Ctrl + 1),就可以看到完整的动态属性了。 ? 3.7属性项的显示顺序属性项的显示顺序是根据属性文件(类)的名称按序进行排列,为了能按你的要求次序显示属性项,应预先设计好所有属性文件(类)的名称、类型、连接实体扩展属性的序号等信息,逐个添加属性项。本例中8个属性项的类名分别为CZDXX1;CZDXX2;CZDXX3;-----CZDXX8。 |
|
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 | -2024/11/26 5:33:47- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |