รับตำแหน่งสัมบูรณ์ขององค์ประกอบภายในหน้าต่างใน wpf


89

ฉันต้องการรับตำแหน่งที่แน่นอนขององค์ประกอบที่สัมพันธ์กับองค์ประกอบของหน้าต่าง / รูทเมื่อคลิกสองครั้ง ตำแหน่งสัมพัทธ์ขององค์ประกอบภายในเป็นพาเรนต์คือทั้งหมดที่ฉันสามารถทำได้และสิ่งที่ฉันพยายามจะไปคือจุดที่สัมพันธ์กับหน้าต่าง ฉันเคยเห็นวิธีแก้ไขจุดขององค์ประกอบบนหน้าจอ แต่ไม่ใช่ในหน้าต่าง

คำตอบ:


130

ฉันคิดว่าสิ่งที่ BrandonS ต้องการไม่ใช่ตำแหน่งของเมาส์ที่สัมพันธ์กับองค์ประกอบราก แต่เป็นตำแหน่งขององค์ประกอบลูกหลานบางอย่าง

ด้วยเหตุนี้จึงมีวิธีTransformToAncestor :

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

myVisualองค์ประกอบที่เพิ่งคลิกสองครั้งอยู่ที่ไหนและrootVisualคือ Application.Current.MainWindow หรือสิ่งที่คุณต้องการให้ตำแหน่งสัมพันธ์กับ


3
สวัสดีฉันลองสิ่งนี้และได้รับข้อยกเว้นต่อไปนี้: System.InvalidOperationException is unhandled Message = Visual ที่ระบุไม่ใช่บรรพบุรุษของ Visual นี้ Source = PresentationCore ความคิดใด?
RoflcoptrException

8
Visual.TransformToAncestor จะใช้ได้ก็ต่อเมื่อคุณส่งผ่าน Visual. ถ้าคุณต้องการตำแหน่งสัมพัทธ์ของสององค์ประกอบและอีกองค์ประกอบหนึ่งไม่มีองค์ประกอบอื่นคุณสามารถใช้ Visual.TransformToVisual แทนได้
Robert Macnee

5
TransformToVisual ยังคงต้องการบรรพบุรุษร่วมกันซึ่งอาจเป็นปัญหาได้หากการควบคุมอยู่ในป๊อปอัป
Adam Mills

1
ใช้งานง่ายสุด ๆ ! พวกเขาไม่สามารถรวมสิ่งนี้ในการเรียก "GetRelativePosition" ได้หรือไม่ :-) ขอบคุณสำหรับความช่วยเหลือ +1
พอล

1
@ cod3monk3y - หรือบางทีถ้า Microsoft โอเพนซอร์ส WPF ฉันจะส่งคำขอให้ดึง :-)
พอล

43

หากต้องการรับตำแหน่งที่แน่นอนขององค์ประกอบ 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 สูง)
Drew Noakes

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

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
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.