3

我试图检测鼠标光标下的控件,无论控件是否启用。

VisualTreeHelper.FindElementsInHostCoordinates忽略其IsEnabled属性设置为的控件false。有没有办法改变这种行为,或者有什么其他方法可以在特定的屏幕位置找到控件?

谢谢。

4

1 回答 1

1

您可以实现自己的递归方法来搜索子树并将每个元素转换为应用程序的根视觉对象,以获得其“绝对”边界,然后测试“绝对”鼠标点是否在该区域内。

这可能不是所需要的,但应该可以帮助您入门。我基本上用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);
于 2010-09-09T17:39:59.770 回答