Как: учитывая HWND, узнайте, является ли окно модальным или нет

для любого заданного окна, которое я обрабатываю, мне нужен способ узнать, является ли данное окно модальным.

насколько я могу судить, нет методов, которые делают именно это, поэтому мне нужно какое-то умное обходное решение для этого!

помощь приветствуется!

EDIT: почему мое 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");
                    }
                }
            }
        }

3 ответов


модальные окна обычно работают, отключая их владельца, где владелец является окном верхнего уровня. Поэтому, если вы проверяете эту ситуацию, вы должны поймать, является ли диалог модальным или нет.

  • проверьте, что HWND на самом деле является диалогом верхнего уровня, а не дочерним окном
  • получить владельца (GetWindow (GW_OWNER))
  • проверяем, что владелец сам является окном верхнего уровня (например. GetAncestor (GA_PARENT)==GetDesktopWindow ())
  • проверьте, что владелец отключено (GetWindowLong (GWL_STYLE) & WS_DISABLED)

Это должно поймать все стандартные модальные диалоги Win32-стиля.

обратите внимание, что родитель и владелец-это тонко разные понятия; это владелец, которого вы хотите проверить здесь. Это может запутаться, потому что GetParent может вернуть владельца... - более подробная информация от Raymond Chen здесь.


Я не уверен, что решение Бренданмка всегда будет правильным. Предположим, что окно W отображает сначала немодальный диалог A, а затем модальный диалог B. Оба A и B имеют W в качестве родительского окна. Во время отображения B W был отключен, и поэтому применение алгоритма как к A, так и к B сообщит о том, что оба они являются модальными диалогами.


Я только что написал GetWindowLong(GetWindow(Hwnd, GW_OWNER), GWL_STYLE) & WS_DISABLED & WS_POPUP в моем коде.