如何:给定 HWND,发现窗口是否为模态窗口

发布于 2024-11-03 10:42:42 字数 2030 浏览 6 评论 0原文

对于我处理的任何给定窗口,我需要一种方法来确定给定窗口是否是模态窗口。

据我所知,没有任何方法可以完全做到这一点,这就是为什么我需要一些聪明的解决方法来解决这个问题!

感谢帮助!

编辑:为什么我的 GetWindow(,GW_OWNER) 失败? :(

    [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
    internal static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
    [DllImport("user32.dll", SetLastError = true)]
    internal static extern IntPtr GetWindow(IntPtr hWnd, GetWindow_Cmd uCmd);
    [DllImport("user32.dll", ExactSpelling = true)]
    internal static extern IntPtr GetAncestor(IntPtr hwnd, GetAncestor_Flags gaFlags);
    [DllImport("user32.dll", SetLastError = false)]
    internal static extern IntPtr GetDesktopWindow();
    [DllImport("user32.dll", SetLastError = true)]
    internal static extern int GetWindowLong(IntPtr hWnd, int nIndex);

    const UInt32 WS_DISABLED = 0x8000000;


    internal enum GetAncestor_Flags
    {
        GetParent = 1,
        GetRoot = 2,
        GetRootOwner = 3
    }

    internal enum GetWindow_Cmd : uint
    {
        GW_HWNDFIRST = 0,
        GW_HWNDLAST = 1,
        GW_HWNDNEXT = 2,
        GW_HWNDPREV = 3,
        GW_OWNER = 4,
        GW_CHILD = 5,
        GW_ENABLEDPOPUP = 6
    }



IntPtr _inspHwnd = FindWindow("rctrl_renwnd32", inspector.Caption); // searching for a window with this name
        if (_inspHwnd.ToInt32() != 0) // found window with this name
        {
            IntPtr _ownerHwnd = GetWindow(_inspHwnd, GetWindow_Cmd.GW_OWNER);
            if (_ownerHwnd.ToInt32() != 0)
            {
                IntPtr _ancestorHwnd = GetAncestor(_ownerHwnd, GetAncestor_Flags.GetParent);
                if (_ancestorHwnd == GetDesktopWindow())
                {
                    if (GetWindowLong(_ancestorHwnd, -16) == WS_DISABLED) 
                    { 
                        // inspector is probably modal if you got all the way here
                        MessageBox.Show("modal flag tripped");
                    }
                }
            }
        }

For any given window I handle, I need a way to find out whether or not the given window is Modal.

Far as I can tell, there are no methods that do exactly that, which is why I need some clever workaround to work this out!

Help is appreciated!

EDIT : Why is my GetWindow(,GW_OWNER) failing? :(

    [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
    internal static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
    [DllImport("user32.dll", SetLastError = true)]
    internal static extern IntPtr GetWindow(IntPtr hWnd, GetWindow_Cmd uCmd);
    [DllImport("user32.dll", ExactSpelling = true)]
    internal static extern IntPtr GetAncestor(IntPtr hwnd, GetAncestor_Flags gaFlags);
    [DllImport("user32.dll", SetLastError = false)]
    internal static extern IntPtr GetDesktopWindow();
    [DllImport("user32.dll", SetLastError = true)]
    internal static extern int GetWindowLong(IntPtr hWnd, int nIndex);

    const UInt32 WS_DISABLED = 0x8000000;


    internal enum GetAncestor_Flags
    {
        GetParent = 1,
        GetRoot = 2,
        GetRootOwner = 3
    }

    internal enum GetWindow_Cmd : uint
    {
        GW_HWNDFIRST = 0,
        GW_HWNDLAST = 1,
        GW_HWNDNEXT = 2,
        GW_HWNDPREV = 3,
        GW_OWNER = 4,
        GW_CHILD = 5,
        GW_ENABLEDPOPUP = 6
    }



IntPtr _inspHwnd = FindWindow("rctrl_renwnd32", inspector.Caption); // searching for a window with this name
        if (_inspHwnd.ToInt32() != 0) // found window with this name
        {
            IntPtr _ownerHwnd = GetWindow(_inspHwnd, GetWindow_Cmd.GW_OWNER);
            if (_ownerHwnd.ToInt32() != 0)
            {
                IntPtr _ancestorHwnd = GetAncestor(_ownerHwnd, GetAncestor_Flags.GetParent);
                if (_ancestorHwnd == GetDesktopWindow())
                {
                    if (GetWindowLong(_ancestorHwnd, -16) == WS_DISABLED) 
                    { 
                        // inspector is probably modal if you got all the way here
                        MessageBox.Show("modal flag tripped");
                    }
                }
            }
        }

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

流年里的时光 2024-11-10 10:42:42

模态窗口通常通过禁用其所有者来工作,其中所有者是顶级窗口。因此,如果您测试这种情况,您应该了解对话框是否是模态的。

  • 检查 HWND 实际上是一个顶级对话框,而不是子窗口
  • 获取所有者 (GetWindow(GW_OWNER))
  • 检查所有者本身是否是一个顶级窗口(例如 GetAncestor(GA_PARENT)==GetDesktopWindow())
  • 检查所有者是否已禁用 (GetWindowLong(GWL_STYLE) & WS_DISABLED)

这应该捕获所有标准 Win32 样式模式对话框。

请注意,父级和所有者是略有不同的概念;这是您要在这里查看的所有者。这可能会令人困惑,因为 GetParent 可以返回所有者... - Raymond Chen 提供的更多详细信息 这里

Modal windows usually work by disabling their owner, where the owner is a top-level window. So if you test for this situation, you should catch whether a dialog is modal or not.

  • Check that the HWND is actually a top-level dialog, and not a child window
  • Get the owner (GetWindow(GW_OWNER))
  • Check that the owner is itself a top-level window (eg. GetAncestor(GA_PARENT)==GetDesktopWindow())
  • Check that the owner is disabled (GetWindowLong(GWL_STYLE) & WS_DISABLED)

That should catch all standard Win32-style modal dialogs.

Note that parent and owner are subtly different concepts; it's the owner you want to check here. This can get confusing, because GetParent can return the owner... - more details from Raymond Chen here.

世界和平 2024-11-10 10:42:42

我不确定 BrendanMck 的解决方案总是正确的。假设窗口 W 首先显示一个非模式对话框 A,然后显示一个模式对话框 B。A 和 B 都将 W 作为其父窗口。当 B 显示时,W 被禁用,因此将算法应用于 A 和 B 将报告它们都是模式对话框。

I'm not certain that BrendanMck's solution will always be correct. Let's say that window W displays first a modeless dialog A and then a modal dialog B. Both A and B have W as their parent window. At the time B was displayed, W became disabled and as such applying the algorithm to both A and B will report both of them as being modal dialogs.

贪了杯 2024-11-10 10:42:42

我刚刚写的
GetWindowLong(GetWindow(Hwnd, GW_OWNER), GWL_STYLE) & WS_DISABLED & WS_POPUP
在我的代码中。

I just wrote
GetWindowLong(GetWindow(Hwnd, GW_OWNER), GWL_STYLE) & WS_DISABLED & WS_POPUP
in my code.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文