Имеет ли смысл порядок, в котором дескрипторы возвращаются EnumWindows? - PullRequest
18 голосов
/ 17 ноября 2008

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


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

Ответы [ 5 ]

25 голосов
/ 17 ноября 2008

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

EDIT

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

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

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

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

  1. A C ++ В статье вопросов и ответов в журнале MSDN конкретно указано:

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

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

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

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

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

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

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

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

2 голосов
/ 15 февраля 2014

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

1 голос
/ 17 ноября 2008

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

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

0 голосов
/ 17 ноября 2008

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

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

0 голосов
/ 17 ноября 2008

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

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

...