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

C# 如何:给定HWND,发现窗口是否为模态窗口,c#,winapi,modal-dialog,outlook-2007,inspector,C#,Winapi,Modal Dialog,Outlook 2007,Inspector,对于我处理的任何给定窗口,我需要一种方法来确定给定窗口是否是模态的 据我所知,没有任何方法可以做到这一点,这就是为什么我需要一些聪明的变通方法来解决这个问题 谢谢你的帮助 编辑:为什么我的GetWindow(,GW_所有者)失败( 模态窗口通常通过禁用其所有者来工作,所有者是顶级窗口。因此,如果您测试这种情况,您应该捕获对话框是否为模态 检查HWND实际上是一个顶级对话框,而不是一个子窗口 获取所有者(GetWindow(GW_所有者)) 检查所有者本身是否是顶级窗口(例如get祖先(GA_P

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

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

谢谢你的帮助

编辑:为什么我的GetWindow(,GW_所有者)失败(


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

  • 检查HWND实际上是一个顶级对话框,而不是一个子窗口
  • 获取所有者(GetWindow(GW_所有者))
  • 检查所有者本身是否是顶级窗口(例如get祖先(GA_PARENT)==GetDesktopWindow()
  • 检查所有者是否已禁用(GetWindowLong(GWL_样式)和WS_已禁用)
这将捕获所有标准Win32样式的模态对话框

请注意,家长和所有者的概念有细微的不同;您要在此处检查的是所有者。这可能会让人困惑,因为GetParent可以返回所有者…-Raymond Chen提供了更多详细信息。

我刚刚写道
GetWindowLong(GetWindow(Hwnd,GW_所有者),GWL_样式)&WS_禁用&WS_弹出窗口

在我的代码中。

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

在这里大声思考:1)查找其父窗口2)查看父窗口是否可以激活Hello boltclock,我对窗口属性的理解有限,因此我想问,在这种情况下,“激活”意味着什么。它像是可见的还是检查它是否存在?它基本上意味着检查你是否可以使窗口聚焦(通常通过单击它或Alt+Tab键)。在非模态检查器上,似乎“父对象”不等于outlook的主体,所以我不确定这种方法是否有效。错误的方法。如果您找到了要查找的特定窗口,那么它是否为模态窗口并不重要。我将标记这一点作为答案,但我对win API不太了解,因此不知道如何实际将您的建议付诸实施:(谁有好的页面让我学习呢?好的,感谢pinvoke.net,我现在几乎所有的东西都可以工作了,但是GWL_风格有点让我困惑,那应该是一个常量UInt32吗?它是一个纯int(或Int32),值-16-更多关于MSDN的细节。在这种情况下,还可以使用IsWindowEnabled()谢谢,brandon!只剩下一个问题需要解决!我的GetWindow函数似乎返回0!如果我做错了什么,我会在我的问题中添加一些代码。您是否使用Spy++检查在这种特殊情况下模态是如何工作的?上面的答案是win32应用程序中模态通常是如何工作的;但始终有可能utlook正在做它自己的事情。Spy++是一个很好的工具,可以在编写代码之前弄清楚发生了什么。另一件需要注意的事情是——不要直接比较GetWindowLong的输出和禁用WS_;GetWindowLong返回一个位域,因此可能会设置其他位。你需要解释的不是将一些代码复制到你甚至不知道的地方知道。
    [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");
                    }
                }
            }
        }