我希望有人能够帮助我,我在我的应用程序中有以下一些代码来获取一个Rect
var windowPosition = NativeMethods.GetWindowRect(this._hwnd);
return new Rect(windowPosition.Left, windowPosition.Top, windowPosition.Width, windowPosition.Height);
我在一些我为自定义窗口编写的代码中使用它,这是在WPF应用程序中,窗口是使用IWindowManager.OpenWindow
打开的。
当我运行代码并打开窗口时,我在windowPosition
对象中得到以下值,这是一个RECT
top = 1466, bottom = 785, left = 26, right = 26, width = 0, height = -681
我看不出在RECT中以这些奇数值结束的代码有什么问题,结果我在下一行得到ArgumentException
。
我也尝试将此窗口作为主应用程序窗口运行,我遇到了同样的问题,应用程序正在使用MVVM和Caliburn Micro,虽然我不确定为什么会产生影响。
根据要求,RECT结构定义如下:
[StructLayout(LayoutKind.Sequential)]
internal struct RECT
{
public void Offset(int dx, int dy)
{
this.Left += dx;
this.Top += dy;
this.Right += dx;
this.Bottom += dy;
}
public int Left { get; set; }
public int Top { get; set; }
public int Right { get; set; }
public int Bottom { get; set; }
public int Width
{
get
{
return this.Right - this.Left;
}
}
public int Height
{
get
{
return this.Bottom - this.Top;
}
}
public POINT Position
{
get
{
return new POINT { x = this.Left, y = this.Top };
}
}
public SIZE Size
{
get
{
return new SIZE { cx = this.Width, cy = this.Height };
}
}
}
和NativeMethods的GetWindowRect方法:
[DllImport("user32.dll", EntryPoint = "GetWindowRect", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool GetWindowRectInternal(IntPtr hWnd, out RECT lpRect);
public static RECT GetWindowRect(IntPtr hwnd)
{
RECT rc;
if (!GetWindowRectInternal(hwnd, out rc))
{
throw new Win32Exception(Marshal.GetLastWin32Error());
}
return rc;
}
我正在使用hWnd
访问WindowInteropHelper(window).Handle
,我忽略了包含NativeMethods中的公共方法,并且现在包含了这些方法,为浪费时间道歉。
答案 0 :(得分:3)
正如各个评论者多次指出的那样,您的RECT
结构的成员声明的顺序错误。 Win32 RECT
structure按其left
,top
,right
和bottom
边界定义了一个矩形。右边界和底边界位于矩形之外(换句话说,矩形为end-point exclusive)。
因此,您需要修复结构定义:
[StructLayout(LayoutKind.Sequential)]
public struct RECT
{
// Data members, in order, matching the Win32 RECT structure:
public int Left;
public int Top;
public int Right;
public int Bottom;
// Constructor:
public RECT(int left, int top, int right, int bottom)
{
this.Left = left;
this.Top = top;
this.Right = right;
this.Bottom = bottom;
}
// Convenience properties:
public int Width
{
get { return this.Right - this.Left; }
set { this.Right = value + this.Left; }
}
public int Height
{
get { return this.Bottom - this.Top; }
set { this.Bottom = value + this.Top; }
}
// Conversion helper functions:
public System.Drawing.Point Position
{
get { return new System.Drawing.Point(this.Left, this.Top); }
}
public System.Drawing.Size Size
{
get { return new System.Drawing.Size(this.Width, this.Height); }
}
}
您还需要确保正确定义了POINT
和SIZE
结构。或者,由于System.Drawing.Point
和System.Drawing.Size
结构与本机类型100%兼容,因此只需使用它们(作为上述RECT
结构中的转换函数)。
值得指出的是一个名为pinvoke.net的网站的存在,这是一个P / Invoke签名的协作编辑(维基式)存储库 - 包括结构和功能。在早期,定义并不完全值得信赖,但我认为它们正在变得更好。 (几年前我停止写这些内容并且没有跟上网站的进度。至少它的RECT structure是正确的。)
GetWindowRect
结构的P / Invoke定义是正确的,但您显示的代码将无法编译。没有GetWindowRectInternal
功能。你需要这样的东西:
[DllImport("user32.dll", SetLastError = true, EntryPoint="GetWindowRect")]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool GetWindowRectInternal(IntPtr hWnd, out RECT lpRect);
public static RECT GetWindowRect(IntPtr hWnd)
{
RECT rc;
if (!GetWindowRectInternal(hWnd, out rc))
{
throw new Win32Exception(Marshal.GetLastWin32Error());
}
return rc;
}