Поделиться через


Функции окна

В этом обзоре рассматриваются функции таких окон, как типы окон, состояния, размер и позиция.

Типы окон

В этом разделе содержатся следующие разделы, описывающие типы окон.

Перекрывающиеся окна

перекрывающееся окно — это окно верхнего уровня (не дочернее окно), которое имеет строку заголовка, границу и область клиента; оно предназначено для работы в качестве главного окна приложения. Кроме того, он может содержать меню окна, кнопки свертывания и разворачивания, а также полосы прокрутки. Перекрываемое окно, используемое в качестве главного окна, обычно включает все эти компоненты.

Указав стиль WS_OVERLAPPED или WS_OVERLAPPEDWINDOW в функции CreateWindowEx, приложение создает перекрывающееся окно. Если вы используете стиль WS_OVERLAPPED, окно имеет строку заголовка и границу. Если вы используете стиль WS_OVERLAPPEDWINDOW, окно имеет строку заголовка, рамку для изменения размеров, меню окна и кнопки для свертывания и разворачивания.

Всплывающие окна

Всплывающее окно — это особый тип перекрывающегося окна, используемого для диалоговых окон, окон сообщений и других временных окон, которые отображаются вне главного окна приложения. Заголовки являются необязательными для всплывающих окон; В противном случае всплывающие окна совпадают с перекрывающимися окнами стиля WS_OVERLAPPED.

Всплывающее окно создается путем указания стиля WS_POPUP в CreateWindowEx. Чтобы включить строку заголовка, укажите стиль WS_CAPTION. Используйте стиль WS_POPUPWINDOW, чтобы создать всплывающее окно с границой и меню окна. Стиль WS_CAPTION должен сочетаться со стилем WS_POPUPWINDOW, чтобы сделать меню окна видимым.

Дочерние окна

дочернее окно имеет стиль WS_CHILD и ограничивается клиентской областью родительского окна. Приложение обычно использует дочерние окна для разделения клиентской области родительского окна на функциональные области. Создайте дочернее окно, указав стиль WS_CHILD в функции CreateWindowEx.

Дочернее окно должно иметь родительское окно. Родительское окно может быть перекрывающимся окном, всплывающим окном или даже другим дочерним окном. При вызове CreateWindowExукажите родительское окно. Если в CreateWindowEx указать стиль WS_CHILD, но не указать родительское окно, система не создает окно.

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

В этом разделе рассматриваются следующие аспекты дочерних окон:

Позиционирование

Система всегда позиционирует дочернее окно относительно левого верхнего угла клиентской области родительского окна. Часть дочернего окна никогда не отображается вне границ родительского окна. Если приложение создает дочернее окно, которое больше родительского окна или помещает дочернее окно таким образом, что некоторые или все дочерние окна выходят за рамки родительского окна, система обрезает дочернее окно; То есть часть за пределами клиентской области родительского окна не отображается. Действия, влияющие на родительское окно, также могут повлиять на дочернее окно, как показано ниже.

Родительское окно Дочернее окно
Разрушенный Уничтожено до уничтожения родительского окна.
Скрытый Скрыта до того, как будет скрыто родительское окно. Дочернее окно отображается только в том случае, если родительское окно отображается.
Перемещен Перемещается вместе с клиентской областью родительского окна. Дочернее окно отвечает за рисование клиентской области после перемещения.
Показано Отображается после отображения родительского окна.

 

Обрезка

Система не автоматически отсеивает дочернее окно из клиентской области родительского окна. Это означает, что родительское окно отображается поверх дочернего окна, если оно делает отрисовку в том же месте, что и дочернее окно. Однако система обрезает дочернее окно из клиентской области родительского окна, если родительское окно имеет стиль WS_CLIPCHILDREN. Если дочернее окно обрезается, родительское окно не может рисовать поверх него.

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

Если окно имеет стиль WS_CLIPCHILDREN или WS_CLIPSIBLINGS, возникает небольшая потеря производительности. Каждое окно занимает системные ресурсы, поэтому приложение не должно использовать дочерние окна неизбирательно. Для оптимальной производительности, если приложению нужно логически разделить главное окно, оно должно сделать это в процедуре главного окна, а не с помощью дочерних окон.

Отношение к родительскому окну

Приложение может изменить родительское окно существующего дочернего окна, вызвав функцию SetParent. В этом случае система удаляет дочернее окно из клиентской области старого родительского окна и перемещает его в клиентскую область нового родительского окна. Если SetParent задает дескриптор NULL, окно рабочего стола становится новым родительским окном. В этом случае дочернее окно рисуется на рабочем столе вне границ любого другого окна. Функция GetParent получает дескриптор окна, являющегося родительским для данного дочернего окна.

Родительское окно передает часть клиентской области дочернему окну, и дочернее окно получает весь ввод из этой области. Класс окна не должен совпадать с каждым дочерним окном родительского окна. Это означает, что приложение может заполнить родительское окно дочерними окнами, которые выглядят разными и выполняют различные задачи. Например, диалоговое окно может содержать множество типов элементов управления, каждое дочернее окно, которое принимает различные типы данных от пользователя.

Дочернее окно имеет только одно родительское окно, но у родительского окна может быть любое количество дочерних окон. Каждое дочернее окно, в свою очередь, может иметь дочерние окна. В этой цепочке окон каждое дочернее окно называется потомком исходного родительского окна. Приложение использует функцию IsChild для обнаружения того, является ли данное окно дочерним окном или потомком заданного родительского окна.

Функция EnumChildWindows перечисляет дочерние окна родительского окна. Затем EnumChildWindows передает дескриптор для каждого дочернего окна в функцию обратного вызова, определенную приложением. Перечисляются также окна-потомки заданного родительского окна.

Сообщения

Система передает входные сообщения дочернего окна непосредственно в дочернее окно; Сообщения не передаются через родительское окно. Единственное исключение заключается в том, что дочернее окно было отключено функцией EnableWindow. В этом случае система передает все входные сообщения, которые отправились бы в дочернее окно в родительское окно. Это позволяет родительскому окну проверять входные сообщения и включать дочернее окно при необходимости.

Дочернее окно может иметь уникальный целочисленный идентификатор. Идентификаторы дочерних окон важны при работе с окнами управления. Приложение направляет действие элемента управления, отправляя им сообщения. Приложение использует идентификатор дочернего окна элемента управления для направления сообщений в элемент управления. Кроме того, элемент управления отправляет сообщения уведомления в родительское окно. В сообщении уведомления содержится идентификатор дочернего окна элемента управления, который родитель использует для определения того, какой элемент управления отправил сообщение. Приложение задает идентификатор дочернего окна для других типов дочерних окон, устанавливая параметр hMenu функции CreateWindowEx в значение, а не в дескриптор меню.

Многоуровневые окна

Использование слоёного окна может значительно повысить производительность и визуальные эффекты для окна со сложной формой, анимирующего её форму или использующего эффекты альфа-смешивания. Система автоматически создает и перерисовывает слоистые окна и окна базовых приложений. В результате слоистые окна отрисовываются гладко, без мерцания, характерного для сложных областей окна. Кроме того, слоистые окна могут быть частично полупрозрачными, то есть с смешением по альфа-каналу.

Чтобы создать многоуровневое окно, укажите стиль расширенного окна WS_EX_LAYERED при вызове функции CreateWindowExили вызовите функцию SetWindowLong, чтобы задать WS_EX_LAYERED после создания окна. После вызова CreateWindowEx многоуровневый окно не станет видимым, пока функция SetLayeredWindowAttributes или UpdateLayeredWindow будет вызвана для этого окна.

Заметка

Начиная с Windows 8, WS_EX_LAYERED можно использовать с дочерними окнами и окнами верхнего уровня. Предыдущие версии Windows поддерживают WS_EX_LAYERED только для окон верхнего уровня.

 

Чтобы задать уровень прозрачности или цветный ключ прозрачности для заданного многоуровневого окна, вызовите SetLayeredWindowAttributes. После вызова система по-прежнему может попросить окно нарисовать, когда окно отображается или изменяется. Однако, поскольку система сохраняет изображение многоуровневого окна, система не попросит окно нарисовать, если части его отображаются в результате относительного перемещения окна на рабочем столе. Устаревшим приложениям не нужно реструктурировать код отрисовки, если они хотят добавить полупрозрачность или прозрачность для окна, так как система перенаправляет отрисовку окон, которые использовали SetLayeredWindowAttributes, в память вне экрана и снова композирует его для достижения желаемого эффекта.

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

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

Окна только для сообщений

Окно только для позволяет отправлять и получать сообщения. Он не отображается, не имеет порядка z, не может быть перечислен и не получает широковещательные сообщения. Окно просто отправляет сообщения.

Чтобы создать окно только для сообщений, укажите константу HWND_MESSAGE в параметре hWndParent функции CreateWindowEx . Можно также изменить существующее окно на окно только для сообщений, указав HWND_MESSAGE в параметре hWndNewParent функции SetParent.

Чтобы найти окна только для сообщений, укажите HWND_MESSAGE в параметре hwndParent функции FindWindowEx. Кроме того, FindWindowEx выполняет поиск окон, доступных только для сообщений, а также окон верхнего уровня, если параметры hwndParent и hwndChildAfterNULL.

Связи окон

Существует множество способов связи окна с пользователем или другим окном. Окно может быть собственным окном, окном переднего плана или фоновым окном. Окно также имеет z-порядок относительно других окон. Дополнительные сведения см. в следующих разделах:

Передние и фоновые окна

Каждый процесс может иметь несколько потоков выполнения, и каждый поток может создавать окна. Поток, создавший окно, с которым в настоящее время работает пользователь, называется потоком переднего плана, а окно называется окном переднего плана. Все остальные потоки являются фоновыми потоками, а окна, созданные фоновыми потоками, называются фоновыми окнами.

У каждого потока есть уровень приоритета, который определяет количество времени процессора, получаемое потоком. Хотя приложение может задать уровень приоритета своих потоков, обычно поток переднего плана имеет немного более высокий уровень приоритета, чем фоновые потоки. Так как он имеет более высокий приоритет, поток переднего плана получает больше времени ЦП, чем фоновые потоки. Поток переднего плана имеет обычный базовый приоритет 9; Фоновый поток имеет обычный базовый приоритет 7.

Пользователь задает окно переднего плана, щелкнув окно или используя сочетание клавиш ALT+TAB или ALT+ESC. Чтобы получить дескриптор для окна переднего плана, используйте функцию GetForegroundWindow. Чтобы проверить, является ли окно приложения окном переднего плана, сравните дескриптор, возвращенный GetForegroundWindow с окном приложения.

Приложение задает окно переднего плана с помощью функции SetForegroundWindow.

Система ограничивает, какие процессы могут установить окно на передний план. Процесс может задать окно переднего плана, только если:

  • Все следующие условия истинны:
    • Процесс вызова SetForegroundWindow принадлежит классическому приложению, а не приложению UWP или приложению Магазина Windows, предназначенному для Windows 8 или 8.1.
    • Процесс переднего плана не отключил вызовы SetForegroundWindow с помощью предыдущего вызова функции LockSetForegroundWindow.
    • Истек срок ожидания блокировки переднего плана (см. SPI_GETFOREGROUNDLOCKTIMEOUT в SystemParametersInfo).
    • Меню не активны.
  • Кроме того, по крайней мере одно из следующих условий является верным:
    • Вызывающий процесс — это основной процесс.
    • Вызывающий процесс был запущен процессом переднего плана.
    • В настоящее время нет окна переднего плана и, следовательно, нет процесса переднего плана.
    • Вызывающий процесс получил последнее событие ввода.
    • Проводится отладка процесса на переднем плане или вызывающего процесса.

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

Процесс, который может задать окно переднего плана, может включить другой процесс, чтобы задать окно переднего плана, вызвав функцию AllowSetForegroundWindow или вызвав функцию BroadcastSystemMessage с флагом BSF_ALLOWSFW. Процесс переднего плана может отключить вызовы SetForegroundWindow путем вызова функции LockSetForegroundWindow.

Владельцы Windows

Перекрывающееся или всплывающее окно может принадлежать другому перекрывающемуся или всплывающему окну. Принадлежность накладывает несколько ограничений на окно.

  • Собственное окно всегда над его владельцем в z-порядке.
  • Система автоматически уничтожает собственное окно при уничтожении его владельца.
  • Собственное окно скрыто, когда его владелец сворачен.

Только перекрывающееся или всплывающее окно может быть окном владельца; Дочернее окно не может быть окном владельца. Приложение создает собственное окно, указав дескриптор окна владельца в качестве параметра hwndParentCreateWindowEx при создании окна с WS_OVERLAPPED или стилем WS_POPUP. Параметр hwndParent должен определить перекрывающееся или всплывающее окно. Если hwndParent определяет дочернее окно, система назначает владение родительскому окну верхнего уровня дочернего окна. После создания собственного окна приложение не может передать владение окном другому окну.

Диалоговые окна и поля сообщений по умолчанию являются владельческими окнами. Приложение указывает окно владельца при вызове функции, которая создает диалоговое окно или окно сообщения.

Приложение может использовать функцию GetWindow с флагом GW_OWNER для получения дескриптора владельца окна.

Z-Order

z-order окна указывает положение окна в стеке перекрывающихся окон. Этот стек окон ориентирован вдоль мнимой оси, оси Z, расширяющейся наружу с экрана. Окно в верхней части z-порядка перекрывает все остальные окна. Окно в нижней части z-порядка перекрывается всеми остальными окнами.

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

Когда приложение создает окно, система помещает его в начало z-порядка для окон одного типа. Вы можете использовать функцию BringWindowToTop, чтобы открыть окно в верхней части z-порядка для окон одного типа. Вы можете изменить порядок z с помощью функций SetWindowPos и DeferWindowPos.

Пользователь изменяет порядок z, активируя другое окно. Система размещает активное окно в верхней части z-порядка для окон одного типа. Когда окно поднимается на верхнюю часть z-порядка, то вместе с ним поднимаются и его дочерние окна. Вы можете использовать функцию GetTopWindow для поиска всех дочерних окон родительского окна и возврата дескриптора дочернего окна с наивысшим порядком по оси z. Функция GetNextWindow извлекает дескриптор к следующему или предыдущему окну в z-порядке.

Состояние отображения окна

В любое время окно может быть активным или неактивным; скрытым или видимым; и свернутым, развернутым или восстановленным. Эти качества в совокупности называются состояние отображения окна. В следующих разделах рассматривается состояние отображения окна:

Активное окно

активное окно — это окно верхнего уровня приложения, с которым в настоящее время работает пользователь. Чтобы пользователь легко идентифицировать активное окно, система помещает его в верхней части z-порядка и изменяет цвет строки заголовка и границу с заданными системой цветами активных окон. Только окно верхнего уровня может быть активным окном. Когда пользователь работает с дочерним окном, система активирует родительское окно верхнего уровня, связанное с дочерним окном.

Одно окно верхнего уровня в системе одновременно активно. Пользователь активирует окно верхнего уровня, щелкнув его (или одно из дочерних окон), или с помощью сочетания клавиш ALT+ESC или ALT+TAB. Приложение активирует окно верхнего уровня, вызвав функцию SetActiveWindow. Другие функции могут привести к активации другого окна верхнего уровня, включая SetWindowPos, DeferWindowPos, SetWindowPlacementи DestroyWindow. Хотя приложение может активировать другое окно верхнего уровня в любое время, чтобы избежать путаницы пользователя, оно должно сделать это только в ответ на действие пользователя. Приложение использует функцию GetActiveWindow для получения дескриптора активного окна.

Когда активация изменяется из окна верхнего уровня одного приложения на окно верхнего уровня другого, система отправляет WM_ACTIVATEAPP сообщение обоим приложениям, уведомляя их об изменении. При изменении активации в другом окне верхнего уровня в одном приложении система отправляет оба окна WM_ACTIVATE сообщение.

Отключенные окна

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

По умолчанию окно включено при создании. Однако приложение может указать стиль WS_DISABLED, чтобы отключить новое окно. Приложение включает или отключает существующее окно с помощью функции EnableWindow. Система отправляет сообщение WM_ENABLE окну, когда его состояние должно измениться. Приложение может определить, включено ли окно с помощью функции IsWindowEnabled.

Когда дочернее окно отключено, система передает в родительское окно сообщения ввода мыши дочернего окна. Родитель использует сообщения, чтобы определить, следует ли включить дочернее окно. Для получения дополнительной информации см. Ввод мыши.

Только одно окно одновременно может получать ввод клавиатуры; Это окно, как говорят, имеет фокус клавиатуры. Если приложение использует функцию EnableWindow для отключения окна с фокусировкой на клавиатуре, окно теряет фокус клавиатуры в дополнение к отключению. EnableWindow затем задает фокус клавиатуры на NULL, то есть окно не имеет фокуса. Если дочернее окно или другое окно потомка имеет фокус клавиатуры, окно-потомок теряет фокус при отключении родительского окна. Дополнительные сведения см. в разделе Ввод с клавиатуры.

Видимость окна

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

Окно отображается, когда для окна задан стиль WS_VISIBLE. По умолчанию функция CreateWindowEx создает скрытое окно, если приложение не указывает стиль WS_VISIBLE. Как правило, приложение задает стиль WS_VISIBLE после создания окна, чтобы сохранить сведения о процессе создания скрыты от пользователя. Например, приложение может скрыть новое окно при настройке внешнего вида окна. Если стиль WS_VISIBLE указан в CreateWindowEx, система отправляет WM_SHOWWINDOW сообщение в окно после создания окна, но перед его отображением.

Приложение может определить, отображается ли окно с помощью функции IsWindowVisible. Приложение может отображать (сделать видимым) или скрывать окно с помощью ShowWindow, SetWindowPos, DeferWindowPosили функции SetWindowPlacement или SetWindowLong. Эти функции показывают или скрывают окно, задав или удалив стиль WS_VISIBLE для окна. Они также отправляют WM_SHOWWINDOW сообщение в окно перед отображением или скрытием.

Когда окно владельца свернуто, система автоматически скрывает принадлежащие ему окна. Аналогичным образом при восстановлении окна владельца система автоматически отображает связанные окна. В обоих случаях система отправляет сообщение WM_SHOWWINDOW в собственные окна перед скрытием или отображением. Иногда приложению может потребоваться скрыть принадлежащие окна без необходимости свести к минимуму или скрыть владельца. В этом случае приложение использует функцию ShowOwnedPopups. Эта функция задает или удаляет стиль WS_VISIBLE для всех собственных окон и отправляет WM_SHOWWINDOW сообщение в собственные окна перед скрытием или отображением. Скрытие окна владельца не влияет на состояние видимости принадлежащих окон.

При отображении родительского окна также отображаются связанные с ним дочерние окна. Аналогичным образом, когда родительское окно скрыто, его дочерние окна также скрыты. Минимизация родительского окна не влияет на состояние видимости дочерних окон; то есть дочерние окна сворачиваются вместе с родительским окном, но стиль WS_VISIBLE не изменяется.

Даже если окно имеет стиль WS_VISIBLE, пользователь может не видеть окно на экране; другие окна могут полностью перекрываться или могут быть перемещены за границу экрана. Кроме того, видимое дочернее окно подчиняется правилам вырезки, определенным его родительско-дочерними отношениями. Если родительское окно не отображается, оно тоже не будет видимо. Если родительское окно выходит за границу экрана, дочернее окно также перемещается, так как дочернее окно рисуется относительно левого верхнего угла родительского окна. Например, пользователь может переместить родительское окно, содержащее дочернее окно достаточно далеко от края экрана, что пользователь может не видеть дочернее окно, даже если дочернее окно и его родительское окно имеют стиль WS_VISIBLE.

Свернутые, развернутые и восстановленные Окна

максимизированное окно — это окно со стилем WS_MAXIMIZE. По умолчанию система увеличивает развернутое окно так, чтобы оно заполняло экран, или, в случае дочернего окна, клиентскую область родительского окна. Хотя размер окна можно задать таким же, как у максимизированного окна, максимизированное окно немного отличается. Система автоматически перемещает заголовок окна в верхнюю часть экрана или в верхнюю часть клиентской области родительского окна. Кроме того, система отключает границу размера окна и возможность размещения окна в строке заголовка (чтобы пользователь не может переместить окно путем перетаскивания заголовка).

Свернутое окно — это окно со стилем WS_MINIMIZE. По умолчанию система уменьшает свернутое окно до размера кнопки панели задач и перемещает свернутое окно на панель задач. восстановленное окно — это окно, которое было возвращено к предыдущему размеру и положению, то есть размеру и положению, которые оно имело до сворачивания или разворачивания.

Если приложение задает стиль WS_MAXIMIZE или WS_MINIMIZE в функции CreateWindowEx, окно изначально максимизировано или минимизировано. После создания окна приложение может использовать функцию CloseWindow, чтобы свести к минимуму окно. Функция ArrangeIconicWindows упорядочивает значки на рабочем столе или упорядочивает свернутые дочерние окна родительского окна в родительском окне. Функция OpenIcon восстанавливает свернутое окно до предыдущих размеров и позиции.

Функция ShowWindow может свести к минимуму, развернуть или восстановить окно. Он также может задать состояния видимости и активации окна. Функция SetWindowPlacement включает те же функции, что и ShowWindow, но она может переопределить свернутые, развернутые и восстановленные позиции окна по умолчанию.

Функции IsZoomed и IsIconic определяют, является ли данное окно развернуто или свернуто соответственно. Функция GetWindowPlacement извлекает положение свернутого, развернутого и восстановленного окна, а также определяет состояние его отображения.

Когда система получает команду для развертывания или восстановления свернутого окна, она отправляет окну сообщение WM_QUERYOPEN. Если процедура окна возвращает FALSE, система игнорирует команду "Развернуть" или "Восстановить".

Система автоматически задает размер и позицию развернутого окна в соответствии с системными значениями по умолчанию для развернутого окна. Чтобы переопределить эти значения по умолчанию, приложение может вызвать функцию SetWindowPlacement или обработать сообщение WM_GETMINMAXINFO, полученное окном, когда система собирается максимизировать окно. WM_GETMINMAXINFO включает указатель на структуру MINMAXINFO, содержащую значения, которые система использует для задания максимального размера и положения. Замена этих значений переопределяет значения по умолчанию.

Размер окна и положение

Размер и положение окна выражаются как ограничивающий прямоугольник, заданный в координатах относительно экрана или родительского окна. Координаты окна верхнего уровня относительно левого верхнего угла экрана; Координаты дочернего окна относительно левого верхнего угла родительского окна. Приложение указывает начальный размер окна и позицию при создании окна, но оно может изменять размер окна и положение в любое время. Дополнительные сведения см. в разделе Заполненные фигуры.

В этом разделе содержатся следующие разделы:

Размер и положение по умолчанию

Приложение может разрешить системе вычислить начальный размер или положение окна верхнего уровня, указав CW_USEDEFAULT в CreateWindowEx. Если приложение задает координаты окна на CW_USEDEFAULT и не создало других окон верхнего уровня, система задает положение нового окна относительно левого верхнего угла экрана; в противном случае он задает позицию относительно положения окна верхнего уровня, созданного приложением в последнее время. Если для параметра ширины и высоты задано значение CW_USEDEFAULT, система вычисляет размер нового окна. Если приложение создало другие окна верхнего уровня, система основывает размер нового окна на размере последнего созданного окна верхнего уровня. Указание CW_USEDEFAULT при создании дочернего или всплывающего окна приводит к тому, что система устанавливает размер окна в минимальном размере окна по умолчанию.

Размер отслеживания

Система поддерживает минимальный и максимальный размер отслеживания для окна стиля WS_THICKFRAME; Окно с этим стилем имеет границу размера. Минимальный размер отслеживания — это наименьший размер окна, который можно создать, перетаскивая границу изменения размера окна. Аналогичным образом максимальный размер отслеживания — это самый большой размер окна, который можно создать, перетаскивая границу размера.

Минимальные и максимальные размеры отслеживания окна устанавливаются на системные значения по умолчанию при создании окна. Приложение может обнаруживать значения по умолчанию и переопределять их, обрабатывая сообщение WM_GETMINMAXINFO. Дополнительные сведения см. в разделе Размер и положение сообщений.

Системные команды

Приложение с меню окна может изменить размер и положение этого окна, отправив системные команды. Системные команды создаются при выборе пользователем команд в меню окна. Приложение может эмулировать действие пользователя, отправив WM_SYSCOMMAND сообщение в окно. Следующие системные команды влияют на размер и положение окна.

Команда Описание
SC_CLOSE Закрывает окно. Эта команда отправляет в окно сообщение WM_CLOSE. Окно выполняет все шаги, необходимые для очистки и уничтожения самого себя.
SC_MAXIMIZE Разворачивает окно.
SC_MINIMIZE Свернуть окно.
SC_MOVE Перемещает окно.
SC_RESTORE Восстанавливает свернутое или развернутое окно в прежний размер и положение.
SC_SIZE Запускает команду для изменения размера. Чтобы изменить размер окна, используйте мышь или клавиатуру.

 

Функции размера и положения

После создания окна приложение может задать размер или позицию окна, вызвав одну из нескольких различных функций, включая SetWindowPlacement, MoveWindow, SetWindowPosи DeferWindowPos. SetWindowPlacement задает положение окна в свернутом и развернутом состояниях, размер и положение после восстановления, а также состояние отображения. Функции MoveWindow и SetWindowPos похожи; оба задают размер или позицию одного окна приложения. Функция SetWindowPos включает набор флагов, влияющих на состояние отображения окна; MoveWindow не включает эти флаги. Используйте функции BeginDeferWindowPos, DeferWindowPosи EndDeferWindowPos, чтобы одновременно задать положение ряда окон, включая размер, позицию, позицию в z-порядке и показать состояние.

Приложение может получить координаты ограничивающего прямоугольника окна с помощью функции GetWindowRect. GetWindowRect заполняет структуру RECT координатами верхнего левого и нижнего углов окна. Координаты отсчитываются относительно левого верхнего угла экрана, даже если это дочернее окно. Функция ScreenToClient или MapWindowPoints сопоставляет координаты экрана ограничивающего прямоугольника дочернего окна с координатами относительно клиентской области родительского окна.

Функция GetClientRect извлекает координаты клиентской области окна. GetClientRect заполняет структуруRECTкоординатами левого и нижнего правых углов клиентской области, но координаты относятся к самой клиентской области. Это означает, что координаты верхнего левого угла клиентской области всегда (0,0), а координаты нижнего правого угла — ширина и высота клиентской области.

Функция CascadeWindows каскадирует окна на рабочем столе или каскадирует дочерние окна указанного родительского окна. Функция TileWindows размещает окна на рабочем столе в виде плитки или располагает в виде плитки дочерние окна указанного родительского окна.

Размер и положение сообщений

Система отправляет сообщение WM_GETMINMAXINFO в окно, размер или положение которого будет изменено. Например, сообщение отправляется, когда пользователь щелкает переместить или Размер в меню окна или щелкает границу размера или строку заголовка; Сообщение также отправляется при вызове приложения SetWindowPos для перемещения или размера окна. WM_GETMINMAXINFO включает указатель на структуру MINMAXINFO, содержащую максимальный размер и позицию по умолчанию для окна, а также минимальный и максимальный размер отслеживания по умолчанию. Приложение может переопределить значения по умолчанию, обрабатывая WM_GETMINMAXINFO и устанавливая соответствующие члены MINMAXINFO. Окно должно иметь стиль WS_THICKFRAME или WS_CAPTION для получения WM_GETMINMAXINFO. Окно с стилем WS_THICKFRAME получает это сообщение во время процесса создания окна, а также при перемещении или размере.

Система отправляет сообщение WM_WINDOWPOSCHANGING для окна, размер, позиция, место в z-порядке или состояние отображения которого будут изменяться. Это сообщение содержит указатель на структуру WINDOWPOS, указывающую новый размер окна, позицию, позицию в порядке z и состояние отображения. Задав элементы WINDOWPOS, приложение может повлиять на новый размер, положение и внешний вид окна.

После изменения размера окна, позиции, позиции в z-порядке или отображения состояния система отправляет в окно сообщение WM_WINDOWPOSCHANGED. Это сообщение содержит указатель на WINDOWPOS, который сообщает окну о его новом размере, положении, позиции в z-порядке и состоянии отображения. Установка элементов структуры WINDOWPOS, передаваемой с помощью WM_WINDOWPOSCHANGED, не влияет на окно. Окно, которое должно обрабатывать WM_SIZE и сообщения WM_MOVE, должно передавать WM_WINDOWPOSCHANGED в функцию DefWindowProc; в противном случае система не отправляет WM_SIZE и WM_MOVE сообщения в окно.

Система отправляет сообщение WM_NCCALCSIZE в окно при создании или размере окна. Система использует сообщение для вычисления размера клиентской области окна и положения клиентской области относительно верхнего левого угла окна. Обычно окно передает это сообщение процедуре окна по умолчанию; однако это сообщение может быть полезно в приложениях, которые настраивают неклиентную область окна или сохраняют части клиентской области при изменении размера окна. Дополнительные сведения см. в Живопись и рисование.

Анимация окна

Специальные эффекты можно создавать при отображении или скрытии окон с помощью функции AnimateWindow. Если окно анимировано таким образом, система будет либо свернуть, сдвинуть или затухнуть окно, в зависимости от указанных вами флагов в вызове AnimateWindow.

По умолчанию система использует анимацию свертывания. С этим эффектом окно как бы разворачивается (показывая окно) или сворачивается (скрывая окно). Можно использовать параметр dwFlags, чтобы указать, перемещается ли окно горизонтально, вертикально или по диагонали.

При указании флага AW_SLIDE система использует анимацию слайдов. С этим эффектом окно плавно появляется на экране (показ окна) или исчезает с экрана (скрытие окна). Можно использовать параметр dwFlags для указания, будет ли окно скользить горизонтально, вертикально или по диагонали.

При указании флага AW_BLEND система использует альфа-растушевку.

Вы также можете использовать флаг AW_CENTER, чтобы окно сворачивалось внутрь и расширялось наружу.

Макет окна и зеркальное отображение

Макет окна определяет, как текст и объекты графического интерфейса Windows Graphics Device Interface (GDI) размещаются в контексте окна или устройства (DC). Для некоторых языков, таких как английский, французский и немецкий, требуется макет слева направо (LTR). Другие языки, такие как арабский и иврит, требуют макета справа налево (RTL). Макет окна применяется к тексту, но также влияет на другие элементы GDI окна, включая растровые изображения, значки, расположение источника, кнопки, каскадные элементы управления деревом, а также увеличивается ли горизонтальная координата при переходе слева или вправо. Например, после установки макета RTL в приложении источник расположен в правом краю окна или устройства, а число, представляющее горизонтальную координату, увеличивается по мере перемещения влево. Однако не все объекты подвержены влиянию макета окна. Например, макет диалоговых окон, полей сообщений и контекстов устройств (DC), которые не связаны с окном, такие как метафайлы и контексты принтера, должны обрабатываться отдельно. Конкретные сведения об этих параметрах упоминаются далее в этом разделе.

Функции окна позволяют указать или изменить макет окна в арабских и ивритских версиях Windows. Обратите внимание, что изменение макета RTL (также известное как зеркальное отображение) не поддерживается для окон с CS_OWNDC стиля или контроллера домена с GM_ADVANCED графическим режимом.

По умолчанию макет окна "слева направо" (LTR). Чтобы задать макет окна RTL, вызовите CreateWindowEx со стилем WS_EX_LAYOUTRTL. Кроме того, по умолчанию дочернее окно (то есть создается с помощью стиля WS_CHILD и с допустимым родительским hWnd параметром в вызове CreateWindow или CreateWindowEx) имеет тот же макет, что и его родительский. Чтобы отключить наследование зеркального отображения для всех дочерних окон, укажите WS_EX_NOINHERITLAYOUT в вызове CreateWindowEx. Обратите внимание, что зеркальное отображение не наследуется окнами, которые создаются без стиля WS_CHILD или окнами, для которых родительский параметр hWnd в CreateWindowEx задан как NULL. Чтобы отключить наследование зеркального отображения для отдельного окна, обработайте сообщение WM_NCCREATE с помощью GetWindowLong и SetWindowLong, чтобы отключить флаг WS_EX_LAYOUTRTL. Эта обработка выполняется дополнительно к любой другой необходимой обработке. В следующем фрагменте кода показано, как это сделать.

SetWindowLong (hWnd, 
               GWL_EXSTYLE, 
               GetWindowLong(hWnd,GWL_EXSTYLE) & ~WS_EX_LAYOUTRTL))

Макет по умолчанию можно задать для RTL, вызвав SetProcessDefaultLayout(LAYOUT_RTL). Все окна, созданные после вызова, будут зеркальны, но существующие окна не затронуты. Чтобы отключить зеркальное отображение по умолчанию, вызовите SetProcessDefaultLayout(0).

Обратите внимание, что SetProcessDefaultLayout зеркально отражает только контроллеры домена зеркальных окон. Чтобы отразить любой контекст устройства, вызовите SetLayout(hdc, LAYOUT_RTL). Дополнительные сведения см. в обсуждении контекстов зеркального отображения устройств, не связанных с окнами, которые будут приведены далее в этом разделе.

Растровые изображения и значки в зеркальном окне также зеркально отражаются по умолчанию. Однако не все из них должны быть отражены. Например, объекты, такие как текст, логотип компании или аналоговые часы, не следует зеркалить. Чтобы отключить зеркальное отображение растровых изображений, вызовите SetLayout с установленным битом LAYOUT_BITMAPORIENTATIONPRESERVED в dwLayout. Для отключения зеркального отображения в DC вызовите SetLayout(hdc, 0).

Чтобы запросить текущий макет по умолчанию, вызовите GetProcessDefaultLayout. После успешного возврата pdwDefaultLayout содержит LAYOUT_RTL или 0. Чтобы запросить параметры макета контекста устройства, вызовите GetLayout. При успешном возвращении GetLayout возвращает DWORD, указывающий параметры макета согласно настройкам параметров LAYOUT_RTL и битов LAYOUT_BITMAPORIENTATIONPRESERVED.

После создания окна измените макет с помощью функции SetWindowLong. Например, это необходимо, если пользователь изменяет язык пользовательского интерфейса существующего окна с арабского или иврита на немецкий. Однако при изменении макета существующего окна необходимо сделать недействительным и обновить окно, чтобы убедиться, что содержимое окна рисуется на одном макете. В следующем примере кода демонстрируется изменение макета окна по мере необходимости:

// Using ANSI versions of GetWindowLong and SetWindowLong because Unicode
// is not needed for these calls

lExStyles = GetWindowLongA(hWnd, GWL_EXSTYLE);

// Check whether new layout is opposite the current layout
if (!!(pLState -> IsRTLLayout) != !!(lExStyles & WS_EX_LAYOUTRTL))
{
    // the following lines will update the window layout

    lExStyles ^= WS_EX_LAYOUTRTL;        // toggle layout
    SetWindowLongA(hWnd, GWL_EXSTYLE, lExStyles);
    InvalidateRect(hWnd, NULL, TRUE);    // to update layout in the client area
}

При зеркальном отображении следует мыслить понятиями "близко" и "далеко" вместо "слева" и "справа". Невыполнение этого может вызвать проблемы. Одна из распространенных методик программирования, которая вызывает проблемы в зеркальном окне, возникает при сопоставлении координат экрана и клиентских координат. Например, приложения часто используют код, аналогичный следующему, чтобы разместить элемент управления в окне:

// DO NOT USE THIS IF APPLICATION MIRRORS THE WINDOW

// get coordinates of the window in screen coordinates
GetWindowRect(hControl, (LPRECT) &rControlRect);  

// map screen coordinates to client coordinates in dialog
ScreenToClient(hDialog, (LPPOINT) &rControlRect.left); 
ScreenToClient(hDialog, (LPPOINT) &rControlRect.right);

Это приводит к проблемам зеркального отображения, так как левый край прямоугольника становится правым краем в зеркальном окне, и наоборот. Чтобы избежать этой проблемы, замените вызовы ScreenToClient вызовом MapWindowPoints следующим образом:

// USE THIS FOR MIRRORING

GetWindowRect(hControl, (LPRECT) &rControlRect);
MapWindowPoints(NULL, hDialog, (LPPOINT) &rControlRect, 2)

Этот код работает, так как на платформах, поддерживающих зеркальное отображение, MapWindowPoints изменяется, чтобы переключить координаты левой и правой точки при зеркальном отображении окна клиента. Дополнительные сведения см. в разделе "Примечания" MapWindowPoints.

Другая распространенная практика, которая может вызвать проблемы в зеркальных окнах, — размещение объектов в окне клиента с помощью смещения в координатах экрана вместо координат клиента. Например, следующий код использует разницу в координатах экрана в качестве позиции x в координатах клиента для размещения элемента управления в диалоговом окне.

// OK if LTR layout and mapping mode of client is MM_TEXT,
// but WRONG for a mirrored dialog 

RECT rdDialog;
RECT rcControl;

HWND hControl = GetDlgItem(hDlg, IDD_CONTROL);
GetWindowRect(hDlg, &rcDialog);             // gets rect in screen coordinates
GetWindowRect(hControl, &rcControl);
MoveWindow(hControl,
           rcControl.left - rcDialog.left,  // uses x position in client coords
           rcControl.top - rcDialog.top,
           nWidth,
           nHeight,
           FALSE);

Этот код подходит, когда в диалоговом окне используется направление макета слева направо (LTR), а режим отображения клиента — MM_TEXT, поскольку новая позиция x в клиентских координатах соответствует разнице между левыми гранями элемента управления и диалогового окна в экранных координатах. Однако в зеркальном диалоговом окне влево и вправо будут изменены, поэтому вместо этого следует использовать MapWindowPoints следующим образом:

RECT rcDialog;
RECT rcControl;

HWND hControl - GetDlgItem(hDlg, IDD_CONTROL);
GetWindowRect(hControl, &rcControl);

// MapWindowPoints works correctly in both mirrored and non-mirrored windows.
MapWindowPoints(NULL, hDlg, (LPPOINT) &rcControl, 2);

// Now rcControl is in client coordinates.
MoveWindow(hControl, rcControl.left, rcControl.top, nWidth, nHeight, FALSE)

Диалоговые окна зеркального отображения и поля сообщений

Диалоговые окна и поля сообщений не наследуют макет, поэтому необходимо явно задать макет. Для зеркального отображения окна сообщения вызовите MessageBox или MessageBoxEx с параметром MB_RTLREADING. Чтобы макетировать диалоговое окно справа налево, используйте расширенный стиль WS_EX_LAYOUTRTL в структуре шаблона диалога DLGTEMPLATEEX. Листы свойств — это особый случай диалоговых окон. Каждая вкладка рассматривается как самостоятельное диалоговое окно, поэтому необходимо включить стиль WS_EX_LAYOUTRTL на каждой вкладке, которую требуется зеркально отразить.

Контексты зеркального отображения устройства, не связанные с окном

Дескрипторы устройства, не связанные с окном, такие как метафайлы или дескрипторы принтера, не наследуют разметку, поэтому необходимо явно указать разметку. Чтобы изменить макет контекста устройства, используйте функцию SetLayout.

ФункцияSetLayoutредко используется с окнами. Как правило, окна получают связанный контроллер домена только при обработке сообщения WM_PAINT. Иногда программа создает контроллер домена для окна, вызывая GetDC. В любом случае начальный макет контроллера домена устанавливается BeginPaint или GetDC в соответствии с флагом WS_EX_LAYOUTRTL окна.

Значения, возвращаемые GetWindowOrgEx, GetWindowExtEx, GetViewportOrgEx и GetViewportExtEx не влияют на вызов SetLayout.

Если макет имеет значение RTL, GetMapMode вернет MM_ANISOTROPIC вместо MM_TEXT. Вызов SetMapMode с MM_TEXT будет работать правильно; затрагивается только возвращаемое значение из GetMapMode. Аналогичным образом, вызов SetLayout(hdc, LAYOUT_RTL), когда режим сопоставления — MM_TEXT, приводит к тому, что отчетный режим сопоставления меняется на MM_ANISOTROPIC.

Уничтожение окна

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

Приложение уничтожает многие окна, которые он создает вскоре после их создания. Например, приложение обычно уничтожает диалоговое окно, как только приложение имеет достаточно входных данных от пользователя, чтобы продолжить свою задачу. Приложение в конечном итоге уничтожает главное окно приложения (перед завершением).

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

Уничтожение окна не влияет на класс окна, из которого создается окно. Новые окна по-прежнему можно создавать с помощью этого класса, и все существующие окна этого класса продолжают работать. Уничтожение окна также уничтожает его дочерние окна. Функция DestroyWindow отправляет WM_DESTROY сообщение сначала в окно, а затем в дочерние окна и окна потомков. Таким образом, все окна потомки удаляемого окна также уничтожаются.

Окно с меню окна получает сообщение WM_CLOSE, когда пользователь щелкает закрыть. Обрабатывая это сообщение, приложение может запрашивать подтверждение, прежде чем уничтожить окно. Если пользователь подтверждает, что окно должно быть уничтожено, приложение может вызвать функцию DestroyWindow, чтобы уничтожить окно.

Если разрушенное окно является активным окном, то активные и фокусные состояния передаются в другое окно. Окно, которое становится активным окном, является следующим окном, как определено сочетанием клавиш ALT+ESC. Затем новое активное окно определяет, какое окно получает фокус клавиатуры.