Nhận vị trí tuyệt đối của phần tử trong cửa sổ trong wpf


88

Tôi muốn có được vị trí tuyệt đối của một phần tử liên quan đến phần tử window / root khi nó được nhấp đúp. Vị trí tương đối của phần tử bên trong phần tử gốc của nó là tất cả những gì tôi có thể có được và những gì tôi đang cố gắng đạt được là điểm liên quan đến cửa sổ. Tôi đã thấy các giải pháp về cách lấy điểm của một phần tử trên màn hình, nhưng không phải trong cửa sổ.

Câu trả lời:


127

Tôi nghĩ những gì BrandonS muốn không phải là vị trí của chuột so với phần tử gốc, mà là vị trí của một phần tử con cháu nào đó.

Đối với điều đó, có phương thức TransformToAncestor :

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

Trong trường hợp myVisuallà yếu tố đã được chỉ cần kích đúp nhấn vào, và rootVisuallà Application.Current.MainWindow hoặc bất cứ điều gì bạn muốn vị trí tương đối để.


2
Xin chào, tôi đã thử điều này và tôi nhận được ngoại lệ sau: System.InvalidOperationException đã được xử lý Thông báo = Visual được chỉ định không phải là tổ tiên của Visual này. Nguồn = PresentationCore Bất kỳ ý tưởng?
RoflcoptrException

8
Visual.TransformToAncestor sẽ chỉ hoạt động nếu bạn chuyển vào Visual có chứa. Nếu bạn muốn vị trí tương đối của hai phần tử và một phần tử không chứa phần tử kia, bạn có thể sử dụng Visual.TransformToVisual để thay thế.
Robert Macnee

5
TransformToVisual vẫn đòi hỏi một tổ tiên chung mà có thể là vấn đề nếu sự kiểm soát là trong một popup
Adam Mills

1
Siêu trực quan! Họ không thể gói điều này trong một cuộc gọi "GetRelativePosition"? :-) Cảm ơn đã giúp đỡ. +1
Paul

1
@ cod3monk3y - hoặc có thể, nếu Microsoft nguồn mở WPF, tôi sẽ gửi cho họ một yêu cầu kéo :-)
Paul

41

Để có được vị trí tuyệt đối của một phần tử giao diện người dùng trong cửa sổ, bạn có thể sử dụng:

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

Nếu bạn đang ở trong Kiểm soát người dùng và chỉ muốn vị trí tương đối của phần tử giao diện người dùng trong kiểm soát đó, chỉ cần sử dụng:

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

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

4
Lưu ý rằng điều này có thể không thực hiện những gì bạn mong đợi nếu tỷ lệ hiển thị của bạn không được đặt thành 100% (tức là trên màn hình DPI cao).
Drew Noakes

18

Thêm phương thức này vào một lớp tĩnh:

 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);
    }

Đặt relativeToScreenparamater truecho vị trí từ góc trên cùng bên trái của toàn bộ màn hình hoặc falsecho vị trí từ góc trên bên trái của cửa sổ ứng dụng.


1
Điều này hoạt động tuyệt vời! Tôi đang sử dụng điều này với một hoạt ảnh trình chiếu hình ảnh trên hoặc ngoài màn hình bằng cách sửa đổi RenderTransformphần tử và do đó nó cần biết vị trí tuyệt đối của phần tử trên màn hình.
cod3monk3y

6

Kể từ .NET 3.0, bạn có thể đơn giản sử dụng *yourElement*.TranslatePoint(new Point(0, 0), *theContainerOfYourChoice*).

Điều này sẽ cung cấp cho bạn điểm 0, 0 của nút của bạn, nhưng hướng tới vùng chứa. (Bạn cũng có thể đưa ra một điểm khác là 0, 0)

Kiểm tra ở đây cho tài liệu.


0

Hừm. Bạn phải chỉ định cửa sổ bạn đã nhấp vào Mouse.GetPosition(IInputElement relativeTo) Mã sau hoạt động tốt cho tôi

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

Tôi nghi ngờ rằng bạn cần phải tham chiếu đến cửa sổ không phải từ lớp riêng của nó mà từ điểm khác của ứng dụng. Trong trường hợp Application.Current.MainWindownày sẽ giúp bạn.


Mặc dù nó không phải là những gì tác giả yêu cầu, nó đã cho tôi đi đúng hướng, nhờ
Ladislav Ondris
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.