如图所示:我才用代码读取 某一个参数cell 的 属性(参数),发现可以读取 Genneral、Geometry、Raw Data、等板块的信息,但是 Variables 板块的信息 没有读取到, 请问大神 是什么原因?
具体代码如下:
bool doubleClickCallbackFunc2(DisplayPathCP path) { WString filename; ElementRefP eP = path->GetHeadElem(); DgnModelRefP currFileP = mdlDisplayPath_getPathRoot(path); MSElementDescrP elDescr; mdlElmdscr_getByElemRef(&elDescr, eP, currFileP, FALSE, NULL); EditElementHandle eeh(elDescr, FALSE, TRUE , 0); FindInstancesScopePtr scope = FindInstancesScope::CreateScope(eeh, FindInstancesScopeOption(DgnECHostType::All)); ECQueryPtr query = ECQuery::CreateQuery(ECQUERY_PROCESS_SearchAllClasses); DgnECInstanceIterable iterable = Bentley::DgnPlatform::DgnECManager::GetManager().FindInstances(*scope, *query); DgnECInstancePtr instance = *((iterable.begin())); ECN::ECClassCR instanceClass = instance->GetClass(); ECPropertyIterable properties = instanceClass.GetProperties(); for (ECPropertyIterable::const_iterator it0 = properties.begin(); it0 != properties.end(); ++it0) { ECValue v; ECPropertyCP pProp = (*it0); WString ddeea = pProp->GetTypeName(); WString ecpName = pProp->GetName(); WString ecpDesc = pProp->GetDescription(); WString ecpVVV = pProp->GetInvariantDescription(); WString ersV = pProp->GetDisplayLabel(); mdlDialog_dmsgsPrint(WPrintfString(L"名称:%s 类型:%s 内容:%s", ecpName, ddeea, ersV)); } filename.Sprintf(L"D:\\1.xml"); instance->WriteToXmlFile(filename.data(), true, true); instance->WriteChanges(); mdlDialog_dmsgsPrint(WPrintfString(L"名称:%s 内容:%s ", L"长度:", L"123" )); return true; }
这个帖子里边的方法您试过没有:https://communities.bentley.com/communities/other_communities/chinafirst/f/microstation-projectwise/143095/c-ce
测试过了,我编写的demo 就是根据 上面的代码 进行的修改,但是 还死活不能获取 图中 标红部分的 参数信息,也就是 我们设置的尺寸信息 或 与约束相关的信息,也就是 edit item 部分的变量 ,遍历不出来。
Bentley 二次开发小白一枚
测试过了,我编写的demo 就是根据 上面的代码 进行的修改,但仍旧是不能获取 如图所使部分的信息,也就是 我们设置的尺寸信息 或 与约束相关的信息,也就是 edit item 部分的变量 ,遍历不出来。
iterable是一个集合,您代码里边只是访问了这个集合的第一项,我给您看的帖子里边正确答案贴出来的代码里边包含多层循环。最外层迭代了iterable,第二层迭代等同于您上边代码中的循环。
老师好,我经过测试后 发现 外层指的是 我途中 1和2 两个 部分(也就是您说的“ iterable是一个集合 ”),但是 我只需要 1(project)的属性信息。 所以 我去掉了 那部分 循环。当然这个是我的理解 ,老师您看看是不是 我理解的有问题。
另外,辛苦老师 帮我 看一下 如何获取 project 这个标签下的 variables 的 信息。 多谢老师的指正!!!
理解有误,一个元素上可以有多个ECInstance,FindInstances就是获取了元素上所有ECInstace的集合。您需要迭代这个集合,而您上边的代码只是访问了第一个ECInstance。
老师 ,你看一下 ,我的元素 下面有一个 test1,test1下由两个 items,分别是 Project 和 test1, 那这两个 items 是不是就是您说的 ECInstance ?
这个是您自定义的ECClass类型或者ItemType(基于EC)的属性,往元素添加一个ECInstance确实会在这里多出一项。但是不能理解为这就是ECInstance。Properties窗口里边看到的属性都是基于EC的,都是通过ECInstance附着到元素上的。EC机制比较复杂,是用一种往元素上添加自定义属性的公用格式,通过这种格式添加到元素上的属性,其他人即使没有你的程序也能读取到你通过EC添加到自定义属性。添加自定义属性时,首先你需要定义数据的类型ECClass,类似于你编程时,定义的struct或者class,结构体只是一种类型,往元素上添加时,你要用这个ECClass创建一个ECInstance。就好比你在编程时用到某个struct或者class,要实例化一个对象实例。之后把这个ECInstance附加到元素上即可。而ECSchema跟ECClass的关系类似于c++中命名空间跟struct或者class的关系。
老师好!
针对您的回复,还是不太明白,见谅!!
另外,上面您的方法 可以读取到 哪些属性信息吗?或者 怎么样才能可以读出来那些信息呢?
请老师 指点!!!!!
老师 我这里 还有一部分代码,可以完全替代上面我编写 的那段代码,可以检索到 我想要 检索的 变量名称 类型等 信息。
但是 我 看不出来 他们的区别 ,您看一下 ,帮我解读一下 ,从业务逻辑 和 结构上 ,谢谢老师 !!!!
ElementRefP eP = path->GetHeadElem(); DgnModelRefP currFileP = mdlDisplayPath_getPathRoot(path); int itype=elementRef_getElemType(eP); MSElementDescrP elDescr; mdlElmdscr_getByElemRef(&elDescr, eP, currFileP, FALSE, NULL); ParametricCellDefHandler& defHdler = ParametricCellDefHandler::GetInstance(); BeFileName activeCellLibraryName; DgnFileP pLibObj; WChar wCellName[MAX_CELLNAME_LENGTH]; DgnFileP pDgnFile = ISessionMgr::GetActiveDgnFile(); int iStatus; DgnIndexIteratorP pDgnIndexIterator; DgnIndexItemP pDgnIndexItem; ElementRefP ElDefRef=NULL; DgnPlatform::DgnModelType ctype; bool is3D; mdlCell_getLibraryName(activeCellLibraryName);//此处是读取激活的存放cell目录或.cel文件 iStatus = mdlCell_getLibraryObject(&pLibObj, activeCellLibraryName.c_str(), true); pDgnIndexIterator = mdlModelIterator_create(pLibObj); mdlModelIterator_setAcceptCellsOnly(pDgnIndexIterator, true); /*下面是一个遍历模板库(cell文件)中模型的功能,要求改模板库只能有一个模型,也就是说找到一个模型后即可停止遍历 ,并获取改模型的名称和其他信息。然后从该模型中获取cell的参数化信息。这里有一个非常重要的前提,就是需要明确 一个模板库必须且只能有一个模型,每个模型中只能有一个cell的强烈要求和限制。通过这个规则来进行约束。 因此目前这个遍历模板库中模型的算法,也就丧失了意义,因为根本不存在遍历的条件或基础。 */ while (pDgnIndexItem = mdlModelIterator_getNext(pDgnIndexIterator) ) { mdlModelItem_getName(pDgnIndexItem, wCellName, MAX_CELLNAME_LENGTH); mdlModelItem_getData(pDgnIndexItem, &ctype, &is3D, NULL, NULL, NULL); ElDefRef = defHdler.FindByName((WCharCP)wCellName, *pDgnFile); if (ElDefRef != nullptr) break; } /*找到需要的模型后,查找该模型下参数化的单元,因为有前提条件和要求,所以可直接查找该模型下的参数化信息。*/ ParametricCellDefinitionPtr PaDef = defHdler.GetCellDefinition(ElementHandle(ElDefRef) ); //ParametricCellInfoPtr PaInfo = ParametricCellInfo::Create(status, *PaDef, setName, *pDgnModel); IParameterDefinitionsPtr paramDefs = PaDef->GetParameterDefinitions(); VirtualCollectionIterator<IParameterDefinitionsIterator> iterEnd = paramDefs->end(); for (VirtualCollectionIterator<IParameterDefinitionsIterator> iter = paramDefs->begin(); iter != iterEnd; ++iter) { //ECValue val1; //mdlDialog_dmsgsPrint( (*iter).GetDisplayLabel() ); WCharCP ddd = (*iter).GetDisplayLabel();//变量名称 WCharCP fff = (*iter).GetAccessString();//变量值 //ParameterType rtt = (*iter).GetType();//变量类型 mdlDialog_dmsgsPrint(WPrintfString(L"名称:%s 内容:%s ", ddd, fff )); }
前一种方法是自己写程序解析ECClass、ECProperty、ECInstance里边的内容,因为承载参数化单元参数值的ECClass结构非常复杂,解析起来非常麻烦,所以SDK又封装了一层接口,接口在后头已经完全处理好了调用起来相对简单多了。EC是基于XAttribute的,如果您没使用或者了解过XAttribute的话确实不好理解EC。通过XAttribute往元素上存储数据时,需要先定义一个c/c++的结构体,然后实例化一个对象实例,最后把这个实例挂到元素上边,这个属性会通过你自己程序中定义的一个ID值来区别于其他的XAttribute。读取的时候通过这个ID值来获取,想想一下如果只有这个ID值,而没有c/c++结构体的定义,获取XAttribute时返回了一个指针,程序中你怎么解析这个指针指向的内存区域呢?你完全解析不出来,所以为了方便业务数据在不同专业之间的交流,诞生了EC。通过EC存储属性的话,定义数据结构时不再是像XAttribute那样,声明一个c/c++的结构体,而是在一个xml中定义一个ECClass(可以参考C:\Program Files\Bentley\MicroStation CONNECT Edition\MicroStation\ECSchemas\Dgn这个路径下的xml文件),往元素上挂接ECInstance的时候,这个ECClass的内容也会保存到dgn文件中。这个时候其他人在读取你通过EC机制添加的属性时,后台会在dgn文件中找到对应的ECClass,随后当然也能解析出你添加的属性了。