Подтвердить что ты не робот

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

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


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

4b9b3361

Ответ 1

Он возвращает их в порядке 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 оба совершенно молчали по этому вопросу. В качестве доказательства я предлагаю следующее:

  • A С++ Q & статья в журнале MSDN конкретно указывает:

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

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

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

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

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

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

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

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

Ответ 2

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

Ответ 3

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

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

Ответ 4

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

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

Ответ 5

Если в документации ничего не говорится о порядке перечисления, я бы настоятельно предложил вам держаться подальше от каких-либо предположений. Несколько сообщений в блоге Raymond Chen (blogs.msdn.com/oldnewthing) расскажут вам, сколько приложений существует, которые полагаются на весь этот недокументированный материал/наблюдение, и что-то ужасно ошибочно, когда выходит новая версия Windows (кроме Разработчики MS представляют еще одну прокладку для еще одного приложения, которое ведет себя плохо).

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