Как: учитывая HWND, определить, является ли окно модальным или нет - PullRequest
9 голосов
/ 26 апреля 2011

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

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

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

РЕДАКТИРОВАТЬ: Почему мой 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 ]

8 голосов
/ 26 апреля 2011

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

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

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

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

1 голос
/ 07 ноября 2012

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

0 голосов
/ 20 июня 2012

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

...