调用控件函数: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
函数实现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);
}
}
如果需要捕捉自定义实体的端点,最近点等,需要响应捕捉事件: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;
}
}
}
}运行效果如下图 :
