[MSCE C++]元素预览的问题

老师好:

     为了便于沟通和交流,我重新创建了一个贴子。

通过老师点点滴滴的 指导 和 浏览论坛 其他的相关帖子 ,找到了 部分资料,并将代码编译通过了。但是仍旧有些问题。具体如下

 我的业务场景是 当用户定义 一个 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);
}

希望老师在百忙之中 ,帮忙分析一下 ,是什么原因,辛苦老师了!!感激!!!

Parents
  • 看到您之前的帖子了。调试代码比较费时,请耐心等待我们的答复。



  • 好的,感谢老师!!!!

    Bentley 二次开发小白一枚

  • 我是一个更高级的环境下实现的这个对话框中显示图形。

    即光标放到哪个元素上,就会临时弹出一个对话框,在该对话框中显示这个元素的图形的。效果如下:

    大致关键代码如下:

    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就可以测试了。光标移动到哪个元素上,就会在光标处弹出一个预览对话框显示这个元素的。光标一离开这个元素,该对话框自动关闭。



  • 老师好:

    您这个  是可以的,但是 从理论上 ,感觉没有问题啊,所以 老师能不能  看一下 我那个简单  场景的 测试代码,是否有问题,或者让说 原理上 是否存在 问题!!!!

    Bentley 二次开发小白一枚

  • if(dimP->messageType == DITEM_MESSAGE_BUTTON )

    跟踪一下代码,看这个条件进入了吗?另外,你这样判断会被调用两次,因为Button事件有按下和抬起两次调用。一个按钮控件最好关联一个命令号,在命令处理函数中调用updateDialog

    另外,我把你的代码加入到了我的代码中去显示,没有调用AddToModel,也是正常的。

    显示结果如下图所示:

    如果还是找不到原因,请提交一个完整的可调试项目,最好排除其他无关因素,就抽取这个功能发给我。我帮你逐行查看一下。不过这样会比较耽误时间。最好还是自己调试找原因。



  • 老师好:

     我 整理了一个 可以执行的,还是辛苦您  帮忙 查看一下!我确实 找不到头绪!!!辛苦老师了!!!!

    编译后 ,是一个对话框 界面,界面上有一个 预览按钮。

    附近是 可执行的工程。

    8233.UI_code.zip

    Bentley 二次开发小白一枚

  • 其实你的预览功能是正确的,只不过你把对话框设计得太大了,稍微一动就会发生对话框更新事件(DIALOG_MESSAGE_UPDATE),这个Generic类型的控件会被重新刷新,你绘制的图形就消失了。

    我对你的代码做了多处修改,包括对话框高度、某些ID的名称和编号的不合适设置等。在你源代码中也写了注释。

    最主要的修改是给对话框增加了一个钩函数(DlgBasic_hookFunc),它是通过钩函数标识符HOOKID_DlgBasic与资源关联起来的。

    在对话框刷新消息下又重新绘制了图形。为了懒省事,将你的代码复制了一份过来,你将来要抽取成一份代码。同时,为了控制首次打开时不显示图形,设计了一个全局变量g_firstStart。

    修改后的项目源代码如下:

    8371.UI_code.7z

    执行结果如下图所示:



Reply
  • 其实你的预览功能是正确的,只不过你把对话框设计得太大了,稍微一动就会发生对话框更新事件(DIALOG_MESSAGE_UPDATE),这个Generic类型的控件会被重新刷新,你绘制的图形就消失了。

    我对你的代码做了多处修改,包括对话框高度、某些ID的名称和编号的不合适设置等。在你源代码中也写了注释。

    最主要的修改是给对话框增加了一个钩函数(DlgBasic_hookFunc),它是通过钩函数标识符HOOKID_DlgBasic与资源关联起来的。

    在对话框刷新消息下又重新绘制了图形。为了懒省事,将你的代码复制了一份过来,你将来要抽取成一份代码。同时,为了控制首次打开时不显示图形,设计了一个全局变量g_firstStart。

    修改后的项目源代码如下:

    8371.UI_code.7z

    执行结果如下图所示:



Children