我有一个自定义控件,该控件呈现从左上角到右下角的贝塞尔曲线。我想修改命中测试行为,以便将控件悬停在贝塞尔曲线之上或附近,而只是“命中”,而FillContainsWithDetail
不会返回预期的结果。
我想念什么?
这是派生的示例类:
public class BezierControl : FrameworkElement
{
protected override HitTestResult HitTestCore(PointHitTestParameters hitTestParameters)
{
if (_geometry == null) return null;
var p = hitTestParameters.HitPoint;
EllipseGeometry expandedHitTestArea = new EllipseGeometry(p, 10.0, 10.0);
var intersection = expandedHitTestArea.FillContainsWithDetail(_geometry);
if (intersection > IntersectionDetail.Empty)
{
return new PointHitTestResult(this, hitTestParameters.HitPoint);
}
return null;
}
private StreamGeometry _geometry;
private StreamGeometry getGeometry()
{
var result = new StreamGeometry();
using (var context = result.Open())
{
var start = new Point(0, 0);
var startCp = new Point(10, 0);
var end = new Point(this.ActualWidth, this.ActualHeight);
var endCp = new Point(this.ActualWidth - 10, this.ActualHeight);
context.BeginFigure(start, false, false);
context.BezierTo(startCp, endCp, end, true, false);
}
result.Freeze();
return result;
}
protected override void OnRender(DrawingContext dc)
{
base.OnRender(dc);
if (_geometry == null) _geometry = getGeometry();
dc.DrawGeometry(null, _pen, _geometry);
}
private Pen _pen = new Pen(Brushes.Red, 1.0);
}
编辑:下面批准的答案很好,但这也使我想到了另一种选择-或向我展示了为什么我的解决方案失败了:我正在创建像这样的几何体:
context.BeginFigure(bezier.Start, false, false);
第一个bool
参数称为isFilled
。将此设置为true
可以使_geometry
和之间相交expandedHitTestArea
。
在注意到这一点之前,我在下面实现了可接受的答案,并widenedGeometry
出于性能原因决定懒惰地创建它。现在哪个让我感到困惑:从性能的角度来看,哪种方法更好?还是在这种情况下可以忽略不计,因为几何无论如何都是便宜的?
您不需要那个EllipseGeometry。只需检查命中点是否在原始几何图形的加宽路径几何图形内(当然,创建时也可以创建一次_geometry
):
protected override HitTestResult HitTestCore(PointHitTestParameters hitTestParameters)
{
if (_geometry != null)
{
var widenedGeometry = _geometry.GetWidenedPathGeometry(new Pen(null, 20));
if (widenedGeometry.FillContains(hitTestParameters.HitPoint))
{
return new PointHitTestResult(this, hitTestParameters.HitPoint);
}
}
return null;
}
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句