Имеет ли смысл порядок, в котором дескрипторы возвращаются EnumWindows?

StackOverflow https://stackoverflow.com/questions/295996

Вопрос

Судя по паре предварительных тестов, кажется, что EnumWindows всегда возвращает окна в обратном порядке создания экземпляров, т.е.самое последнее созданное окно первым.Это достоверное наблюдение?Если да, то верно ли это для всех версий Windows?И достоверно ли это предположение, т.е.такое поведение где-то задокументировано?


Контекст: Я имею дело с ситуацией, когда я запускаю стороннее приложение для открытия нескольких немодальных окон, и мне нужно отправить некоторые оконные сообщения в эти окна, как только они откроются, но у меня нет надежного способа идентифицировать их, поскольку ни их классы окон, ни их заголовки не будут различаться, и я также не знаю их ожидаемых координат.Однако, если бы я мог положиться на приведенное выше поведение EnumWindows Я мог бы просто использовать первый дескриптор, возвращаемый EnumWindows чей класс и заголовок соответствуют моим ожиданиям.Это все еще оставляет некоторые гипотетические лазейки, но я думаю, что этого будет достаточно.Альтернативные предложения, тем не менее, приветствуются.

Это было полезно?

Решение

Он возвращает их в Z-порядке.Сначала самое верхнее окно с WS_EX_TOPMOST установить, пока не появится самое нижнее окно с WS_EX_TOPMOST set, затем самое верхнее окно без WS_EX_TOPMOST, но в самое нижнее окно без WS_EX_TOPMOST.Обратите внимание, что видимость не является определяющим фактором, поэтому невидимое окно, которое находится выше в Z-порядке, чем видимое окно, все равно будет отображаться перед ним.

РЕДАКТИРОВАТЬ:

Крайне маловероятно, что вы сможете использовать это по своему усмотрению, просто взяв первый доход от EnumWindows.Мало того, что ваше новое окно вряд ли будет первым возвратом, но у вас возникнет состояние гонки, когда в это время могут быть открыты другие окна.Однако вы можете сохранить список всех известных окон приложения, и когда вам понадобится найти новое открытое окно, вызвать EnumWindows и сравните дескрипторы окон с теми, что указаны в вашем списке.Когда вы найдете тот, который имеет правильный класс и заголовок (вы можете даже проверить, принадлежит ли он правильному процессу с помощью GetWindowThreadProcessID) то есть нет в вашем списке, то вы нашли новое окно.

Однако для ваших целей вам может быть даже лучше установить перехватчик CBT и следить за уведомлением HCBT_CREATEWND.См. справку MSDN по SetWindowsHookEx() и тот CBTProc перезвонить Чтобы получить больше информации.

Уровень уверенности в порядке перечисления:

В ряде комментариев и других ответов на этот вопрос упоминается отсутствие точной документации в MSDN о порядке, в котором EnumWindows возвращает дескрипторы окон.И действительно, страницы на EnumWindows и тот EnumWindowsProc перезвонить оба молчат по этому поводу.В качестве доказательства предлагаю следующее:

  1. А Статья вопросов и ответов по C++ в журнале MSDN конкретно утверждает:

    EnumWindows перечисляет окна в Z-порядке сверху вниз.

  2. Страница на EnumChildWindows ссылается на заказ в разделе примечаний:

    Дочернее окно, которое перемещается или перемещается в порядке Z во время процесса перечисления, будет правильно пронумеровано.

    Это означает, что порядок зависит от Z-порядка.А поскольку в описании hWndParent параметр, он говорит следующее:

    Если этот параметр имеет значение NULL, эта функция эквивалентна EnumWindows.

    можно предположить, что та же логика и порядок применимы и к EnumWindows.

  3. Это наблюдаемое поведение этой функции, которое делает ее изменение критическим.В целом Microsoft очень хорошо старается не вносить критических изменений в наблюдаемое поведение.Это не гарантия, но это довольно безопасная ставка.Вы с большей вероятностью обнаружите, что в следующей версии используемая вами функция устарела и заменена еще одной версией «Ex», чем обнаружите, что ее наблюдаемое поведение изменилось.

Конечно, на данном этапе все это очень академично, поскольку EnumWindows вероятно, это не лучшее решение проблемы ОП — по крайней мере EnumThreadWindows вероятно, подойдет лучше, но я подумал, что об этом стоит упомянуть другим людям, которые могут встретить этот пост.

Другие советы

Предыдущие ответы нуждаются в значительной доработке. Enum-order = Z-order, только если GetSystemMetrics (SM_IMMENABLED) = 0, т. Е. Функции диспетчера методов ввода / редактора метода ввода отключены. Потому что все классы окон " IME " (заголовок «IME по умолчанию») и «MSCTFIME UI»; перечисляются после окна «Progman» («Диспетчер программ»), т. е. не в Z-порядке.

Порядок не указан в API ( ссылка MSDN ) поэтому не гарантируется, что будет что-то конкретное - если бы была гарантия, это было бы явно указано в API. Что происходит, например, если окно создается в середине перечисления - включается ли оно в перечисление? Это позволяет оконному менеджеру свободно изменять свою реализацию, если это становится более эффективным.

Однако существует уникальное значение, которое можно использовать для различения окон - дескриптор окна. В вашем методе EnumWindowProc сохраните дескриптор окна для каждого соответствующего окна - он вам все равно нужен для отправки сообщений в окно.

Если вы управляете обоими процессами, вы можете отправить с первого из них сообщение SendMessage с " HWND_BROADCAST " в качестве первого параметра.

Тогда другая программа, когда получает сообщение, может сделать SendMessage для своих дочерних окон.

Если в документации ничего не говорится о порядке перечисления, я НАСТОЯТЕЛЬНО рекомендую вам избегать любых предположений. Пара постов в блоге Рэймонда Чена (blogs.msdn.com/oldnewthing) покажет вам, сколько существует приложений, использующих все эти недокументированные материалы / наблюдения, и что-то идет не так, когда выходит новая версия Windows (если только Разработчики MS вводят еще одну прокладку для еще одного приложения, которое ведет себя плохо).

Что касается вашей цели, есть несколько функций, таких как GetWindowThreadProcessID, GetParent, EnumThreadWindows и EnumWindows, которые могут помочь вам выполнить задачу.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top