为什么Canvas上的TextBox的命中测试位置与其实际位置不同?

时间:2012-12-13 13:03:42

标签: wpf canvas textbox hittest

我有一个带有几个元素的画布,如Line,Path和Text Box。在Canvas的MouseOver事件中,所有人都有HitTest,例如:

bool HitTest( Point p )
{
  return VisualTreeHelper.HitTest( textBox, p ) != null;
}

这对行和路径的像素精确度有效,但对文本框不起作用。

例如,当TextBox位于50,50时,如下所示:

Canvas.SetLeft( textBox, 50.0 );
Canvas.SetTop( textBox, 50.0 );

正确地在该位置绘制:如果文本高约20像素,宽50像素,则屏幕上的边界矩形大致为L = 50 T = 50 R = 100 B = 70。

但是HitTest函数在该矩形中返回false,并且仅在矩形中返回true L = 0 T = 0 R = 50 B = 20。换句话说,命中测试知道文本框的大小,但忽略它不是位于0,0。

为什么会这样,以及如何解决? (我觉得这与定位Line和Path元素我不使用SetLeft / SetTop这一事实有关)

1 个答案:

答案 0 :(得分:2)

仅仅因为TextBox对于它位于Canvas中的事实一无所知,因此没有关于“实际位置”的事实。

当您致电VisualTreeHelper.HitTest(textBox, p)时,点p以相对于textBox视觉的坐标给出。在Canvas或TextBox所在的任何其他可能容器中的位置无关紧要。

你得到Line和Path的“正确”坐标(相对于你的画布)只是因为你没有在它们上设置Canvas.Left或Canvas.Top。

如果您需要相对于Canvas的坐标,通常会执行以下操作:

bool HitTest(UIElement element, Point p)
{
    var elementPoint = new Point(
        p.X - Canvas.GetLeft(element),
        p.Y - Canvas.GetTop(element));

    return VisualTreeHelper.HitTest(element, elementPoint) != null;
}

或者

bool HitTest(UIElement element, Point p)
{
    var elementPoint = canvas.TransformToDescendant(element).Transform(p);

    return VisualTreeHelper.HitTest(element, elementPoint) != null;
}