是否有一个表单的属性,我可以检查它何时在另一个窗口后面?
我有一个在表单内运行的基于 OpenGL 的虚拟环境。
单击此表单顶部的另一个窗口时,我希望能够忽略鼠标。
我查看了这个帖子,但问题的标题与答案不符。
汉斯一如既往地是对的。Pinvoke 是你的朋友。我在 msdn 论坛中找到了满足我需求的解决方案,该方法使用多个 WinAPI 调用来确定窗口是否重叠。我做了一些小的修改以允许忽略某些句柄。只要另一个窗口稍微重叠,该方法就会返回 true,您可能需要进行自己的修改。
private const int GW_HWNDPREV = 3;
[DllImport("user32.dll")]
private static extern IntPtr GetWindow(IntPtr hWnd, int uCmd);
[DllImport("user32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool GetWindowRect(IntPtr hWnd, ref RECT lpRect);
[DllImport("user32.dll")]
private static extern bool IntersectRect(out RECT lprcDst, [In] ref RECT lprcSrc1, [In] ref RECT lprcSrc2);
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool IsWindowVisible(IntPtr hWnd);
public static bool IsWindowOverlapped(IntPtr hWnd, HashSet<IntPtr> ignoreHandles)
{
if (hWnd == IntPtr.Zero)
return false; //throw new InvalidOperationException("Window does not yet exist");
if (!IsWindowVisible(hWnd))
return false;
HashSet<IntPtr> visited = new HashSet<IntPtr> { hWnd };
//The set is used to make calling GetWindow in a loop stable by checking if we have already
//visited the window returned by GetWindow. This avoids the possibility of an infinate loop.
RECT thisRect = new RECT();
GetWindowRect(hWnd, ref thisRect);
while ((hWnd = GetWindow(hWnd, GW_HWNDPREV)) != IntPtr.Zero && !visited.Contains(hWnd))
{
visited.Add(hWnd);
if (ignoreHandles != null && ignoreHandles.Contains(hWnd))
continue;
RECT testRect, intersection;
testRect = intersection = new RECT();
if (IsWindowVisible(hWnd) && GetWindowRect(hWnd, ref testRect) && IntersectRect(out intersection, ref thisRect, ref testRect))
return true;
}
return false;
}