我需要知道最大化窗口的位置。
WPF窗口具有Top和Left属性,用于指定窗口的位置。但是,如果最大化窗口,这些属性会使窗口的值保持正常状态。
如果您在单屏设置上运行,则最大化位置自然是(0,0)。但是,如果您有多个屏幕不一定是真的。如果在主屏幕上将窗口最大化,窗口将只有位置(0,0)。
那么......有没有办法找出最大化窗口的位置(最好是与Top和Left属性相同的逻辑单位)?
答案 0 :(得分:9)
这是我在此基础上提出的解决方案(谢谢!)。
此解决方案......
主要方法GetAbsolutePosition
在此处作为扩展方法实现。如果您有一个名为Window
的{{1}},请按以下方式调用:
myWindow
这是完整的代码:
Point p = myWindow.GetAbsolutePosition();
答案 1 :(得分:7)
我终于找到了一个适合我的解决方案:
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 :(得分:5)
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);
}
}
答案 3 :(得分:5)
适用于所有显示器和所有高DPI变体的通用一行答案:
Point leftTop = this.PointToScreen(new Point(0, 0));
例如,返回(-8,-8)窗口,该窗口在1920 {{}}返回1936的宽屏幕上最大化。
对其他答案的咆哮:永远不要将逻辑96 dpi WPF像素(使用ActualWidth
)与本机真实像素混合(使用double
) - 特别是只需将double转换为int!
答案 4 :(得分:0)
我意识到您正在使用WPF,这个答案使用了Forms技术,但它应该没有太大困难。
您可以通过My.Settings.Screens.AllScreens获取一系列屏幕。从那里,您可以访问屏幕当前正在处理的分辨率。
由于WPF窗口保留了它们最大化时的顶部/左侧值,因此您可以通过确定顶部/左侧坐标所指的屏幕,然后获取顶部/左侧坐标来确定它们所在的屏幕对于那个屏幕。
不幸的是,我在路上,此刻无法测试。如果你确实实施了,我很乐意看到你提出的建议。
答案 5 :(得分:0)
这似乎是System.Windows.Window的问题!!!
最大化的窗口给出的Left,Width,ActualWidth,Top,Height和ActualHeight值不可靠。
最大化窗口后,通常可以保留预先最大化窗口的Left和Width值。
对于其他阅读者-窗口未最大化时没有问题。
此外,我觉得奇怪的是,您读取的值在WPF DPI坐标中,即1936x1096,从(-8,-8)到(1928,1088)],但是设置这些值时,您必须使用屏幕像素坐标[即1920x1080,使用(0,0)等...]
@tgr在上面提供了可靠的部分解决方案,下面我对其进行了改进:
这是C#解决方案:
using System;
using System.Runtime.InteropServices;
using System.Windows;
using System.Windows.Interop;
public static partial class Extensions
{
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 Int32Rect _getOsInteropRect(Window w)
{
bool multimonSupported = OSInterop.GetSystemMetrics(OSInterop.SM_CMONITORS) != 0;
if (!multimonSupported)
{
OSInterop.RECT rc = new OSInterop.RECT();
OSInterop.SystemParametersInfo(48, 0, ref rc, 0);
return new Int32Rect(rc.left, rc.top, rc.width, rc.height);
}
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);
return new Int32Rect(info.rcWork.left, info.rcWork.top, info.rcWork.width, info.rcWork.height);
}
public static Rect GetAbsoluteRect(this Window w)
{
if (w.WindowState != WindowState.Maximized)
return new Rect(w.Left, w.Top, w.ActualWidth, w.ActualHeight);
var r = _getOsInteropRect(w);
return new Rect(r.X, r.Y, r.Width, r.Height);
}
public static Point GetAbsolutePosition(this Window w)
{
if (w.WindowState != WindowState.Maximized)
return new Point(w.Left, w.Top);
var r = _getOsInteropRect(w);
return new Point(r.X, r.Y);
}
}
答案 6 :(得分:0)
我还没有找到解决您问题的方法,但是如果您只需要放置一个窗口来创建一个新窗口,则可以执行以下操作:
...
Window windowNew = new Window();
ConfigureWindow(this, windowNew);
Window.Show();
...
static public void ConfigureWindow(Window windowOld, Window windowNew)
{
windowNew.Height = windowOld.ActualHeight;
windowNew.Width = windowOld.ActualWidth;
if (windowOld.WindowState == WindowState.Maximized)
{
windowNew.WindowState = WindowState.Maximized;
}
else
{
windowNew.Top = windowOld.Top;
windowNew.Left = windowOld.Left;
}
}