2016-02-19 50 views
-3

我希望有人能够帮助我,我有我的应用程序代码的方法如下有点让我一个矩形GetWindowRect返回奇数值

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; 
    } 

我使用WindowInteropHelper(window).Handle访问hWnd,我忽略包括来自公众方法NativeMethods现在已经包含了它,对于浪费时间表示歉意。

+1

RECT没有宽度或高度属性,显着增加了你刚刚宣布它错误的几率。奇怪你没有发布相关的代码。 –

+0

向我们展示了如何定义GetWindowRect和RECT结构。 – Dispersia

+2

它是让上下右上,而不是左上下。 –

回答

3

正如各位评论员多次指出的那样,您的RECT结构的成员声明的顺序是错误的。 Win32 RECT structure通过其left,toprightbottom界限来定义矩形。右边界和下边界位于矩形的外部(换句话说,矩形是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); } 
    } 
} 

你还需要确保你的POINTSIZE结构正确定义。或者,由于System.Drawing.PointSystem.Drawing.Size结构与本机类型100%兼容,只需使用它们(如上面的RECT结构中的转换函数那样)。

值得指出的是,存在一个名为pinvoke.net的网站,该网站是P/Invoke签名的协作编辑(wiki样式)存储库,既用于结构和功能。在早期,这些定义并不完全值得信赖,但我认为它们正在变得更好。 (我在几年前停笔这些并没有与该网站的进度跟上。至少其RECT structure是正确的。)

您的P/Invoke定义为GetWindowRect结构是正确的,但你的代码显示不会编译。没有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; 
} 
+0

认识到我在我发布的代码中有错字,所以纠正了错误,并且纠正了我的RECT定义,想要理解为什么四个属性的位置很重要? –

+0

您正在与本机代码@Neil进行互操作。你调用的Win32函数(比如'GetWindowRect')期望处理一个'RECT'结构。这就是他们的写作方式,也是他们ABI的一部分。 RECT结构是以某种方式定义的,其成员按一定顺序排列。如果你定义了一个不同的结构,并且它的成员以不同的顺序传递给这些函数,他们将不知道它们被欺骗了。他们会像“RECT”结构那样对待它,但它不会真的是一个,所以你会得到错误的结果。这就像恶作剧 - 打电话给某人。 –

+0

注意这里的结构是如何声明的[[StructLayout(LayoutKind.Sequential)]'。这使编译器不必重新排列成员的顺序,并提醒您该命令很重要。 –