2016-02-19 51 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)]'。這使編譯器不必重新排列成員的順序,並提醒您該命令很重要。 –