LOGO
帮助文档
旧版文档
简介绘制自定义实体对象动态绘制自定义实体响应事件,动态绘制响应事件,绘制自定义实体响应事件,返回自定义实体夹点响应事件,夹点移动处理响应事件, 增加坐标变换功能响应事件,增加实体求交响应事件,增加捕捉
简介

在控件中除了内置的直线,圆,文字等实体外,开发人员还可以增加自定义实体。点击此处下载演示实例


视频如下:

绘制自定义实体对象

调用控件函数:DrawCustomEntity直接在图上,绘制自定义实体,如下C#代码:

 private void button2_Click(object sender, EventArgs e)
        {
            // 调用DrawCustomEntity绘制一个自定义实体,实体类型字符串为:DrawCustEntity
            MxDrawCustomEntity ent = (MxDrawCustomEntity)axMxDrawX1.DrawCustomEntity("DrawCustEntity","");
            
            // 开始设置自定义实体的属性。
            ent.BeginSetValue();
            // 设置属性Width
            ent.SetDouble("Width", 30);
            MxDrawPoint pt1 = new MxDrawPoint();
            pt1.x = 10;
            pt1.y = 10;
            MxDrawPoint pt2 = new MxDrawPoint();
            pt2.x = 100;
            pt2.y = 200;
            // 设置属性Point1,Point2
            ent.SetPoint("Point1", pt1);
            ent.SetPoint("Point2", pt2);
            ent.SetLong("Count", 2);
            // 结束设置自定义实体的属性。
            ent.EntSetValue();
            // 更新显示
            axMxDrawX1.UpdateDisplay();
        }

 

下面函数MyDrawMline,用来具体绘制自定义实体,将用在后面的事件中调用。

    // MyDrawMline,用来绘制我们的自定义实体
    private void MyDrawMline(MxDrawWorldDraw pWorldDraw, MxDrawCustomEntity pCustomEntity, MxDrawPoint curPt)
    {  
        // 取自定义实体的端点数目。
        if (!pCustomEntity.IsHave("Count"))
            return;
        long lCount = pCustomEntity.GetLong("Count");
        MxDrawPolyline tmpPl = new MxDrawPolyline();

        for (long i = 0; i < lCount; i++)
        {
            String sName;
            sName = "Point" + (i + 1).ToString();
            if (!pCustomEntity.IsHave(sName))
                break;
            // 取自定义实体的端点坐标。
            MxDrawPoint pt = pCustomEntity.GetPoint(sName);
            // 把端点坐标,传给pl线,用于生成双线。
            tmpPl.AddVertexAt(pt);
        }
        if (curPt != null)
            tmpPl.AddVertexAt(curPt);
        if (tmpPl.NumVerts < 2)
        {
            // 端点数少于2就,不构成直线,就不需要显示。
            return;
        }
        // 求pl线,开始点的导数.
        MxDrawVector3d vecFx;
        if (!tmpPl.GetFirstDeriv(tmpPl.GetStartParam(), out vecFx))
            return;
        if (vecFx.IsZeroLength())
            return;
        // 把向量旋转90度.
        vecFx.RotateByXyPlan(3.14159265 / 2.0);
        vecFx.Normalize();
        //  得到双线的宽度属性。
        double dWidth = pCustomEntity.GetDouble("Width");
        vecFx.Mult(dWidth);
        MxDrawPoint startPt = tmpPl.GetStartPoint();
        // 向pl线,两个方向偏移,
        MxDrawPoint offsetPt1 = new MxDrawPoint();
        offsetPt1.x = startPt.x;
        offsetPt1.y = startPt.y;
        offsetPt1.Add(vecFx);
        MxDrawPoint offsetPt2 = new MxDrawPoint();
        offsetPt2.x = startPt.x;
        offsetPt2.y = startPt.y;
        offsetPt2.Sum(vecFx);
        MxDrawText text = new MxDrawText();
        text.TextString = "Test";
        text.Height = 100;
        text.Position = startPt;
        text.AlignmentPoint = startPt;
        MxDrawPoint pt1, pt2;
        text.GetBoundingBox(out pt1, out pt2);
        MxDrawPoint pt3 = new MxDrawPoint();
        pt3.x = pt1.x;
        pt3.y = pt2.y;
        MxDrawPoint pt4 = new MxDrawPoint();
        pt4.x = pt2.x;
        pt4.y = pt1.y;
        MxDrawPoints pts = new MxDrawPoints();
        pts.Add(pt1.x, pt1.y, 0);
        pts.Add(pt3.x, pt3.y, 0);
        pts.Add(pt2.x, pt2.y, 0);
        pts.Add(pt4.x, pt4.y, 0);
        Int32 lDraworder = pWorldDraw.Draworder;
        pWorldDraw.Draworder = lDraworder + 1;
        pWorldDraw.DrawWipeout(pts);
        pWorldDraw.Draworder = lDraworder + 2;
        pWorldDraw.DrawEntity((MxDrawEntity)text);
        pWorldDraw.Draworder = lDraworder;
        //    pWorldDraw->
        {
            MxDrawResbuf newobj;
            if (tmpPl.OffsetCurves(dWidth, offsetPt1, out newobj))
            {
                for (Int32 j = 0; j < newobj.Count; j++)
                {
                    MxDrawEntity tmpObj = (MxDrawEntity)newobj.AtObject(j);
                    if (tmpObj == null)
                        continue;
                    pWorldDraw.DrawEntity(tmpObj);
                }
                newobj.RemoveAll();
            }
        }
        {
            MxDrawResbuf newobj;
            if (tmpPl.OffsetCurves(dWidth, offsetPt2, out newobj))
            {
                for (Int32 j = 0; j < newobj.Count; j++)
                {
                    MxDrawEntity tmpObj = (MxDrawEntity)newobj.AtObject(j);
                    if (tmpObj == null)
                        continue;
                    pWorldDraw.DrawEntity(tmpObj);
                }
                // 这不使用newobj,需要显示调用RemoveAll函数清楚内存。
                // 不然这个可能就会程序退出时才释放,这时它会去释放控件对象指针,有可能会出错。
                newobj.RemoveAll();
            }
        }
    }

 

动态绘制自定义实体

下面代码让用户在图上循环点取点坐标,直接到按ESC退出,然后绘制自定义实体,在点取点过程中可以看动态画制效果,C#代码实现如下:


private void DrawMlineCommand()
{
    // 定义取点变量。
    MxDrawUiPrPoint getPt = new MxDrawUiPrPoint();
    
    getPt.message = "点取第一点";
    // 等用户在图上点取一个点
    if (getPt.go() != MCAD_McUiPrStatus.mcOk)
    {
        return;
    }
    // 返回点的点对象值。
    var frstPt = getPt.value();
    if (frstPt == null)
    {
        return;
    }
 
    // 定义第二个取点变量。
    MxDrawUiPrPoint getSecondPt = new MxDrawUiPrPoint();
 
    getSecondPt.message = "点取第二点";
    getSecondPt.basePoint = frstPt;
 
    getSecondPt.setUseBasePt(false);
 
    // 设置在取点时的动态绘制.
    MxDrawCustomEntity spDrawData = getSecondPt.InitUserDraw("DrawCustEntity");
    
    // 设置绘制变量。Width,Point1
    spDrawData.SetDouble("Width", 30);
 
    spDrawData.SetPoint("Point1", frstPt);
 
    Int32 lCount = 1;
    spDrawData.SetLong("Count", 1);
            
    // 循环取点,直到用户按ESC取消.
    while (true)
    {
        if (getSecondPt.go() != MCAD_McUiPrStatus.mcOk)
            break;
 
        var secondPt = getSecondPt.value();
        if (secondPt == null)
            break;
 
        lCount++;
 
        String sPointName = "Point" + lCount.ToString();
 
        spDrawData.SetPoint(sPointName, secondPt);
        spDrawData.SetLong("Count", lCount);
    }
    
    // 把自定义实本对象spDrawData画在图上。
    if (lCount > 1)
        axMxDrawX1.DrawEntity(spDrawData);
}
响应事件,动态绘制

添加控件DynWorldDraw事件,在事件中响应自定义实体的动态绘制,C#代码实现如下:


private void axMxDrawX1_DynWorldDraw(object sender, AxMxDrawXLib._DMxDrawXEvents_DynWorldDrawEvent e)
{
    // 得到当前动态绘制数据。
    MxDrawCustomEntity pCustomEntity = (MxDrawCustomEntity)e.pData;
    String sGuid = pCustomEntity.Guid;
    e.pRet = 0;
 
    // 得到绘制对象.
    MxDrawWorldDraw pWorldDraw = (MxDrawWorldDraw)e.pWorldDraw;
    
    // 得到当前鼠标点.
    MxDrawPoint curPt = new MxDrawPoint();
    curPt.x = e.dX;
    curPt.y = e.dY;
 
    if (sGuid == "DrawCustEntity")
    {
        // 动态绘制DrawCustEntity
        MyDrawMline(pWorldDraw, pCustomEntity, curPt);
    }
}

响应事件,绘制自定义实体

需要添加DMxDrawXEvents::CustomEntity_Explode事件,绘制自定义实体

注意:该事件必须实现,如果不实现自定义实体将不会保存到图纸中。


如:C#代码实现如下:


private void axMxDrawX1_CustomEntity_Explode(object sender, AxMxDrawXLib._DMxDrawXEvents_CustomEntity_ExplodeEvent e)
        {
            // 得到自定义实体对象.
            MxDrawCustomEntity pCustomEntity = (MxDrawCustomEntity)e.pCustomEntity;
            // 得到自定义实体类型
            var sGuid = pCustomEntity.Guid;
 
            // 得到绘制对象.
            MxDrawWorldDraw pWorldDraw = (MxDrawWorldDraw)e.pDraw;
 
            if (sGuid == "DrawCustEntity")
            {
                // 绘制自定义实体.
                MyDrawMline(pWorldDraw, pCustomEntity, null);
                e.pRet = 1;
            }
        }
响应事件,返回自定义实体夹点

自定义实体支持夹点编辑,下面事件返回实体的夹点

需要响应_DMxDrawXEvents::CustomEntity_getGripPoints事件,C#代码实现如下:


private void axMxDrawX1_CustomEntity_getGripPoints(object sender, AxMxDrawXLib._DMxDrawXEvents_CustomEntity_getGripPointsEvent e)
{
    // 得到自定义实体对象.
    MxDrawCustomEntity pCustomEntity = (MxDrawCustomEntity)e.pCustomEntity;
    
    // 得到自定实体类型
    var sGuid = pCustomEntity.Guid;
    e.pOk = 0;
    if (sGuid == "DrawCustEntity")
    {
        if (!pCustomEntity.IsHave("Count"))
            return;
 
        long lCount = pCustomEntity.GetLong("Count");
 
        // 把需要的夹点数据,放在ret链表中,用于返回 
        MxDrawResbuf ret = (MxDrawResbuf)axMxDrawX1.NewResbuf();
 
        for (long i = 0; i < lCount; i++)
        {
            String sName;
            sName = "Point" + (i + 1).ToString();
            if (!pCustomEntity.IsHave(sName))
                break;
 
            // 取自定义实体的端点坐标。
            MxDrawPoint pt = pCustomEntity.GetPoint(sName);
 
 
            ret.AddPoint(pt);
        }
        e.pOk = 1;
        // 返回夹点数据。
        axMxDrawX1.SetEventRetEx(ret);
    }
 
}
响应事件,夹点移动处理

自定义实体夹点移动后,调用moveGripPointsAt事件修改自定义实体。

响应CustomEntity_moveGripPointsAt事件。


下面例子夹点移动后,在moveGripPointsAt修改自定义实体的点坐标,C#代码实现如下:


private void axMxDrawX1_CustomEntity_moveGripPointsAt(object sender, AxMxDrawXLib._DMxDrawXEvents_CustomEntity_moveGripPointsAtEvent e)
{
    e.pRet = 1;
    // 得到自定义实体对像.
    MxDrawCustomEntity pCustomEntity = (MxDrawCustomEntity)e.pCustomEntity;
    var sGuid = pCustomEntity.Guid;
 
    if (sGuid == "DrawCustEntity")
    {
        if (!pCustomEntity.IsHave("Count"))
            return;
 
        long lCount = pCustomEntity.GetLong("Count");
                
        for (long i = 0; i < lCount; i++)
        {
            String sName;
            sName = "Point" + (i + 1).ToString();
            if (!pCustomEntity.IsHave(sName))
                break;
 
            // 取自定义实体的端点坐标。
            MxDrawPoint pt = pCustomEntity.GetPoint(sName);
 
            // e.lGridIndex表示移动了第几个夹点.
            if (i == e.lGridIndex)
            {
                pt.x = pt.x + e.dOffsetX;
                pt.y = pt.y + e.dOffsetY;
 
                // 修改移动后的点坐标值。
                pCustomEntity.SetPoint(sName, pt);
            }
        }
    }
}
响应事件, 增加坐标变换功能

想要支持自定义实体的移动,旋转,缩放功能,需要添加坐标变换事件处理,事件名:CustomEntity_transformBy

ce1.png 

函数实现c#代码如下:

 private void axMxDrawX1_CustomEntity_transformBy(object sender, _DMxDrawXEvents_CustomEntity_transformByEvent e)
        {
            e.pOk = 1;
            MxDrawCustomEntity pCustomEntity = (MxDrawCustomEntity)e.pCustomEntity;
            // 得到自定义实体类型
            var sGuid = pCustomEntity.Guid;

            if (sGuid == "DrawCustEntity")
            {
                if (!pCustomEntity.IsHave("Count"))
                    return;
                long lCount = pCustomEntity.GetLong("Count");

                // 对实体的点坐标进行坐标变换。
                for (long i = 0; i < lCount; i++)
                {
                    String sName;
                    sName = "Point" + (i + 1).ToString();
                    if (!pCustomEntity.IsHave(sName))
                        break;
                    // 取自定义实体的端点坐标。
                    MxDrawPoint pt = pCustomEntity.GetPoint(sName);
                    // 计算出新的坐标。
                    pt.TransformBy((MxDrawMatrix3d)e.pMatXform);
                    pCustomEntity.SetPoint(sName, pt);

                }
            }
        }

 

响应事件,增加实体求交

如果需要捕捉两个实体的交点,需要响应自定义实体求交事件:CustomEntity_intersectWith

下面c#代码响应求交事件,然后得到自定义实体,计算出交点返回:

private void axMxDrawX1_CustomEntity_intersectWith(object sender, _DMxDrawXEvents_CustomEntity_intersectWithEvent e)
        {
            // 得到自定义实体。
            MxDrawEntity pThis = (MxDrawEntity)e.pCustomEntity;
            // 得到另一个求交的实体。
            MxDrawEntity pOther = (MxDrawEntity)e.pOhterEntity;
            if (pThis.ObjectName != "MxDrawXCustomEntity" || pOther.ObjectName != "MxDrawXCustomEntity")
                return;
            MxDrawCustomEntity pEnt1 = (MxDrawCustomEntity)pThis;
            MxDrawCustomEntity pEnt2 = (MxDrawCustomEntity)pOther;
            
            // 判断自定义有没有我们需要的属性。
            if (!pEnt1.IsHave("Point1"))
                return;
            if (!pEnt1.IsHave("Point2"))
                return;

            if (!pEnt2.IsHave("Point1"))
                return;
            if (!pEnt2.IsHave("Point2"))
                return;

            // 取自定义实体的端点坐标。
            MxDrawPoint pt11 = pEnt1.GetPoint("Point1");
            MxDrawPoint pt12 = pEnt1.GetPoint("Point2");
            MxDrawPoint pt21 = pEnt2.GetPoint("Point1");
            MxDrawPoint pt22 = pEnt2.GetPoint("Point2");
            // 创建两个临时的直线,用来求交点。
            MxDrawLine line1 = new MxDrawLine();
            line1.StartPoint = pt11;
            line1.EndPoint = pt12;
            MxDrawLine line2 = new MxDrawLine();
            line2.StartPoint = pt21;
            line2.EndPoint = pt22;
            // 返回求到的交点。
            MxDrawPoints pts = line1.IntersectWith(line2, MCAD_McExtendOption.mcExtendNone);
            if(pts.Count > 0 )
            {
                MxDrawResbuf ret = (MxDrawResbuf)axMxDrawX1.NewResbuf();
                
                for (Int32 i = 0; i < pts.Count; i++)
                {
                 
       
                    ret.AddPoint(pts.Item(i));
                }
                // 告诉控件,求到了交点。
                e.pOk = 1;
                axMxDrawX1.SetEventRetEx(ret);
            }
        }


ce2.png


响应事件,增加捕捉

如果需要捕捉自定义实体的端点,最近点等,需要响应捕捉事件:CustomEntity_getOsnapPoints

如下C#代码,返回自定义实体的端点,计算最近点并返回。

 // 响应该事件,计算自定义实体捕捉点
        private void axMxDrawX1_CustomEntity_getOsnapPoints(object sender, _DMxDrawXEvents_CustomEntity_getOsnapPointsEvent e)
        {

            // 		enum OsnapMode         { kOsModeEnd          = 1,
            // 			kOsModeMid          = 2,
            // 			kOsModeCen          = 3,
            // 			kOsModeNode         = 4,
            // 			kOsModeQuad         = 5, 
            // 			kOsModeIns          = 7,
            // 			kOsModePerp         = 8,
            // 			kOsModeTan          = 9,
            // 			kOsModeNear         = 10,
            // 			kOsModeInt          = 11
            // 		};
            e.pOk = 0;

            // 得到自义实体对象。
            MxDrawCustomEntity pCustomEntity = (MxDrawCustomEntity)e.pCustomEntity;
            String sGuid = pCustomEntity.Guid;

            if (sGuid == "DrawCustEntity")
            {
                
                if (!pCustomEntity.IsHave("Count"))
                    return;

                // 得到点数.
                long lCount = pCustomEntity.GetLong("Count");

                if (lCount < 2)
                    return;


                if (e.lOsnapMode == 1)
                {
                    // 端点捕捉。
                    MxDrawPoint pickPoint = (MxDrawPoint)axMxDrawX1.NewPoint();

                    // 得到当前鼠标点。
                    pickPoint.x = e.dPickPointX;
                    pickPoint.y = e.dPickPointY;

                    // 得到开始点,结束点。
                    String sName = "Point1";
                    MxDrawPoint stp = pCustomEntity.GetPoint(sName);

                    sName = "Point" + lCount.ToString();

                    MxDrawPoint ept = pCustomEntity.GetPoint(sName);


                    // 计算出当前点与那个点最近,然后返回.
                    Double dDis1 = pickPoint.DistanceTo(stp);
                    Double dDis2 = pickPoint.DistanceTo(ept);


                    if (dDis1 < dDis2)
                    {
                        e.pSnapPointsX = stp.x;
                        e.pSnapPointsY = stp.y;

                    }
                    else
                    {
                        e.pSnapPointsX = ept.x;
                        e.pSnapPointsY = ept.y;


                    }

                    e.pOk = 1;

                }
                else if (e.lOsnapMode == 10)
                {
                    // 最近点捕捉。
                     MxDrawPolyline pl = new MxDrawPolyline();

                    // 把自定义实体变成一个 PL线,用于计算最近点坐标。
                    for (long i = 0; i < lCount; i++)
                    {
                        String sName;
                        sName = "Point" + (i + 1).ToString();
                        if (!pCustomEntity.IsHave(sName))
                            break;

                        // 取自定义实体的端点坐标。
                        MxDrawPoint pt = pCustomEntity.GetPoint(sName);

                        pl.AddVertexAt(pt);
                        
                    }

                    // 得到当前鼠标点。
                    MxDrawPoint pickPoint = (MxDrawPoint)axMxDrawX1.NewPoint();

                    pickPoint.x = e.dPickPointX;
                    pickPoint.y = e.dPickPointY;


                    // 计算最近点。
                    MxDrawPoint closePoint = pl.GetClosestPointTo2(pickPoint, false);

                    if (closePoint != null)
                    {
                        // 计算最点,然后返回。
                        e.pSnapPointsX = closePoint.x;
                        e.pSnapPointsY = closePoint.y;

                        e.pOk = 1;
                    }
                }
                   
                
            }
        }


运行效果如下图 :

 ce3.png