在控件中除了内置的直线,圆,文字等实体外,开发人员还可以增加自定义实体。点击此处在线演示。
调用控件函数:DrawCustomEntity直接在图上,绘制自定义实体,如下js代码:
function button2_Click()
{
// 调用DrawCustomEntity绘制一个自定义实体,实体类型字符串为:DrawCustEntity
var ent = mxOcx.DrawCustomEntity("DrawCustEntity","");
// 开始设置自定义实体的属性。
ent.BeginSetValue();
// 设置属性Width
ent.SetDouble("Width", 30);
var pt1 = mxOcx.NewPoint();
pt1.x = 10;
pt1.y = 10;
var pt2 = mxOcx.NewPoint();
pt2.x = 100;
pt2.y = 200;
// 设置属性Point1,Point2
ent.SetPoint("Point1", pt1);
ent.SetPoint("Point2", pt2);
ent.SetLong("Count", 2);
// 结束设置自定义实体的属性。
ent.EntSetValue();
// 更新显示
mxOcx.UpdateDisplay();
}
下面函数MyDrawMline,用来具体绘制自定义实体,将用在后面的事件中调用。
// MyDrawMline,用来绘制我们的自定义实体
function MyDrawMline(pWorldDraw, pCustomEntity, curPt)
{ var mxOcx = document.getElementById("MxDrawXCtrl");
// 取自定义实体的端点数目。
if (!pCustomEntity.IsHave("Count"))
return;
var lCount = pCustomEntity.GetLong("Count");
var tmpPl = mxOcx.NewEntity("IMxDrawPolyline");
//var tmpPl = new MxDrawPolyline();
for (var i = 0; i < lCount; i++)
{
var sName;
sName = "Point" + (i + 1).toString();
if (!pCustomEntity.IsHave(sName))
break;
// 取自定义实体的端点坐标。
var pt = pCustomEntity.GetPoint(sName);
// 把端点坐标,传给pl线,用于生成双线。
tmpPl.AddVertexAt(pt);
}
if (curPt != null)
tmpPl.AddVertexAt(curPt);
if (tmpPl.NumVerts < 2)
{
// 端点数少于2就,不构成直线,就不需要显示。
return;
}
// 求pl线,开始点的导数.
var vecFx = tmpPl.GetFirstDeriv2(tmpPl.GetStartParam());
if (!vecFx)
return;
if (vecFx.IsZeroLength())
return;
// 把向量旋转90度.
vecFx.RotateByXyPlan(3.14159265 / 2.0);
vecFx.Normalize();
// 得到双线的宽度属性。
var dWidth = pCustomEntity.GetDouble("Width");
vecFx.Mult(dWidth);
var startPt = tmpPl.GetStartPoint();
// 向pl线,两个方向偏移,
var offsetPt1 = mxOcx.NewPoint();
offsetPt1.x = startPt.x;
offsetPt1.y = startPt.y;
offsetPt1.Add(vecFx);
var offsetPt2 = mxOcx.NewPoint();
offsetPt2.x = startPt.x;
offsetPt2.y = startPt.y;
offsetPt2.Sum(vecFx);
var text = mxOcx.NewEntity("IMxDrawText");
text.TextString = "Test";
text.Height = 100;
text.Position = startPt;
text.AlignmentPoint = startPt;
var pt1 = mxOcx.NewPoint();
var pt2 = mxOcx.NewPoint();
text.GetBoundingBox(pt1,pt2);
var pt3 = mxOcx.NewPoint();
pt3.x = pt1.x;
pt3.y = pt2.y;
var pt4 = mxOcx.NewPoint();
pt4.x = pt2.x;
pt4.y = pt1.y;
var pts = mxOcx.NewComObject("IMxDrawPoints");
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);
var lDraworder = pWorldDraw.Draworder;
pWorldDraw.Draworder = lDraworder + 1;
pWorldDraw.DrawWipeout(pts);
pWorldDraw.Draworder = lDraworder + 2;
pWorldDraw.DrawEntity(text);
pWorldDraw.Draworder = lDraworder;
{
var newobj =tmpPl.OffsetCurves2(dWidth, offsetPt1);
if (newobj)
{
for (var j = 0; j < newobj.Count; j++)
{
var tmpObj = newobj.AtObject(j);
if (tmpObj == null)
continue;
pWorldDraw.DrawEntity(tmpObj);
}
newobj.RemoveAll();
}
}
{
var newobj =tmpPl.OffsetCurves2(dWidth, offsetPt2);
if (newobj)
{
for (var j = 0; j < newobj.Count; j++)
{
var tmpObj = newobj.AtObject(j);
if (tmpObj == null)
continue;
pWorldDraw.DrawEntity(tmpObj);
}
// 这不使用newobj,需要显示调用RemoveAll函数清楚内存。
// 不然这个可能就会程序退出时才释放,这时它会去释放控件对象指针,有可能会出错。
newobj.RemoveAll();
}
}
}下面代码让用户在图上循环点取点坐标,直接到按ESC退出,然后绘制自定义实体,在点取点过程中可以看动态画制效果,js代码实现如下:
function DrawMlineCommand()
{
// 定义取点变量。
//MxDrawUiPrPoint getPt = new MxDrawUiPrPoint();
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(false);
// 设置在取点时的动态绘制.
var spDrawData = getSecondPt.InitUserDraw("DrawCustEntity");
// 设置绘制变量。Width,Point1
spDrawData.SetDouble("Width", 30);
spDrawData.SetPoint("Point1", frstPt);
var lCount = 1;
spDrawData.SetLong("Count", 1);
// 循环取点,直到用户按ESC取消.
while (true)
{
if (getSecondPt.go() != 1)
break;
var secondPt = getSecondPt.value();
if (secondPt == null)
break;
lCount++;
var sPointName = "Point" + lCount.toString();
spDrawData.SetPoint(sPointName, secondPt);
spDrawData.SetLong("Count", lCount);
}
// 把自定义实本对象spDrawData画在图上。
if (lCount > 1)
mxOcx.DrawEntity(spDrawData);
}
添加控件DynWorldDraw事件,在事件中响应自定义实体的动态绘制
document.getElementById("MxDrawXCtrl").ImpDynWorldDrawFun = DoDynWorldDrawFun;js代码实现如下:
function DoDynWorldDrawFun(dX,dY,pWorldDraw, pData, pRet)
{ var mxOcx = document.getElementById("MxDrawXCtrl");
// 得到当前动态绘制数据。
var pCustomEntity = pData;
var sGuid = pCustomEntity.Guid;
pRet = 0;
// 得到当前鼠标点.
var curPt = mxOcx.NewPoint();
curPt.x = dX;
curPt.y = dY;
if (sGuid == "DrawCustEntity")
{
// 动态绘制DrawCustEntity
MyDrawMline(pWorldDraw, pCustomEntity, curPt);
}
}需要添加DMxDrawXEvents::CustomEntity_Explode事件,绘制自定义实体
document.getElementById("MxDrawXCtrl").ImpExplodeFun = ExplodeFun;注意:该事件必须实现,如果不实现自定义实体将不会保存到图纸中。
如:js代码实现如下:
function ExplodeFun(pCustomEntity,pWorldDraw, pRet)
{
// 得到自定义实体类型
var sGuid = pCustomEntity.Guid;
if (sGuid == "DrawCustEntity")
{
// 绘制自定义实体.
MyDrawMline(pWorldDraw, pCustomEntity, null);
pRet = 1;
}
}自定义实体支持夹点编辑,下面事件返回实体的夹点
需要响应_DMxDrawXEvents::CustomEntity_getGripPoints事件
document.getElementById("MxDrawXCtrl").ImpGetGripPointsFun = GetGripPointsFun;js代码实现如下:
function GetGripPointsFun(pCustomEntity, pOk)
{var mxOcx = document.getElementById("MxDrawXCtrl");
// 得到自定实体类型
var sGuid = pCustomEntity.Guid;
pOk = 0;
if (sGuid == "DrawCustEntity")
{
if (!pCustomEntity.IsHave("Count"))
return;
var lCount = pCustomEntity.GetLong("Count");
// 把需要的夹点数据,放在ret链表中,用于返回
var ret = mxOcx.NewResbuf();
for (var i = 0; i < lCount; i++)
{
var sName;
sName = "Point" + (i + 1).toString();
if (!pCustomEntity.IsHave(sName))
break;
// 取自定义实体的端点坐标。
var pt = pCustomEntity.GetPoint(sName);
ret.AddPoint(pt);
}
pOk = 1;
// 返回夹点数据。
mxOcx.SetEventRetEx(ret);
}
}自定义实体夹点移动后,调用moveGripPointsAt事件修改自定义实体。
响应CustomEntity_moveGripPointsAt事件
document.getElementById("MxDrawXCtrl").ImpMoveGripPointsAtFun = MoveGripPointsAtFun;下面例子夹点移动后,在moveGripPointsAt修改自定义实体的点坐标,js代码实现如下:
function MoveGripPointsAtFun(pCustomEntity, lGridIndex, dOffsetX, dOffsetY)
{
pRet = 1;
// 得到自定义实体对像.
var sGuid = pCustomEntity.Guid;
if (sGuid == "DrawCustEntity")
{
if (!pCustomEntity.IsHave("Count"))
return;
var lCount = pCustomEntity.GetLong("Count");
for (var i = 0; i < lCount; i++)
{
var sName;
sName = "Point" + (i + 1).toString();
if (!pCustomEntity.IsHave(sName))
break;
// 取自定义实体的端点坐标。
var pt = pCustomEntity.GetPoint(sName);
// e.lGridIndex表示移动了第几个夹点.
if (i == lGridIndex)
{
pt.x = pt.x + dOffsetX;
pt.y = pt.y + dOffsetY;
// 修改移动后的点坐标值。
pCustomEntity.SetPoint(sName, pt);
}
}
}
}想要支持自定义实体的移动,旋转,缩放功能,需要添加坐标变换事件处理,事件名:CustomEntity_transformBy
document.getElementById("MxDrawXCtrl").ImpTransformByFun = TransformByFun;
函数实现js代码如下:
function TransformByFun(pCustomEntity, pMatXform, pOk)
{
pOk = 1;
// 得到自定义实体类型
var sGuid = pCustomEntity.Guid;
if (sGuid == "DrawCustEntity")
{
if (!pCustomEntity.IsHave("Count"))
return;
var lCount = pCustomEntity.GetLong("Count");
// 对实体的点坐标进行坐标变换。
for (var i = 0; i < lCount; i++)
{
var sName;
sName = "Point" + (i + 1).toString();
if (!pCustomEntity.IsHave(sName))
break;
// 取自定义实体的端点坐标。
var pt = pCustomEntity.GetPoint(sName);
// 计算出新的坐标。
pt.TransformBy(pMatXform);
pCustomEntity.SetPoint(sName, pt);
}
}
}