您可以实现自己的递归方法来搜索子树,并将每个元素转换为应用程序的根可视化,以获得其“绝对”边界,然后测试“绝对”鼠标点是否在该区域内。
确切地
FindElementsInHostCoordinates
具有相同的签名,因此可以在MouseMove处理程序中以相同的方式使用它。此方法只尝试“命中测试”FrameworkElements,因为它需要知道ActualWidth和ActualHeight来计算命中区域。
private IEnumerable<UIElement> FindAllElementsInHostCoordinates(Point intersectingPoint, UIElement subTree)
{
var results = new List<UIElement>();
int count = VisualTreeHelper.GetChildrenCount(subTree);
for (int i = 0; i < count; i++)
{
var child = VisualTreeHelper.GetChild(subTree, i) as FrameworkElement;
if (child != null)
{
GeneralTransform gt = child.TransformToVisual(Application.Current.RootVisual as UIElement);
Point offset = gt.Transform(new Point(0, 0));
Rect elementBounds = new Rect(offset.X, offset.Y, child.ActualWidth, child.ActualHeight);
if (IsInBounds(intersectingPoint, elementBounds))
{
results.Add(child as UIElement);
}
}
results.AddRange(FindAllElementsInHostCoordinates(intersectingPoint, child));
}
return results;
}
private bool IsInBounds(Point point, Rect bounds)
{
if (point.X > bounds.Left && point.X < bounds.Right &&
point.Y < bounds.Bottom && point.Y > bounds.Top)
{
return true;
}
return false;
}
然后您只需要确保从MouseMove处理程序传入的点与
Application.Current.RootVisual
IEnumerable<UIElement> elements = FindAllElementsInHostCoordinates(e.GetPosition(Application.Current.RootVisual), this);