[DllImport("user32.dll")]
private static extern bool GetWindowRect(IntPtr hWnd, out RECT lpRect);
功能: 獲取指定窗口邊框矩形的屏幕坐標(相對於屏幕左上角)。
參數:
hWnd:目標窗口句柄lpRect:輸出參數,接收 RECT 結構(Left、Top、Right、Bottom)返回值: 非零表示成功,零表示失敗(調用 GetLastError 獲取錯誤碼)。
[StructLayout(LayoutKind.Sequential)]
public struct RECT {
public int Left; // 左上角 X
public int Top; // 左上角 Y
public int Right; // 右下角 X
public int Bottom; // 右下角 Y
}
注意: 必須加 [StructLayout(LayoutKind.Sequential)] 確保記憶體佈局與 Win32 API 一致。
using System;
using System.Runtime.InteropServices;
public class WindowHelper {
[DllImport("user32.dll", SetLastError = true)]
private static extern bool GetWindowRect(IntPtr hWnd, out RECT lpRect);
[DllImport("user32.dll", SetLastError = true)]
private static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
[StructLayout(LayoutKind.Sequential)]
public struct RECT {
public int Left, Top, Right, Bottom;
}
public static RECT GetWindowRect(string windowTitle) {
IntPtr hWnd = FindWindow(null, windowTitle);
if (hWnd == IntPtr.Zero) throw new Exception("窗口未找到");
RECT rect;
if (!GetWindowRect(hWnd, out rect)) {
int error = Marshal.GetLastWin32Error();
throw new System.ComponentModel.Win32Exception(error);
}
return rect;
}
}
// 使用
var rect = WindowHelper.GetWindowRect("計算器");
Console.WriteLine($"Left:{rect.Left}, Top:{rect.Top}, Right:{rect.Right}, Bottom:{rect.Bottom}");
Console.WriteLine($"寬度:{rect.Right - rect.Left}, 高度:{rect.Bottom - rect.Top}");
| 問題 | 原因 | 解決 |
|---|---|---|
| 返回全零矩形 | 窗口最小化或隱藏 | 調用前確保窗口可見(IsWindowVisible) |
| 座標異常(負值/超大) | 多顯示器、DPI 縮放 | 使用 GetDpiForWindow 校正,或 SetProcessDpiAwareness |
| AccessViolationException | RECT 結構佈局錯誤 | 加 [StructLayout(LayoutKind.Sequential)],字段順序勿變 |
| FindWindow 返回零 | 標題不完全匹配、類名錯誤 | 用 Spy++ 確認類名/標題,或 EnumWindows 遍歷查找 |
GetClientRect:獲取客戶區域座標(不含邊框/標題欄),相對窗口左上角ScreenToClient / ClientToScreen:屏幕/客戶區座標轉換SetWindowPos:設置窗口位置大小(見下文)