使用鼠标事件代替Jig进行拖拽

什么是事件代替Jig?

这里说的事件指的是Editor.PointMonitor事件,利用事件加瞬态的方式,使用户不用写Jig直接用交互就可以写预览。

这样做的好处有什么?

准确性

众所周知,对象捕捉在CAD里是一个非常重要的东西,如果没有对象捕捉画图将会寸步难行。而在DrawJig中,AquirePoint拿到的鼠标点是对象捕捉前的点,而不是鼠标被捕捉吸附过去的位置,虽然点击了左键之后的最终结果没影响,但是在预览的时候会有较大的影响,而使用PointMoniter事件,通过ComputedPoint不但可以拿到吸附后的鼠标点,还可以知道当前是否吸附到了最近点、端点、或中点上,然后通过端点中点等参数实现更多的操作。

便捷性

使用PointMonitor事件,在代码上比Jig方式并未增加理解负担。
且大部分开发者肯定对GetPoint更加熟悉,在已经掌握GetPoint的情况下如果从0开始学习拖拽预览,那么使PointMonitor事件对比Jig从学习难度上是要更低的。
而且将一个无拖拽效果的功能改成有拖拽效果用事件也比Jig能更快的兼容,代码修改量更小。
顺便把瞬态也学了,后面还能用的上。
关键字的处理也不用纠结了,因为使用Jig会涉及到关键字是返回None还是返回Keyword空字符串的问题。

更好的预览

经验充足的开发者可能会发现一个问题,在Jig中显示多段线,会经常出现看不清的问题,而在瞬态中就可以清楚的预览,使用PointMonitor事件需要配合瞬态正好可以规避这个问题。并且使用瞬态可以更容易的实现高亮预览。

更强大的功能

相比Jig只能拿到鼠标点,PointMonitor事件可以同时拿到鼠标点和吸附点。
并且还可以直接通过事件拿到吸附的对象和嵌套关系,以实现更复杂的需求,或者让Jig不容易做的需求变得更简单。

缺点

目前能想到的缺点是不能定义鼠标的样式了,使用Jig可以切换鼠标指针样式,虽然Jig是在拾取点,但是可以把鼠标样式改为选择对象,或者各种其他的格式。虽然说作用不大吧,一般不会这样干。

那么要如何操作呢?

首先是要对PointMonitor事件进行封装,封装成委托的方式,此举动是为了事件能拿到方法的上下文。
具体可以看我的项目封装好的。PointMonitorEventTool

我将通过一些小例子举出他们的区别

两种方式实现画一条直线加一个圆

使用Jig方式

var ed = Env.Editor;
var r1 = ed.GetPoint("\n选择点");
if(r1.Status != PromptStatus.OK)
    return;
var pt1 = r1.Value.Ucs2Wcs();
using var line = new Line(pt1, pt1);
using var j2 = new JigEx((mpw, _) =>
{
    line.EndPoint = mpw;
});
j2.DatabaseEntityDraw(wd => wd.Geometry.Draw(line));
j2.SetOptions(pt1, CursorType.RubberBand, "\n选择下一点");
var r2 = ed.Drag(j2);
if(r2.Status != PromptStatus.OK)
    return;
using var tr = new DBTrans();
tr.CurrentSpace.AddEntity(line);

PointMonitor1.png

使用PointMonitor事件

var ed = Env.Editor;
var r1 = ed.GetPoint("\n选择点");
if (r1.Status != PromptStatus.OK)
    return;
var pt1 = r1.Value.Ucs2Wcs();
using var line = new Line(pt1, pt1);
using var jet = new JigExTransient();
jet.Add(line);
using var d1 = ed.ListenPointMonitor(args =>
{
    line.EndPoint = args.Context.ComputedPoint;
    jet.Update(line);
});
var r2 = ed.GetPoint(
    new PromptPointOptions("\n选择下一点") { UseBasePoint = true, BasePoint = r1.Value });
if (r2.Status != PromptStatus.OK)
    return;
using var tr = new DBTrans();
tr.CurrentSpace.AddEntity(line);

PointMonitor2.png

可以看出两种虽然都吸附到了,但是实际显示效果是不一样的,用事件可以让对象更好的显示在吸附点上。


并且通过鼠标事件,可以拿到更多的参数,可以拿到鼠标吸附对象的Id,以实现更多的功能。