废话不多说直接上代码

测试代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

void TestFun()
{
// 此处需要写unity程序的标题

IntPtr handle = Win32Api.GetProcessWnd("测试窗口");

// WPF 程序需要这样使用
// IntPtr currentIntPtr = new WindowInteropHelper(this).Handle;
if (Win32Api.IsCover(handle))
{
Console.WriteLine("窗口被完全遮挡");

}
else
{
Console.WriteLine("窗口未被完全遮挡");
}

}

系统API

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236


internal class Win32Api
{
[StructLayout(LayoutKind.Sequential)]
public struct Rect
{
public int Left;
public int Top;
public int Right;
public int Bottom;
}

/// <summary>
/// 获取 Win32 窗口的一些基本信息。
/// </summary>
public readonly struct WindowInfo
{
public WindowInfo(IntPtr hWnd, string className, string title, bool isVisible, Rectangle bounds) : this()
{
Hwnd = hWnd;
ClassName = className;
Title = title;
IsVisible = isVisible;
Bounds = bounds;
}

/// <summary>
/// 获取窗口句柄。
/// </summary>
public IntPtr Hwnd { get; }

/// <summary>
/// 获取窗口类名。
/// </summary>
public string ClassName { get; }

/// <summary>
/// 获取窗口标题。
/// </summary>
public string Title { get; }

/// <summary>
/// 获取当前窗口是否可见。
/// </summary>
public bool IsVisible { get; }

/// <summary>
/// 获取窗口当前的位置和尺寸。
/// </summary>
public Rectangle Bounds { get; }

/// <summary>
/// 获取窗口当前是否是最小化的。
/// </summary>
public bool IsMinimized => Bounds.Left == -32000 && Bounds.Top == -32000;
}


[DllImport("user32.dll", SetLastError = true)]
public static extern IntPtr GetWindow(IntPtr hwnd, uint windowType);

public delegate bool WNDENUMPROC(IntPtr hwnd, int lParam);

[DllImport("user32.dll", SetLastError = true)]
public static extern bool EnumWindows(WNDENUMPROC lpEnumFunc, uint lParam);

[DllImport("user32.dll", SetLastError = true)]
public static extern IntPtr GetParent(IntPtr hWnd);

[DllImport("user32.dll")]
public static extern uint GetWindowThreadProcessId(IntPtr hWnd, ref uint lpdwProcessId);
[DllImport("user32.dll")]
public static extern int GetWindowTextLength(IntPtr hWnd);

[DllImport("User32.dll", CharSet = CharSet.Auto)]
public static extern int GetWindowText(IntPtr hWnd, StringBuilder text, int nMaxCount);

[DllImport("kernel32.dll")]
public static extern void SetLastError(uint dwErrCode);

[DllImport("user32")]
public static extern int GetClassName(IntPtr hWnd, StringBuilder lpString, int nMaxCount);

[DllImport("user32")]
public static extern bool IsWindowVisible(IntPtr hWnd);


[DllImport("user32.dll")]
public static extern int GetWindowRect(IntPtr hwnd, out Rect lpRect);


public static IntPtr ptrWnd = IntPtr.Zero;
static string Title;

/// <summary>
/// 获得当前进程的主窗口句柄
/// </summary>
/// <param name="title">窗口标题</param>
/// <returns></returns>
public static IntPtr GetProcessWnd(string title)
{
if (ptrWnd == IntPtr.Zero)
{
Title = title;
uint pid = (uint)Process.GetCurrentProcess().Id; // 当前进程 ID
bool bResult = EnumWindows(OnWindowEnum, pid);
return (!bResult && Marshal.GetLastWin32Error() == 0) ? ptrWnd : IntPtr.Zero;
}
return ptrWnd;
}

static bool OnWindowEnum(IntPtr hwnd, int lParam)
{
uint id = 0;

if (GetParent(hwnd) == IntPtr.Zero)
{
GetWindowThreadProcessId(hwnd, ref id);
if (id == lParam) // 找到进程对应的主窗口句柄
{
int length = GetWindowTextLength(hwnd);
StringBuilder windowName = new StringBuilder(length + 1);
GetWindowText(hwnd, windowName, windowName.Capacity);
if (windowName.ToString().CompareTo(Title) == 0)
{
ptrWnd = hwnd; // 把句柄缓存起来
SetLastError(0); // 设置无错误
return false; // 返回 false 以终止枚举窗口
}
}
}
return true;
}


public static bool IsCover(IntPtr handle)
{

var currentWindow = GetWindowDetail(handle);

var windows = GetAllAboveWindows(handle);
var windowInfos = windows.Where(I => I.IsVisible &&
!I.IsMinimized &&
I.Bounds.Width > 1 &&
I.Bounds.Height > 1 &&
I.Hwnd != handle &&
!(I.ClassName.StartsWith("Shell_") &&
I.ClassName.EndsWith("TrayWnd")))
.ToList();


foreach (var item in windowInfos)
{

if (item.Bounds.Contains(currentWindow.Bounds))
return true;
}

return false;
}

/// <summary>
/// 查找当前用户空间下所有符合条件的窗口(仅查找顶层窗口)。如果不指定条件,将返回所有窗口。
/// </summary>
/// <param name="match">过滤窗口的条件。</param>
/// <returns>找到的所有窗口信息。</returns>
public static IReadOnlyList<WindowInfo> FindAll(Predicate<WindowInfo> match = null)
{
var windowList = new List<WindowInfo>();
EnumWindows(OnWindowEnum, 0);
return match == null ? windowList : windowList.FindAll(match);

bool OnWindowEnum(IntPtr hWnd, int lparam)
{
// 仅查找顶层窗口。
if (GetParent(hWnd) == IntPtr.Zero)
{
var windowDetail = GetWindowDetail(hWnd);
// 添加到已找到的窗口列表。
windowList.Add(windowDetail);
}
return true;
}
}

public static WindowInfo GetWindowDetail(IntPtr hWnd)
{
// 获取窗口类名。
var lpString = new StringBuilder(512);
GetClassName(hWnd, lpString, lpString.Capacity);
var className = lpString.ToString();

// 获取窗口标题。
var lptrString = new StringBuilder(512);
GetWindowText(hWnd, lptrString, lptrString.Capacity);
var title = lptrString.ToString().Trim();

// 获取窗口可见性。
var isVisible = IsWindowVisible(hWnd);

// 获取窗口位置和尺寸。
Rect rect = default;
GetWindowRect(hWnd, out rect);
var bounds = new Rectangle(rect.Left, rect.Top, rect.Right - rect.Left, rect.Bottom - rect.Top);

return new WindowInfo(hWnd, className, title, isVisible, bounds);
}
public static List<WindowInfo> GetAllAboveWindows(IntPtr hwnd)
{
var windowInfos = new List<WindowInfo>();
var intPtr = GetWindow(hwnd, 3);
if (intPtr == IntPtr.Zero)
{
return windowInfos;
}
var windowDetail = GetWindowDetail(intPtr);
windowInfos.AddRange(GetAllAboveWindows(intPtr));
windowInfos.Add(windowDetail);
return windowInfos;
}
public static List<WindowInfo> GetAllBelowWindows(IntPtr hwnd)
{
var windowInfos = new List<WindowInfo>();
var intPtr = GetWindow(hwnd, 2);
if (intPtr == IntPtr.Zero)
{
return windowInfos;
}
var windowDetail = GetWindowDetail(intPtr);
windowInfos.AddRange(GetAllBelowWindows(intPtr));
windowInfos.Add(windowDetail);
return windowInfos;
}
}