Получить абсолютное положение элемента в окне в wpf

88

Я хотел бы получить абсолютную позицию элемента по отношению к оконному / корневому элементу при двойном щелчке. Относительное положение элемента в родительском элементе - это все, что я могу понять, и я пытаюсь добраться до точки относительно окна. Я видел решения о том, как получить точку элемента на экране, но не в окне.

BrandonS
источник

Ответы:

127

Я думаю, что BrandonS хочет не положение мыши относительно корневого элемента, а положение некоторого дочернего элемента.

Для этого есть метод TransformToAncestor :

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

Где myVisualэлемент, по которому только что щелкнули двойным щелчком, и rootVisualэто Application.Current.MainWindow или любое другое положение относительно.

Роберт Макни
источник
2
Привет, я попробовал это и получил следующее исключение: System.InvalidOperationException не было обработано Сообщение = Указанный визуал не является предком этого визуала. Источник = PresentationCore Есть идеи?
RoflcoptrException
8
Visual.TransformToAncestor будет работать, только если вы передадите содержащий Visual. Если вам нужно относительное положение двух элементов, и один из них не содержит другого, вы можете вместо этого использовать Visual.TransformToVisual.
Роберт Макни,
5
TransformToVisual по-прежнему требует общего предка, что может быть проблематичным, если элемент управления находится во всплывающем окне
Адам Миллс
1
Супер интуитивно понятный! Разве они не могут заключить это в вызов GetRelativePosition? :-) Спасибо за помощь. +1
Пол
1
@ cod3monk3y - или, может быть, если Microsoft откроет WPF, я пришлю им запрос на перенос :-)
Пол
42

Чтобы получить абсолютное положение элемента пользовательского интерфейса в окне, вы можете использовать:

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

Если вы находитесь в пользовательском элементе управления и просто хотите относительное положение элемента пользовательского интерфейса в этом элементе управления, просто используйте:

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% (т.е. на экранах с высоким разрешением).
Дрю Ноукс,
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 05
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вам поможет.

Олег
источник
Несмотря на то, что это не то, о чем просил автор, это
привело