0

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

我有一个在表单内运行的基于 OpenGL 的虚拟环境。

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

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

4

1 回答 1

1

汉斯一如既往地是对的。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;
    }
于 2013-09-18T15:48:53.083 回答