Đâ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);
}
}
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
ý 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
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