老师好:
为了便于沟通和交流,我重新创建了一个贴子。
通过老师点点滴滴的 指导 和 浏览论坛 其他的相关帖子 ,找到了 部分资料,并将代码编译通过了。但是仍旧有些问题。具体如下
我的业务场景是 当用户定义 一个 3D元素的时候,通过预览按钮 ,可以在 Generic 上显示出来该元素,但是目前 测试发现 Generic 上没有反应(没有显示该元素)。
具体业务逻辑是 :
当用户点击 预览按钮后 ,将根据定义好的数据 创建出来一个元素(CELL),最终通过调用 void drawCellDetail(MSDialogP dbP , DialogItem *diP , int is3d , MSElementDescrP cellDP)函数,将这个元素(CELL)显示到 Generic上,从而达到预览的效果(并且 要求 该元素(CELL) 不添加到当前的设计文件中,只是 预览的功能)。
其中 diP 是 Generic 句柄,
dbP是 diP ->GetDialog () ,
is3d 是 1,
cellDP是我代码创建的cell 通过 eehTmp.GetElementDescrP(); 获取的。
代码如下:
ppp=mdlDialog_itemGetByTypeAndId(dimP->db,RTYPE_Generic ,GENERICID_Cells , 0 );
drawCellDetail(ppp->GetDialog () , ppp , 1 , pz.ElementD);
编译通过的代码如下:
void drawCellDetail(MSDialogP dbP , DialogItem *diP , int is3d , MSElementDescrP cellDP) { ViewFlags viewflags; RotMatrix rMatrix; BSIRect localRect; Dpoint3d origin, newextent; int nDices; DRange3d dRangeVec=Bentley::DRange3d::From(0,0,0,0,0,0); // int status; //dRangeVec->From(0,0,0,0,0,0); localRect = diP->rect; mdlElmdscr_validate (cellDP, MASTERFILE); nDices = mdlModelRef_is3D (MASTERFILE); if (!is3d) { mdlRMatrix_getIdentity (&rMatrix); mdlCnv_scanRangeToDRange (&dRangeVec, &cellDP->el.hdr.dhdr.range); origin = dRangeVec.low; origin.z = 0.0; mdlVec_subtractPoint (&newextent,&dRangeVec.high,&origin); newextent.z = fc_1000; if (newextent.x < fc_1) newextent.x = fc_1000; if (newextent.y < fc_1) newextent.y = fc_1000; memset (&viewflags, 0, sizeof(viewflags)); viewflags.patterns = 1; viewflags.ed_fields = 1; viewflags.on_off = 1; viewflags.grid = 1; viewflags.constructs = 1; viewflags.dimens = 1; // mdlDialog_rectInset(&localRect, 3, 3); mdlWindow_clipRectSet ((MSWindow *)dbP, &localRect); mdlElmdscr_displayToWindow ((MSWindow *)dbP, &localRect,&viewflags ,cellDP, &rMatrix, &origin, &newextent, nDices, -1); mdlWindow_clipRectSet ((MSWindow *)dbP, NULL); } else { BSIRect localRectArray[4]; int deltaX; int deltaY; int winNumber; RotMatrix rMatrixArray[4]; //set up the views mdlView_getStandard (&rMatrixArray[0],StandardView::Top); mdlView_getStandard (&rMatrixArray[1],StandardView::Iso); mdlView_getStandard (&rMatrixArray[2],StandardView::Front); mdlView_getStandard (&rMatrixArray[3],StandardView::Right); deltaX = localRect.corner.x - localRect.origin.x; deltaY = localRect.corner.y - localRect.origin.y; localRectArray[0] = localRect; localRectArray[0].corner.y = localRect.origin.y+(deltaY/2); localRectArray[0].corner.x = localRect.origin.x+(deltaX/2); localRectArray[1] = localRect; localRectArray[1].origin.x = localRect.origin.x+(deltaX/2); localRectArray[1].corner.y = localRect.origin.y+(deltaY/2); localRectArray[2] = localRect; localRectArray[2].origin.y = localRect.origin.y+(deltaY/2); localRectArray[2].corner.x = localRect.corner.x-(deltaX/2); localRectArray[3] = localRect; localRectArray[3].origin.x = localRect.origin.x+(deltaX/2); localRectArray[3].origin.y = localRect.origin.y+(deltaY/2); for (winNumber = 0;winNumber <4 ;winNumber++ ) { mdlCnv_scanRangeToDRange (&dRangeVec, &cellDP->el.hdr.dhdr.range); mdlRMatrix_multiplyRange (&dRangeVec.low,&dRangeVec.high,&rMatrixArray[winNumber]); mdlVec_subtractPoint (&newextent,&dRangeVec.high,&dRangeVec.low); mdlRMatrix_multiplyTransposePoint(&dRangeVec.low, &rMatrixArray[winNumber]); if (newextent.z< fc_1) newextent.z = fc_1000; if (newextent.x < fc_1) newextent.x = fc_1000; if (newextent.y < fc_1) newextent.y = fc_1000; memset (&viewflags, 0, sizeof(viewflags)); viewflags.patterns = 1; viewflags.ed_fields = 1; viewflags.on_off = 1; viewflags.grid = 1; viewflags.constructs = 1; viewflags.dimens = 1; // mdlDialog_rectInset(&localRectArray[winNumber], 2, 2); mdlWindow_clipRectSet ((MSWindow *)dbP, &localRect); mdlElmdscr_displayToWindow ((MSWindow *)dbP, &localRectArray[winNumber],&viewflags ,cellDP, &rMatrixArray[winNumber], &dRangeVec.low, &newextent, nDices, -1); mdlDialog_rectDrawEdge (dbP,&localRectArray[winNumber],TRUE); mdlWindow_clipRectSet ((MSWindow *)dbP, NULL); } } mdlElmdscr_freeAll (&cellDP); }
希望老师在百忙之中 ,帮忙分析一下 ,是什么原因,辛苦老师了!!感激!!!
看到您之前的帖子了。调试代码比较费时,请耐心等待我们的答复。
好的,感谢老师!!!!
Bentley 二次开发小白一枚
如下代码是 预览 按钮 的 测试代码:
DialogItem * ppp=mdlDialog_itemGetByTypeAndId(dimP->db,RTYPE_Generic ,GENERICID_Cells , 0 );
EditElementHandle eehBUT;CurveVectorPtr pCurveVec1 = CurveVector::Create(CurveVector::BOUNDARY_TYPE_Outer);pCurveVec1->Add(ICurvePrimitive::CreateRectangle(1000-1000/2,1000-1000/2,1000+1000/2,1000+1000/2,0) );DVec3d extrusionVec1 = DVec3d::From(0, 0, 500 );DgnExtrusionDetail data1(pCurveVec1, extrusionVec1, true);//pCurveVecISolidPrimitivePtr pSolid1 = ISolidPrimitive::CreateDgnExtrusion(data1);DraftingElementSchema::ToElement(eehBUT, *pSolid1, nullptr, *ACTIVEMODEL);updateDialog(eehBUT, ppp->GetDialog () , ppp);//这里 ppp 为 Generic 的 DialogItem 变量。
//updateDialog(eehBUT, dimP->db , ppp);//因为 Generic 所在的对话框 我理解 有两种方式,所以 这种方式我也测试了。
背景色 全部是 黑色的 !!!!
另外,我将 Generic 背景色改为白色后,发现 eehBUT 并没有绘制到 Generic。
因为是预览,所以 我没有将 eehBUT 添加到涉及文件中。
辛苦老师 ,帮忙分析一下原因!!!!
请将元素添加到模型中测试一下。我当时是通过ElementId读到的元素实现预览的。
上图 没有 eehBUT,
但是 在 设计文件中是可以看到 eehBUT 这个元素的。如下图:
我的 预览按钮 的测试代码如下:(已经将 eehBUT 添加到设计文件中)
if(dimP->messageType == DITEM_MESSAGE_BUTTON ) { DialogItem* ppp=mdlDialog_itemGetByTypeAndId(dimP->db,RTYPE_Generic ,GENERICID_Cells , 0 ); EditElementHandle eehBUT; CurveVectorPtr pCurveVec1 = CurveVector::Create(CurveVector::BOUNDARY_TYPE_Outer); pCurveVec1->Add(ICurvePrimitive::CreateRectangle(100-100/2,100-100/2,100+100/2,100+100/2,0) ); DVec3d extrusionVec1 = DVec3d::From(0, 0, 50 ); DgnExtrusionDetail data1(pCurveVec1, extrusionVec1, true);//pCurveVec ISolidPrimitivePtr pSolid1 = ISolidPrimitive::CreateDgnExtrusion(data1); DraftingElementSchema::ToElement(eehBUT, *pSolid1, nullptr, *ACTIVEMODEL); eehBUT.AddToModel(); updateDialog(eehBUT, dimP->db , ppp); }
根据您提供的 预览方法 修改的代码如下:
void updateDialog(ElementHandleR eh, MSDialogP dbP , DialogItem *diP) { if (NULL == diP) return; ViewFlags viewflags; mdlView_getDefaultFlags(&viewflags); viewflags.camera = 0; //viewflags.renderMode = (UInt32)MSRenderMode::SmoothShade; RotMatrix rMatrix; mdlView_getStandard(&rMatrix, StandardView::Top); DRange3d range; Dpoint3d extent; mdlElement_extractRange(&range, eh.GetElementCP()); extent.Subtract(range.high, (DVec3dR)range.low); mdlElmdscr_extendedDisplayToWindow((MSWindowP)dbP, &diP->GetRect(), &viewflags, eh.GetElementDescrCP(), &rMatrix, &range.low, &extent, true, -1, NULL, true, NULL); }
代码是 可以测试 执行的 ,辛苦老师 了!
我是一个更高级的环境下实现的这个对话框中显示图形。
即光标放到哪个元素上,就会临时弹出一个对话框,在该对话框中显示这个元素的图形的。效果如下:
大致关键代码如下:
DialogBoxRsc DIALOGID_ShowPromptDlog = { DIALOGATTRX_TRANSPARENTBORDERLESS, 31.0*XC, 15.0*YC, NOHELP, LHELPCMD, NOHOOK, NOPARENTID, "", { { { 1.5*XC, GENY(2.5), 28.0*XC, GENY(10.0) }, Generic, GENERICID_ShowElement, ON, 0, "", "" }, } }; DItem_GenericRsc GENERICID_ShowElement = { NOHELP, MHELP, NOHOOK, NOARG };
void updateDialog(ElementHandleR eh, MSDialogP dbP) { DialogItemP diP = dbP->GetItemByTypeAndId(RTYPE_Generic, GENERICID_ShowElement); if (NULL == diP) return; ViewFlags viewflags; mdlView_getDefaultFlags(&viewflags); viewflags.camera = 0; //viewflags.renderMode = (UInt32)MSRenderMode::SmoothShade; RotMatrix rMatrix; mdlView_getStandard(&rMatrix, StandardView::Top); DRange3d range; Dpoint3d extent; mdlElement_extractRange(&range, eh.GetElementCP()); extent.Subtract(range.high, (DVec3dR)range.low); mdlElmdscr_extendedDisplayToWindow((MSWindowP)dbP, &diP->GetRect(), &viewflags, eh.GetElementDescrCP(), &rMatrix, &range.low, &extent, true, -1, NULL, true, NULL); } void pathFunc(DisplayPathCP path, WStringR description) { DPoint3d hitPoint; mdlHitPath_getHitPoint((HitPathCP)path, hitPoint); Point2d screenPt; IndexedViewSetR viewSet = IViewManager::GetManager().GetActiveViewSet(); int view = viewSet.GetSelectedView(); mdlView_pointToScreen(&screenPt, &hitPoint, view, DgnCoordSystem::View); MSDialogP dbP = MSDialog::Open(NULL, DIALOGID_ShowPromptDlog); if (NULL == dbP) return; screenPt.x += 25; screenPt.y += 200; mdlWindow_resize((MSWindowP)dbP, CORNER_ALL, &screenPt); ElementHandle eh(path->GetHeadElem(), path->GetRoot()); updateDialog(eh, dbP); description = L""; } LocateFilterStatus gPostLocateFunc(LOCATE_Action action, MSElementCP pElement, DgnModelRefP modelRef, UInt32 filePosition, DPoint3dCP pPoint, int viewNumber, HitPathCP hitPath, WStringR rejectReason) { if (!AccuSnap::GetInstance().IsHot()) { MSDialogP dbP = MSDialog::Find(DIALOGID_ShowPromptDlog); if (NULL != dbP) { dbP->CloseCommandQueue(); dbP = NULL; } } return LOCATE_FILTER_STATUS_Neutral; } void showPrompt(WCharCP unparsed) { LocateCallback::SetOverridePathDescriptionFunction(pathFunc); LocateCallback::SetGlobalPostLocateFunction(gPostLocateFunc); }
可以解压我的最终执行程序File.zip到你的mdlapps下,
File.zip
然后,在MSCE中键入MDL LOAD File装载程序。再键入MyDialog ShowPrompt就可以测试了。光标移动到哪个元素上,就会在光标处弹出一个预览对话框显示这个元素的。光标一离开这个元素,该对话框自动关闭。
您这个 是可以的,但是 从理论上 ,感觉没有问题啊,所以 老师能不能 看一下 我那个简单 场景的 测试代码,是否有问题,或者让说 原理上 是否存在 问题!!!!