IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: 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技术实现动态属性的方法在网上并不是很多,对于初步接触这个内容的人来说,还是存在很多困惑,首先创建的项目在初次编译时就会出现很多问题,诸如:

  1. 1>TRACKER : 错误 TRK0005: 未能找到:“midl.exe”。系统找不到指定的文件;
  2. midl : command line error MIDL1012: argument illegal for switch / header
  3. 2>midl : command line error MIDL1024: Errors on command line—Aborting
  4. featuresOPM.rc(102): error RC2135: file not found: asdkfeaturesOPM.tlb

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两种,宗地上赋有扩展属性如下表:

DXF

值(例)

数据类型

控件类型

说明

1001

TDQSXX

注册程序名

1000

00159

String

文本框

宗地简码

1000

刘胜利

String

文本框

权利人

1000

320102196906182735

String

文本框

证件编号

1000

31/村民小组

String

列表框

权属性质

1000

063/教育用地

String

列表框

土地用途

1000

刘小兰

String

文本框

共有人

1000

186.27

String

文本框

宗地面积

1000

宗地备注

String

文本框

宗地备注

? ? 在CAD特性面板中创建一个分类标签“土地权属信息”,在这个标签下添加宗地简码、权利人、证件编号、权属性质、土地用途、共有人、宗地面积、宗地备注等八项属性。其中123678六项为文本框,45二项为列表框。

? ? 第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. myOPM.vcxproj -> d:\Autodesk\ARX程序\myOPM\x64\myOPM.ARX

========== 生成: 成功 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 支持对话框属性

?

  1. 要在常规分类里创建一个文本框属性项,如CAD特性面板中的<透明度>

选择No addtional support

  1. 要在常规分类里创建一个列表框属性项,如CAD特性面板中的<图层>

选择Support for IDnamicEnumProperty

  1. 要在常规分类里创建一个对话框属性项,如CAD特性面板中的<颜色>

选择Support for IDynamicDialogProperty

  1. ?要在自定义分类里创建一个文本框属性项,如下图中的<宗地简码>

选择Support for ICategorizeProperty

No addtional support

  1. 要在自定义分类里创建一个列表框属性项,如下图中的<权属性质>

选择Support for ICategorizeProperty

Support for IDnamicEnumProperty

  1. 要在自定义分类里创建一个对话框属性项(本例未包含)

选择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。

  开发工具 最新文章
Postman接口测试之Mock快速入门
ASCII码空格替换查表_最全ASCII码对照表0-2
如何使用 ssh 建立 socks 代理
Typora配合PicGo阿里云图床配置
SoapUI、Jmeter、Postman三种接口测试工具的
github用相对路径显示图片_GitHub 中 readm
Windows编译g2o及其g2o viewer
解决jupyter notebook无法连接/ jupyter连接
Git恢复到之前版本
VScode常用快捷键
上一篇文章      下一篇文章      查看所有文章
加:2022-04-15 00:19:38  更:2022-04-15 00:20:20 
 
开发: 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-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码