MxDraw 发表于 2019-5-15 14:58:50

梦想CAD控件自定义实体实现

一、增加自定义实体对象

调用DrawCustomEntity函数,绘制一个自定义实体对象。

下面代码绘制一个自定义实体,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");
    spDrawData.SetDouble("Width", 30);

    spDrawData.SetPoint("Point1", frstPt);

    Int32 lCount = 1;
    spDrawData.SetLong("Count", 1);

    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);
    }
    if (lCount > 1)
      axMxDrawX1.DrawEntity(spDrawData);
}

js代码实现如下:

//绘制自定义实体
function DyInsertCustomEntity() {
    //清空当前显示内容
    mxOcx.NewFile();
    var getPt = mxOcx.NewComObject("IMxDrawUiPrPoint");
    getPt.message = "点取第一点";
    if (getPt.go() != 1)
      return;
    var frstPt = getPt.value();
    if (frstPt == null)
      return;
    var getSecondPt = mxOcx.NewComObject("IMxDrawUiPrPoint");
    getSecondPt.message = "点取第二点";
    getSecondPt.basePoint = frstPt;
    getSecondPt.setUseBasePt(true);
    if (getSecondPt.go() != 1)
      return;
    var secondPt = getSecondPt.value();
    if (secondPt == null)
      return;
    var ent = mxOcx.DrawCustomEntity("TestMxCustomEntity", "");
    ent.SetPoint("spt", frstPt);
    ent.SetPoint("ept", secondPt);
}

//绘制自定义实体1
function MyInsertCustomEntity()
{ //清空当前显示内容
    mxOcx.NewFile();
    var spDrawData;
    var getPt1 = mxOcx.NewComObject("IMxDrawUiPrPoint");
    {
      getPt1.message = "点取第一点";
      spDrawData = getPt1.InitUserDraw("DynDrawEnt1");
      if (getPt1.go() != 1) {
            return;
      }
    }
    var getPt2 = mxOcx.NewComObject("IMxDrawUiPrPoint");
    {
      getPt2.message = "点取第二点";
      spDrawData = getPt2.InitUserDraw("DynDrawEnt2");
      spDrawData.SetPoint("vFirst", getPt1.value());
      if (getPt2.go() != 1) {
            return;
      }
    }
    var getPt3 = mxOcx.NewComObject("IMxDrawUiPrPoint");
    {
      getPt3.message = "点取第三点";
      spDrawData = getPt3.InitUserDraw("DynDrawEnt3");
      spDrawData.SetPoint("vFirst", getPt1.value());
      spDrawData.SetPoint("vSecond", getPt2.value());
      if (getPt3.go() != 1) {
            return;
      }
    }
    var getPt4 = mxOcx.NewComObject("IMxDrawUiPrPoint");
    {
      getPt4.message = "点取第四点";
      spDrawData = getPt4.InitUserDraw("DynDrawEnt4");
      spDrawData.SetPoint("vFirst", getPt1.value());
      spDrawData.SetPoint("vSecond", getPt2.value());
      spDrawData.SetPoint("vThird", getPt3.value());
      if (getPt4.go() != 1) {
            return;
      }
    }
    {
      spDrawData = mxOcx.DrawCustomEntity("DrawEnt", "");
      spDrawData.SetPoint("vFirst", getPt1.value());
      spDrawData.SetPoint("vSecond", getPt2.value());
      spDrawData.SetPoint("vThird", getPt3.value());
      spDrawData.SetPoint("vFour", getPt4.value());
    }
}

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

需要响应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;
            }
      }

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();
      }
    }
}

js代码实现如下:

// 自定义实体绘制函数
function ExplodeFun(pCustomEntity, pWorldDraw, txt) {
    var sGuid = pCustomEntity.Guid;
    if (sGuid == "TestMxCustomEntity") {
      if (!pCustomEntity.IsHave("ept"))
            return;
      var stp = pCustomEntity.GetPoint("spt");
      if (stp == null)
            return;
      var ept = pCustomEntity.GetPoint("ept");
      if (ept == null)
            return;
      var mxUtility = mxOcx.NewUtility();
      var vec = ept.SumVector(stp);
      vec.Mult(0.5);
      var midPt = mxOcx.NewPoint();
      midPt.x = stp.x;
      midPt.y = stp.y;
      midPt.Add(vec);
      var dAng = vec.Angle();
      //计算一个标注角度,使用文字对象始终头朝上
      dAng = mxUtility.GetDimAngle(dAng);
      var dDis = 0.0;
      dDis = stp.DistanceTo(ept);
      var sTxt = "L=" + formatNumber(dDis, '#.##');
      dAng = dAng * 180.0 / 3.14159265;
      vec.RotateByXyPlan(3.14159265 / 2.0);
      vec.Normalize();
      vec.Mult(10);
      stp.Add(vec);
      ept.Add(vec);
      pWorldDraw.DrawLine(stp.x, stp.y, ept.x, ept.y);
      vec.Mult(2);
      stp.Sum(vec);
      ept.Sum(vec);
      pWorldDraw.DrawLine(stp.x, stp.y, ept.x, ept.y);
      pWorldDraw.SetColorIndex(1);
      pWorldDraw.DrawText(midPt.x, midPt.y, sTxt, 5, dAng,
            1, 2);
      mxOcx.SetEventRet(1);

    }


    var dHeigth = mxOcx.ViewLongToDocCoord(5);

    // 绘制绘制自定义实体1
    if(sGuid == "DrawEnt"){
      {
            if (!pCustomEntity.IsHave("vFour"))
                return;

            if (!pCustomEntity.IsHave("vThird"))
                return;

            if (!pCustomEntity.IsHave("vSecond"))
                return;

            if (!pCustomEntity.IsHave("vFirst"))
                return;
      }
      {
            var vFourPt = pCustomEntity.GetPoint("vFour");
            var dX = vFourPt.x;
            var dY = vFourPt.y;

            var vThirdPt = pCustomEntity.GetPoint("vThird");
            pWorldDraw.DrawLine(vThirdPt.x, vThirdPt.y, dX, dY);
            pWorldDraw.DrawText(dX, dY, "(" + dX.toFixed(1) + "," + dY.toFixed(1) + ")", dHeigth, 0, 1, 1);
            var dX = vThirdPt.x;
            var dY = vThirdPt.y;

            var vSecondPt = pCustomEntity.GetPoint("vSecond");
            pWorldDraw.DrawLine(vSecondPt.x, vSecondPt.y, dX, dY);
            pWorldDraw.DrawText(dX, dY, "(" + dX.toFixed(1) + "," + dY.toFixed(1) + ")", dHeigth, 0, 1, 1);
            dX = vSecondPt.x;
            dY = vSecondPt.y;

            var vFirstPt = pCustomEntity.GetPoint("vFirst");
            pWorldDraw.DrawLine(vFirstPt.x, vFirstPt.y, dX, dY);
            pWorldDraw.DrawText(dX, dY, "(" + dX.toFixed(1) + "," + dY.toFixed(1) + ")", dHeigth, 0, 1, 1);
            dX = vFirstPt.x;
            dY = vFirstPt.y;

            pWorldDraw.DrawText(dX, dY, "(" + dX.toFixed(1) + "," + dY.toFixed(1) + ")", dHeigth, 0, 1, 1);
      }
      mxOcx.SetEventRet(1);
    }

}

三、响应自定义事件,动态绘制

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")
    {
      MyDrawMline(pWorldDraw, pCustomEntity, curPt);
    }
}

js代码实现如下:

//动态施放绘制事件回调函数指针
//动态拖放时的绘制事件
//参数一为当前鼠标位置X坐标;参数为二当前鼠标位置Y坐标;
// 参数三为IMxDrawWorldDraw对象,用于动态绘制;参数四为IMxDrawCustomEntity对象,动态绘制数据
function DoDynWorldDrawFun(dX,dY,pWorldDraw,pData) {
    //自定义实体的GUID标识符
    var sGuid = pData.Guid;
    //设置自定义事件的返回值
    mxOcx.SetEventRet(0);

    var curPt = mxOcx.NewPoint();
    curPt.x = dX;
    curPt.y = dY;

    var dHeigth = mxOcx.ViewLongToDocCoord(5);
    //自定义实体的GUID标识符
    switch (pData.Guid) {
      case "DynDrawEnt4":
      {
            var vThirdPt = pData.GetPoint("vThird");
            pWorldDraw.DrawLine(vThirdPt.x, vThirdPt.y, dX, dY);
            pWorldDraw.DrawText(dX, dY, "(" + dX.toFixed(1) + "," + dY.toFixed(1) + ")", dHeigth, 0, 1, 1);
            dX = vThirdPt.x;
            dY = vThirdPt.y;
      }
      case "DynDrawEnt3":
      {
            var vSecondPt = pData.GetPoint("vSecond");
            pWorldDraw.DrawLine(vSecondPt.x, vSecondPt.y, dX, dY);
            pWorldDraw.DrawText(dX, dY, "(" + dX.toFixed(1) + "," + dY.toFixed(1) + ")", dHeigth, 0, 1, 1);
            dX = vSecondPt.x;
            dY = vSecondPt.y;
      }
      case "DynDrawEnt2":
      {
            var vFirstPt = pData.GetPoint("vFirst");
            pWorldDraw.DrawLine(vFirstPt.x, vFirstPt.y, dX, dY);
            pWorldDraw.DrawText(dX, dY, "(" + dX.toFixed(1) + "," + dY.toFixed(1) + ")", dHeigth, 0, 1, 1);
            dX = vFirstPt.x;
            dY = vFirstPt.y;
      }
      case "DynDrawEnt1":
      {
            pWorldDraw.DrawText(dX, dY, "(" + dX.toFixed(1) + "," + dY.toFixed(1) + ")", dHeigth, 0, 1, 1);
      }
    }
    //设置自定义事件的返回值
    mxOcx.SetEventRet(0);

}

四、响应自定义事件,返回自定义实体夹点

需要响应_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");

      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);
    }

}

js代码实现如下:

// 返回自定义实体夹点
function GetGripPointsFun(pCustomEntity) {
    var sGuid = pCustomEntity.Guid;

    //自定义实体绘制两条直线
    if (sGuid == "TestMxCustomEntity") {
      if (!pCustomEntity.IsHave("ept"))
            return;

      var stp = pCustomEntity.GetPoint("spt");
      if (stp == null)
            return;

      var ept = pCustomEntity.GetPoint("ept");
      if (ept == null)
            return;

      var ret = mxOcx.NewResbuf();

      ret.AddPoint(stp);
      ret.AddPoint(ept);

      mxOcx.SetEventRetEx(ret);
    }

    //自定义实体1
    if (sGuid == "DrawEnt") {
      if (!pCustomEntity.IsHave("vFour"))
            return;
      var stp = pCustomEntity.GetPoint("vFirst");
      if (stp == null)
            return;
      var ept = pCustomEntity.GetPoint("vSecond");
      if (ept == null)
            return;
      var tpt = pCustomEntity.GetPoint("vThird");
      if (tpt == null)
            return;
      var fpt = pCustomEntity.GetPoint("vFour");
      if (fpt == null)
            return;
      var ret = mxOcx.NewResbuf();
      ret.AddPoint(stp);
      ret.AddPoint(ept);
      ret.AddPoint(tpt);
      ret.AddPoint(fpt);
      mxOcx.SetEventRetEx(ret);
    }
}

五、响应自定义事件,夹点移动后的处理

需要响应CustomEntity_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);

            if (i == e.lGridIndex)
            {
                pt.x = pt.x + e.dOffsetX;
                pt.y = pt.y + e.dOffsetY;

                pCustomEntity.SetPoint(sName, pt);
            }
      }
    }
}

js代码实现如下:

// 移动自定义实体夹点
function MoveGripPointsFun(pCustomEntity, lGridIndex, dOffsetX, dOffsetY) {

    var sGuid = pCustomEntity.Guid;

    if (sGuid == "TestMxCustomEntity") {
      if (!pCustomEntity.IsHave("ept"))
            return;

      var stp = pCustomEntity.GetPoint("spt");
      if (stp == null)
            return;

      var ept = pCustomEntity.GetPoint("ept");
      if (ept == null)
            return;


      if (lGridIndex == 0) {
            stp.x = stp.x + dOffsetX;
            stp.y = stp.y + dOffsetY;
            pCustomEntity.SetPoint("spt", stp);
      }
      else {
            ept.x = ept.x + dOffsetX;
            ept.y = ept.y + dOffsetY;
            pCustomEntity.SetPoint("ept", ept);
      }

      mxOcx.SetEventRet(1);
    }
    if (sGuid == "DrawEnt") {
      if (!pCustomEntity.IsHave("vFour"))
            return;
      var stp = pCustomEntity.GetPoint("vFirst");
      if (stp == null)
            return;
      var ept = pCustomEntity.GetPoint("vSecond");
      if (ept == null)
            return;
      var tpt = pCustomEntity.GetPoint("vThird");
      if (tpt == null)
            return;
      var fpt = pCustomEntity.GetPoint("vFour");
      if (fpt == null)
            return;
      {
            stp.x = stp.x + dOffsetX;
            stp.y = stp.y + dOffsetY;
            pCustomEntity.SetPoint("vFirst", stp);
            ept.x = ept.x + dOffsetX;
            ept.y = ept.y + dOffsetY;
            pCustomEntity.SetPoint("vSecond", ept);
            tpt.x = tpt.x + dOffsetX;
            tpt.y = tpt.y + dOffsetY;
            pCustomEntity.SetPoint("vThird", tpt);
            fpt.x = fpt.x + dOffsetX;
            fpt.y = fpt.y + dOffsetY;
            pCustomEntity.SetPoint("vFour", fpt);
      }
      mxOcx.SetEventRet(1);
    }
}

六、自定义实体之打碎

c#代码实现如下

            // 打开图纸文件。            
            axMxDrawX1.OpenDwgFile("C:\西桥头村.dwg");   
            // 打碎图纸上的自定义实体。
            MxDrawResbuf filter = new MxDrawResbuf();            
            // 设置选择过滤条件,只选择自定义实体。            
            filter.AddStringEx("ACAD_PROXY_ENTITY", 5020);
            MxDrawSelectionSet ss = new MxDrawSelectionSet();            
            // 得到所有自定义实体。            
            ss.AllSelect(filter);            
            // 遍历自定义实体
            for (Int32 i = 0; i < ss.Count; i++)
            {
                MxDrawEntity ent = ss.Item(i);
                MxDrawResbuf param = new MxDrawResbuf();
                param.AddObjectId(ent.ObjectID);               
                // 打碎自定义实体。               
                MxDrawResbuf ret = (MxDrawResbuf)axMxDrawX1.CallEx("Mx_Explode", param);               
                // 删除自定义实体。
                if(ret.AtString(0) == "Ok")
                  ent.Erase();
            }            
            // 把图纸所有内容都放到当前视区。
            axMxDrawX1.ZoomAll();

七、在块表记录中添加一个自定义实体

c#代码实现如下

      MxDrawDatabase database = (MxDrawDatabase)axMxDrawX1.GetDatabase();
      MxDrawBlockTableRecord blkRec = database.CurrentSpace();      
      // 调用AddCustomEntity函数绘制自定义实体。 逗号后的字符串"DrawCustEntity"是自定义实体的GUID
      MxDrawResbuf ret =blkRec.GetProp("AddCustomEntity,DrawCustEntity");      
      // 得到自定义实体。      
      MxDrawCustomEntity ent = (MxDrawCustomEntity)database.ObjectIdToObject(ret.AtObjectId(0));      
      // 设置自定义实体的属性。      
      ent.BeginSetValue();
      ent.SetDouble("Width", 30);

      MxDrawPoint pt1 = new MxDrawPoint();
      pt1.x = 10;
      pt1.y = 10;
      MxDrawPoint pt2 = new MxDrawPoint();

      pt2.x = 20;
      pt2.y = 20;
      ent.SetPoint("Point1", pt1);
      ent.SetPoint("Point2", pt2);

      ent.SetLong("Count", 2);
      ent.EntSetValue();

qq1254582201 发表于 2019-6-21 00:48:13

厉害,学习了自定义实体

xiaoniao7619 发表于 2019-7-17 20:40:07

楼主应该多介绍下 这个软件啊
页: [1]
查看完整版本: 梦想CAD控件自定义实体实现