Question

I would like to use the WPF HitTest ability on some shapes without showing them onscreen. Is this possible? This code doesn't work the way I expected it to. How do I make this work?

[Test, Ignore, RequiresSTA]
public void VerifyFillContains()
{
    // make a simple triangle:
    var seg1 = new System.Windows.Media.LineSegment(new Point(0.2, 0.1), false);
    var seg2 = new System.Windows.Media.LineSegment(new Point(0.3, 0.8), false);
    var figure = new PathFigure(new Point(0.7, 0.5), new List<PathSegment>{seg1, seg2}, true);

    var sg = new PathGeometry();
    sg.Figures.Add(figure);

    if (sg.CanFreeze)
        sg.Freeze();

    // these don't work:
    Assert.IsFalse(sg.FillContains(new Point()));
    Assert.IsFalse(sg.FillContains(new Point(1.0, 1.0)));
    Assert.IsTrue(sg.FillContains(new Point(0.5, 0.5)));

    var path = new Path { Data = sg, Fill = Brushes.Black };
    path.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity));
    path.Arrange(new Rect(path.DesiredSize));

    // and these don't work:
    var result = VisualTreeHelper.HitTest(path, new Point(0.0, 0.0));
    Assert.IsFalse(result != null && Equals(result.VisualHit, path));
    result = VisualTreeHelper.HitTest(path, new Point(1.0, 1.0));
    Assert.IsFalse(result != null && Equals(result.VisualHit, path));
    result = VisualTreeHelper.HitTest(path, new Point(0.5, 0.5));
    Assert.IsTrue(result != null && Equals(result.VisualHit, path));
}
Was it helpful?

Solution

The hit testing is based on the rendering of the element so you should either measure and arrange shape. e.g.

shape.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity));
shape.Arrange(new Rect(shape.DesiredSize));

Or you could just use the FillContains method of the Geometry. e.g.

var result = shape.Data.FillContains(ToPoint(target));

OTHER TIPS

I think your CreateWpfShapeFromList must implemented AddVisualChild methord to your shape's visual children.

Because i reflected VisualTreeHelper and found HitTest use GetVisualChild interanlly, so try my solution.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top