在wpf中获取窗口内元素的绝对位置


88

我想获得一个元素相对于window / root元素在双击时的绝对位置。元素在其父元素中的相对位置是我似乎可以到达的所有位置,而我试图到达的是相对于窗口的点。我已经看到了如何在屏幕上而不是在窗口中获得元素点的解决方案。

Answers:


127

我认为BrandonS想要的不是鼠标相对于根元素的位置,而是某些后代元素的位置。

为此,有TransformToAncestor方法:

Point relativePoint = myVisual.TransformToAncestor(rootVisual)
                              .Transform(new Point(0, 0));

myVisual刚刚双击的元素在哪里,rootVisualApplication.Current.MainWindow或您想要相对的位置。


2
嗨,我尝试了此操作,但收到以下异常:System.InvalidOperationException未处理Message =指定的Visual不是此Visual的祖先。Source = PresentationCore有什么想法吗?
RoflcoptrException

8
仅当您传递包含Visual的Visual.TransformToAncestor时才有效。如果要两个元素的相对位置,而一个元素不包含另一个元素,则可以使用Visual.TransformToVisual。
罗伯特·麦克妮

5
TransformToVisual仍然需要一个共同的祖先,如果控件在弹出窗口中,则可能会出现问题
Adam Mills

1
超级直观!他们不能将其包装在“ GetRelativePosition”调用中吗?:-) 谢谢您的帮助。+1
保罗

1
@ cod3monk3y-也许,如果微软开源WPF,我会向他们发送拉取请求:-)
Paul

41

要获取窗口中UI元素的绝对位置,可以使用:

Point position = desiredElement.PointToScreen(new Point(0d, 0d));

如果您位于用户控件内,并且只希望UI元素在该控件内的相对位置,则只需使用:

Point position = desiredElement.PointToScreen(new Point(0d, 0d)),
controlPosition = this.PointToScreen(new Point(0d, 0d));

position.X -= controlPosition.X;
position.Y -= controlPosition.Y;

4
请注意,如果您的显示比例未设置为100%(即在高DPI屏幕上),这可能无法达到您的期望。
德鲁·诺阿克斯

18

将此方法添加到静态类中:

 public static Rect GetAbsolutePlacement(this FrameworkElement element, bool relativeToScreen = false)
    {
        var absolutePos = element.PointToScreen(new System.Windows.Point(0, 0));
        if (relativeToScreen)
        {
            return new Rect(absolutePos.X, absolutePos.Y, element.ActualWidth, element.ActualHeight);
        }
        var posMW = Application.Current.MainWindow.PointToScreen(new System.Windows.Point(0, 0));
        absolutePos = new System.Windows.Point(absolutePos.X - posMW.X, absolutePos.Y - posMW.Y);
        return new Rect(absolutePos.X, absolutePos.Y, element.ActualWidth, element.ActualHeight);
    }

relativeToScreen参数设置true为从整个屏幕的左上角放置,或false从应用程序窗口的左上角放置。


1
这棒极了!我将此动画与通过修改RenderTransform元素在屏幕上或屏幕外滑动图像的动画一起使用,因此它需要知道元素在屏幕上的绝对位置。
cod3monk3y 2015年

6

从.NET 3.0开始,您可以简单地使用*yourElement*.TranslatePoint(new Point(0, 0), *theContainerOfYourChoice*)

这将使按钮的点0、0指向容器。(您也可以给其他点指定0,0)

在此处查看文档。


0

嗯 您必须指定单击的窗口Mouse.GetPosition(IInputElement relativeTo) 以下代码对我来说效果很好

protected override void OnMouseDown(MouseButtonEventArgs e)
    {
        base.OnMouseDown(e);
        Point p = e.GetPosition(this);
    }

我怀疑您需要不是从它自己的类而是从应用程序的其他地方引用该窗口。在这种情况下Application.Current.MainWindow会为您提供帮助。


即使不是作者所要求的,它也使我走上了正确的道路,谢谢
Ladislav Ondris
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.