ここで私はここに以前の議論(!ありがとう)に基づいて思い付いたソリューションです。
このソリューション...
- が
- は、すべてのウィンドウ状態を扱う
現在の状態でウィンドウの位置を返します(最大化、最小化、復元)
- Windowsフォームに依存しない(ただし、
- を確実に正しいモニター
を主メタを決定するために、ウィンドウハンドルを使用して)、それに触発されod GetAbsolutePosition
は、ここでは拡張メソッドとして実装されています。あなたはmyWindow
と呼ばれるWindow
を持っている場合は、このようにそれを呼び出す:
Point p = myWindow.GetAbsolutePosition();
ここでは完全なコードです:すべてのモニターおよびすべての高DPIの変種のために働いて
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);
}
}
GetWorkingArea呼び出しを次のように変更すると、私は思う:windowRectangle = System.Windows.Forms.Screen.GetWorkingArea(新しいSystem.Drawing.Point(int)window.Left +(int)(window.ActualWidth/2) (int)window.op +(int)(window.ActualHeight/2)));それはそれを修正します。ウィンドウが複数のモニタにまたがっている場合、WPFが最大化するウィンドウを決定するために使用するポイントなので、ウィンドウの中心を取得する必要があります。 – Matt
良いアイデアだが、これは実際に助けになるのだろうか?この句のこの枝は、WindowStateが最大化されている場合にのみ使用されるため、ActualWithと-Heightは(復元された)ウィンドウサイズではなく画面サイズになります。 – eFloh
ええ、私はあなたが言っていることを得ています。あなたRestoreBoundsから復元されたウィンドウサイズを取得し、おそらくActualWidth/ActualHeightの代わりに使用することはできますか? – Matt