[MSCE U9 C++]为什么用mdlElement_setDisplayStyle函数设置元素的显示样式无效?

	IndexedViewportP viewPort = IViewManager::GetActiveViewSet().GetSelectedViewport();
	if (viewPort == nullptr)
	{
		return false;
	}
	DgnFileP dgnFile = viewPort->GetRootModel()->GetDgnFileP();
	DisplayStyleCP pDisStyle = DisplayStyleManager::FindDisplayStyleByName(L"Smooth", dgnFile);
	if (!pDisStyle)
	{
		return false;
	}
	int iIndex = pDisStyle->GetIndex();
	ElementId eleId = 968;
	MSElement ele;
	mdlAssoc_getElement(&ele, nullptr, eleId, ACTIVEMODEL);
	if (SUCCESS != mdlElement_setDisplayStyle(&ele, iIndex))
	{
		return false;
	}
	MSElementDescrP pEleDescr;
	mdlAssoc_getElementDescr(&pEleDescr, nullptr, eleId, ACTIVEMODEL, true);
	UInt32 posOld = elementRef_getFilePos(pEleDescr->h.elementRef);
	UInt32 posNew = mdlElmdscr_rewrite(pEleDescr, NULL, posOld);
	if (posOld != posNew)
	{
		return false;
	}
	return true;

Parents
  • 您对MSElement和MSElementDescr的理解可能还没到位。如下代码测试通过:

    void setElementDisplayStyle()
    {
    	DgnFileP dgnFile = ISessionMgr::GetActiveDgnFile();
    	int styleIdx = DisplayStyleManager::GetIndexForDisplayStyle(L"Smooth", dgnFile);
    	if (-1 == styleIdx)
    	{
    		mdlDialog_dmsgsPrint(L"Can not find specified display style");
    		return;
    	}
    	ElementId eleId = 1448;
    	MSElementDescrP pEleDescr = NULL;
    	UInt32          filePos;
    	mdlAssoc_getElementDescr(&pEleDescr, &filePos, eleId, ACTIVEMODEL, true);
    	if (NULL == pEleDescr)
    	{
    		mdlDialog_dmsgsPrint(L"Can not find specified element");
    		return;
    	}
    	MSElement  ele;
    	mdlElement_memcpy(&ele, &pEleDescr->el);
    	mdlElement_setDisplayStyle(&ele, styleIdx);
    	mdlElmdscr_replaceElement(&pEleDescr, &ele);
    	mdlElmdscr_rewrite(pEleDescr, NULL, filePos);
    	mdlElmdscr_freeAll(&pEleDescr);
    }



Reply
  • 您对MSElement和MSElementDescr的理解可能还没到位。如下代码测试通过:

    void setElementDisplayStyle()
    {
    	DgnFileP dgnFile = ISessionMgr::GetActiveDgnFile();
    	int styleIdx = DisplayStyleManager::GetIndexForDisplayStyle(L"Smooth", dgnFile);
    	if (-1 == styleIdx)
    	{
    		mdlDialog_dmsgsPrint(L"Can not find specified display style");
    		return;
    	}
    	ElementId eleId = 1448;
    	MSElementDescrP pEleDescr = NULL;
    	UInt32          filePos;
    	mdlAssoc_getElementDescr(&pEleDescr, &filePos, eleId, ACTIVEMODEL, true);
    	if (NULL == pEleDescr)
    	{
    		mdlDialog_dmsgsPrint(L"Can not find specified element");
    		return;
    	}
    	MSElement  ele;
    	mdlElement_memcpy(&ele, &pEleDescr->el);
    	mdlElement_setDisplayStyle(&ele, styleIdx);
    	mdlElmdscr_replaceElement(&pEleDescr, &ele);
    	mdlElmdscr_rewrite(pEleDescr, NULL, filePos);
    	mdlElmdscr_freeAll(&pEleDescr);
    }



Children
  • mdlElement_setDisplayStyle函数的第一个参数为什么还要mdlElement_memcpy、mdlElmdscr_replaceElement来转一下?直接由mdlAssoc_getElement得出的MSElement不行?

  • 对于复杂元素,我们是要修改其第一个头元素。mdlElement_setDisplayStyle是通过给元素附加一个DisplayStyleIndex的Linkage来实现增加自身显示样式的,这个动作会增大头元素的尺寸(size),而原来的复杂元素中一个个元素都是紧密排列的,第一个元素被增大后后续的元素位置都需要调整。对于保存在内存区的元素描述符(MSElementDescr)来说,它是一个复杂的双向链表,我们是通过mdlElement_memcpy先从复杂元素中将第一个元素拿到另一块内存区,修改它,然后再替换回原来的内存区,这样能保持双向链表的正确性,写回磁盘时整个复杂元素也能正确被替换(其实是删除原来位置的复杂元素,在模型尾部增加新的修改过复杂元素。如果整个元素大小不变的话,是可以在原位置替换的)



    Answer Verified By: 某某 某