我有一个带有几个元素的画布,如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这一事实有关)
答案 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;
}