如何检查表单是否在另一个窗口后面?

时间:2013-09-17 21:31:22

标签: winforms

是否有表格的属性,我可以检查它是否在另一个窗口后面?

我在表单中运行基于OpenGL的虚拟环境。

我希望能够在点击此表单顶部的另一个窗口时忽略鼠标。

我看了this帖子,但问题的标题与答案不符。

1 个答案:

答案 0 :(得分:1)

汉斯一如既往地说对了。 Pinvoke是你的朋友..我找到了我的需求in the msdn forum的解决方案,这个方法使用了许多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;
    }