2010-08-30 26 views
5

Cách chính xác để truy xuất vị trí của cửa sổ trong WPF là gì?Cửa sổ ActualTop, ActualLeft

Đây là một số nỗ lực tôi đã thực hiện. Lần đầu tiên, rõ ràng là

Point GetPosition(Window win) 
{ 
    return new Point(win.Top, win.Left); 
} 

nhưng điều này trả về vị trí "sai" khi cửa sổ được phóng to. nỗ lực thứ hai:

Point GetPosition(Window win) 
{ 
    if (win.WindowState == WindowState.Maximized) 
     return new Point(0, 0); 
    else 
     return new Point(win.Top, win.Left); 
} 

Hầu như ở đó, nhưng vẫn còn là một vấn đề: khi bạn có hai (hoặc nhiều hơn) màn hình và cửa sổ là tối đa trong màn hình thứ hai bạn sẽ có được một (0, 0) vị trí đó không làm phản ánh vị trí thực tế của cửa sổ.

Tôi nhận thấy rằng Window có _actualTop và _actualTính viên riêng tư, nhưng không có thuộc tính công khai để hiển thị chúng.

Làm cách nào để bạn lấy giá trị chính xác?

Trả lời

3

Có, vụng về. Bạn có vấn đề lớn hơn, (0, 0) sẽ không hợp lệ ngay cả trên màn hình chính nếu người dùng đặt thanh tác vụ ở bên trái hoặc trên cùng. Như tôi đã làm. Bạn có thể nhận trợ giúp từ lớp Windows Forms Screen. Sử dụng phương thức FromPoint() của nó, sau đó là thuộc tính WorkingArea. Hoặc thuộc tính Bounds nếu bạn cho phép cửa sổ chuyển sang chế độ toàn màn hình.

Cá nhân, tôi chỉ cần P/Gọi GetWindowRect().

+0

Cảm ơn Hans, P/Invoking GetWindowRect() thực sự giải quyết được vấn đề. Không quá đẹp nhưng hoạt động như mong đợi. Cảm ơn một lần nữa! –

+0

Điều gì sai với 'Point leftTop = this.PointToScreen (điểm mới (0, 0));'? – springy76

+0

Khác với nó không phải là mã WPF, chỉ cần thử nó và đặt thanh tác vụ ở bên trái. –

13

Bạn có thể sử dụng phản ánh nếu bạn không muốn dựa vào Winforms hoặc PI

private double GetWindowLeft(Window window) 
    { 
     if (window.WindowState == WindowState.Maximized) 
     { 
      var leftField = typeof(Window).GetField("_actualLeft", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance); 
      return (double)leftField.GetValue(window); 
     } 
     else 
      return window.Left; 
    } 
+0

hoạt động hoàn hảo. Bạn cũng có thể lấy vị trí 'Top' theo cùng một cách (_actualTop) –

3

Dưới đây là một giải pháp mà được xây dựng trên P/Invoke của GetWindowRect, nhưng sử dụng phương pháp khuyến nông để làm cho mã của bạn trông đẹp hơn. Bạn sử dụng myWindow.ActualTop() và myWindow.ActualLeft() trong mã của bạn.

static class WindowExtensions 
{ 
    [StructLayout(LayoutKind.Sequential)] 
    struct RECT 
    { 
     public int Left; 
     public int Top; 
     public int Right; 
     public int Bottom; 
    } 
    [DllImport("user32.dll")] 
    [return: MarshalAs(UnmanagedType.Bool)] 
    static extern bool GetWindowRect(IntPtr hWnd, out RECT lpRect); 


    public static double ActualTop(this Window window) 
    { 
     switch (window.WindowState) 
     { 
      case WindowState.Normal: 
       return window.Top; 
      case WindowState.Minimized: 
       return window.RestoreBounds.Top; 
      case WindowState.Maximized: 
       { 
        RECT rect; 
        GetWindowRect((new WindowInteropHelper(window)).Handle, out rect); 
        return rect.Top; 
       } 
     } 
     return 0; 
    } 
    public static double ActualLeft(this Window window) 
    { 
     switch (window.WindowState) 
     { 
      case WindowState.Normal: 
       return window.Left; 
      case WindowState.Minimized: 
       return window.RestoreBounds.Left; 
      case WindowState.Maximized: 
       { 
        RECT rect; 
        GetWindowRect((new WindowInteropHelper(window)).Handle, out rect); 
        return rect.Left; 
       } 
     } 
     return 0; 
    } 
}