FindWindowEx в дочернем диалоговом окне

Я пытаюсь получить дескриптор дочернего диалогового окна. Я пытался использовать FindWindowEx, но это не сработало. Вместо этого FindWindow работал.

Я провел эксперимент с окном параметров визуальной студии со следующим кодом:

IntPtr vsHandle = Process.GetProcessById(vsProcessId).MainWindowHandle; // consistent with spy++'s parent handle of options window

IntPtr optionsHandle = FindWindowEx(vsHandle, IntPtr.Zero, "#32770", "Options"); // returns 0

IntPtr optionsHandle2 = FindWindow("#32770", "Options"); // returns correct handle

Насколько я понимаю, FindWindowEx должен был работать, это дочернее окно.

Я использую Windows XP, а также пытался использовать FindWindowEx (vsHandle, IntPtr.Zero, "# 32770", null). Не работает. Похоже, что единственный способ получить его - использовать FindWindow, что недостаточно, поскольку могут быть открыты два родительских экземпляра с одним и тем же диалоговым окном.

Это декларация:

[DllImport("user32.dll")]
Private static extern IntPtr FindWindow(string className, string windowTitle);
[DllImport("user32.dll")]
Private static extern IntPtr FindWindowEx(IntPtr parentHWnd, IntPtr childAfterHWnd,     string className, string windowTitle);

Заранее спасибо.


person Rita    schedule 23.05.2013    source источник
comment
вместо этого попробуйте EnumWindows().   -  person David    schedule 23.05.2013
comment
но @David, EnumWindows - Enum верхнего уровня, а не дочернего, за исключением верхнего уровня, принадлежащего системе, имеющей стиль WS_CHILD (см. MSDN)...   -  person kero    schedule 23.05.2013
comment
@Rita, FindWindowEx, конечно, может найти и действительно найти каждое дочернее окно. Например, если вы запускаете exe из files.rsdn.ru/42164/wintreesnap.zip с параметром _f - вы получите текстовый файл с полным деревом окон именно через FindWindowEx. Ищите ошибки в коде...   -  person kero    schedule 23.05.2013
comment
EnumWindows использует обратные вызовы и может искать не только окна верхнего уровня, но и все дочерние окна данного HWND, см. также msdn.   -  person David    schedule 23.05.2013
comment
@David, тогда почему бы не через EnumChildWindows(GetDesktopWindow), проще и быстрее, см. msdn :) Кстати, Рита спросила о FindWindowEx.   -  person kero    schedule 23.05.2013
comment
@kero, тогда почему бы не сделать это прямо сейчас, проще и быстрее, см. msdn :) Кстати, если FindWindowEx не лучший API, зачем его придерживаться? Кстати: ты понимаешь по-английски? почему бы не прочитать хорошенько, прежде чем писать свои комментарии?   -  person David    schedule 23.05.2013
comment
Спасибо, Дэвид, enumWindows сработала   -  person Rita    schedule 05.06.2013


Ответы (1)


Я нашел решение для этого. Причина, по которой FindWindowEx не работал, заключалась в том, что он работает только с дочерними окнами со стилем WS_CHILD, а диалоговые окна, по-видимому, не имеют этого стиля. Вот почему EnumChildWindows тоже не работает (я пробовал).

Таким образом, уродливое решение — EnumWindows в сочетании с GetParent для сравнения дескриптора и текста.

        struct SearchData
        {
            public string WindowText;
            public IntPtr ParentHandle;
            public IntPtr ResultHandle;
        }

        delegate bool EnumWindowsCallback(IntPtr currentWindowHandle, ref SearchData searchData);

        [DllImport("user32.dll")] static extern bool EnumWindows(EnumWindowsCallback callback, ref SearchData searchData);

        [DllImport("user32.dll")] static extern IntPtr GetParent(IntPtr childHandle);

        [DllImport("user32.dll")] static extern void GetWindowText(IntPtr handle, StringBuilder resultWindowText, int maxTextCapacity);


        static bool Callback(IntPtr currentWindowHandle, ref SearchData searchData)
        {
            bool continueEnumeration = true;

            IntPtr currentWindowParentHandle = GetParent(currentWindowHandle);

            if (currentWindowParentHandle == searchData.ParentHandle)
            {
                var windowText = new StringBuilder(1024);
                GetWindowText(currentWindowHandle, windowText, windowText.Capacity);

                if (windowText.ToString() == searchData.WindowText)
                {
                    searchData.ResultHandle = currentWindowHandle;
                    continueEnumeration = false;
                }
            }

            return continueEnumeration;
        }


        IntPtr GetChildWindowHandle(string windowText, IntPtr parentHandle)
        {
            var searchData = new SearchData{ParentHandle=parentHandle, WindowText=windowText};

            EnumWindows(Callback, ref searchData);

            return searchData.ResultHandle;
        }
person Rita    schedule 05.06.2013
comment
Ваше решение отлично сработало и в моем случае. Отсутствие стиля WS_CHILD привело к тому, что FindWindow и FindWindowEx не работали, и ваше решение сработало отлично! Спасибо - person Diwakar Padmaraja; 22.04.2019