2011-01-26 41 views
11

Tôi cần biết vị trí của cửa sổ được phóng to.Làm cách nào để tìm vị trí của cửa sổ được phóng to?

Cửa sổ WPF có thuộc tính trên cùng và bên trái chỉ định vị trí của cửa sổ. Tuy nhiên, nếu bạn phóng to cửa sổ, các thuộc tính này giữ cho các giá trị của cửa sổ ở trạng thái bình thường.

Nếu bạn đang chạy trên một thiết lập một màn hình, vị trí tối đa là tự nhiên (0,0). Tuy nhiên, nếu bạn có nhiều màn hình không nhất thiết phải đúng. Cửa sổ sẽ chỉ có vị trí (0,0) nếu bạn có nó tối đa trên màn hình chính.

Vì vậy, ... có cách nào để tìm ra vị trí của cửa sổ tối đa hay không (tốt nhất là trong cùng một đơn vị lôgíc như thuộc tính Trên cùng và Bên trái)?

Trả lời

0

Tôi nhận thấy rằng bạn đang làm việc trong WPF và câu trả lời này sử dụng công nghệ Biểu mẫu, nhưng nó sẽ hoạt động mà không gặp nhiều khó khăn.

Bạn có thể tải bộ sưu tập màn hình thông qua My.Settings.Screens.AllScreens. Từ đó bạn có thể truy cập vào độ phân giải mà màn hình hiện đang hoạt động.

Vì các cửa sổ WPF giữ lại các giá trị trên cùng/bên trái khi chúng được phóng to, bạn có thể xác định màn hình của chúng bằng cách tìm ra màn hình mà tọa độ Top/Left tham chiếu, và sau đó lấy đầu/trái phối hợp cho màn hình đó.

Thật không may, tôi đang trên đường và không thể kiểm tra điều này vào lúc này. Nếu bạn thực hiện, tôi rất thích nhìn thấy những gì bạn nghĩ ra.

7

cuối cùng tôi đã tìm thấy một giải pháp làm việc cho tôi: (! Thanks)

private System.Drawing.Rectangle getWindowRectangle() 
{ 
    System.Drawing.Rectangle windowRectangle; 

    if (this.WindowState == System.Windows.WindowState.Maximized) 
    { 
     /* Here is the magic: 
     * Use Winforms code to find the Available space on the 
     * screen that contained the window 
     * just before it was maximized 
     * (Left, Top have their values from Normal WindowState) 
     */ 
     windowRectangle = System.Windows.Forms.Screen.GetWorkingArea(
      new System.Drawing.Point((int)this.Left, (int)this.Top)); 
    } 
    else 
    { 
     windowRectangle = new System.Drawing.Rectangle(
      (int)this.Left, (int)this.Top, 
      (int)this.ActualWidth, (int)this.ActualHeight); 
    } 

    return windowRectangle; 
} 
+2

Tôi nghĩ nếu bạn thay đổi lệnh gọi GetWorkingArea thành: windowRectangle = System.Windows.Forms.Screen.GetWorkingArea (cửa sổ System.Drawing.Point ((int) mới.Left + (int) (window.ActualWidth/2), (int) window.Top + (int) (window.ActualHeight/2))); sẽ sửa nó. Bạn cần phải lấy trung tâm của cửa sổ, không phải là điểm yếu, bởi vì đó là điểm mà WPF sử dụng để xác định cửa sổ nào sẽ tối đa hóa, nếu cửa sổ nằm ngang qua nhiều màn hình. – Matt

+1

ý tưởng hay, nhưng điều này có thực sự hữu ích không? nhánh này của mệnh đề if chỉ được sử dụng khi WindowState được tối đa hóa, vì vậy ActualWith và -Height sẽ có kích thước màn hình, không phải là (restore) windowsize – eFloh

+0

Vâng, tôi hiểu những gì bạn đang nói. bạn có thể nhận được kích thước cửa sổ khôi phục từ RestoreBounds và sau đó sử dụng thay vì ActualWidth/ActualHeight có lẽ? – Matt

6

Đây là giải pháp tôi đưa ra dựa trên thảo luận trước đây.

Giải pháp này ...

  • trả về vị trí của một cửa sổ trong tình trạng hiện thời của nó
  • xử lý tất cả các quốc gia cửa sổ (tối đa, giảm thiểu, phục hồi)
  • không phụ thuộc vào Windows Forms (nhưng được lấy cảm hứng từ nó)
  • sử dụng tay cầm cửa sổ để xác định chính xác màn hình chính xác

Muối chính od GetAbsolutePosition được triển khai ở đây dưới dạng một phương thức mở rộng. Nếu bạn có một Window gọi myWindow, gọi nó là như thế này:

Point p = myWindow.GetAbsolutePosition(); 

Dưới đây là đoạn code hoàn chỉnh:

using System; 
using System.Windows; 
using System.Windows.Interop; 
using System.Runtime.InteropServices; 

static class OSInterop 
{ 
    [DllImport("user32.dll")] 
    public static extern int GetSystemMetrics(int smIndex); 
    public const int SM_CMONITORS = 80; 

    [DllImport("user32.dll")] 
    public static extern bool SystemParametersInfo(int nAction, int nParam, ref RECT rc, int nUpdate); 

    [DllImport("user32.dll", CharSet = CharSet.Auto)] 
    public static extern bool GetMonitorInfo(HandleRef hmonitor, [In, Out] MONITORINFOEX info); 

    [DllImport("user32.dll")] 
    public static extern IntPtr MonitorFromWindow(HandleRef handle, int flags); 

    public struct RECT 
    { 
     public int left; 
     public int top; 
     public int right; 
     public int bottom; 
     public int width { get { return right - left; } } 
     public int height { get { return bottom - top; } } 
    } 

    [StructLayout(LayoutKind.Sequential, Pack = 4, CharSet = CharSet.Auto)] 
    public class MONITORINFOEX 
    { 
     public int cbSize = Marshal.SizeOf(typeof(MONITORINFOEX)); 
     public RECT rcMonitor = new RECT(); 
     public RECT rcWork = new RECT(); 
     [MarshalAs(UnmanagedType.ByValArray, SizeConst = 32)] 
     public char[] szDevice = new char[32]; 
     public int dwFlags; 
    } 
} 

static class WPFExtensionMethods 
{ 
    public static Point GetAbsolutePosition(this Window w) 
    { 
     if (w.WindowState != WindowState.Maximized) 
      return new Point(w.Left, w.Top); 

     Int32Rect r; 
     bool multimonSupported = OSInterop.GetSystemMetrics(OSInterop.SM_CMONITORS) != 0; 
     if (!multimonSupported) 
     { 
      OSInterop.RECT rc = new OSInterop.RECT(); 
      OSInterop.SystemParametersInfo(48, 0, ref rc, 0); 
      r = new Int32Rect(rc.left, rc.top, rc.width, rc.height); 
     } 
     else 
     { 
      WindowInteropHelper helper = new WindowInteropHelper(w); 
      IntPtr hmonitor = OSInterop.MonitorFromWindow(new HandleRef((object)null, helper.EnsureHandle()), 2); 
      OSInterop.MONITORINFOEX info = new OSInterop.MONITORINFOEX(); 
      OSInterop.GetMonitorInfo(new HandleRef((object)null, hmonitor), info); 
      r = new Int32Rect(info.rcWork.left, info.rcWork.top, info.rcWork.width, info.rcWork.height); 
     } 
     return new Point(r.X, r.Y); 
    } 
} 
+1

Đây phải là giải pháp được chấp nhận. Cảm ơn! –

3
public static System.Drawing.Rectangle GetWindowRectangle(this Window w) 
{ 
    if (w.WindowState == WindowState.Maximized) { 
     var handle = new System.Windows.Interop.WindowInteropHelper(w).Handle; 
     var screen = System.Windows.Forms.Screen.FromHandle(handle); 
     return screen.WorkingArea; 
    } 
    else { 
     return new System.Drawing.Rectangle(
      (int)w.Left, (int)w.Top, 
      (int)w.ActualWidth, (int)w.ActualHeight); 
    } 
} 
+0

Goldilocks! Các giải pháp đầu tiên là nhỏ gọn nhưng sai, thứ hai có lẽ là đúng, nhưng không nhỏ gọn. Đây là một trong những quyền :) Đối với một số lý do, 3 được bình chọn theo thứ tự đảo ngược giá trị thực tế của họ. –

+0

Không đưa ra câu trả lời đúng cho tôi – Epirocks

3

Phổ một dòng câu trả lời làm việc cho tất cả các màn hình và tất cả DPI cao biến thể:

Point leftTop = this.PointToScreen(new Point(0, 0)); 

Ví dụ này trả về (-8, -8) cho cửa sổ được tối đa o n màn hình rộng 1920 có số ActualWidth trả về năm 1936.

Chỉ là câu trả lời cho các câu trả lời khác: KHÔNG BAO GIỜ trộn các pixel WPF 96 dpi hợp lý (sử dụng double) với pixel thực nguyên bản (sử dụng int) - đặc biệt bằng cách chỉ ghép đôi thành int!

+0

Nó rõ ràng không hoạt động trên nhiều thiết lập màn hình. – Kilazur

+0

@Kilazur tại sao rõ ràng? Ban đầu tôi đã thử nghiệm điều này trên một đầu ba trên tất cả 3 màn hình. Thanh tác vụ là dọc và không phải trên màn hình chính mà một mình freaks ra 50% của tất cả các phần mềm. – springy76

+1

Điểm (0,0) nằm bên trong vùng máy khách của cửa sổ và không trả lại góc trên/trái thực tế của khung cửa sổ. Nếu bạn cố gắng sử dụng các tọa độ này để đặt một cái gì đó khác, nó sẽ xuất hiện sai. –

Các vấn đề liên quan