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


Функции окна

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

Типы окон

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

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

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

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

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

Всплывающее окно — это особый тип перекрывающегося окна, используемого для диалоговых окон, окон сообщений и других временных окон, которые отображаются вне главного окна приложения. Заголовки являются необязательными для всплывающих окон; В противном случае всплывающие окна совпадают с перекрывающимися окнами стиля 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, то форма многоуровневого окна будет игнорироваться, а события мыши будут переданы другим окнам под слоем окна.

Message-Only Windows

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

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

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

Связи окон

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

Переднее и фоновое windows

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

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

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

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

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

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

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

Процесс, который может задать окно переднего плана, может включить другой процесс, чтобы задать окно переднего плана, вызвав функцию 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 (GDI) размещаются в контексте окна или устройства (DC). Для некоторых языков, таких как английский, французский и немецкий, требуется макет слева направо (LTR). Другие языки, такие как арабский и иврит, требуют макета справа налево (RTL). Макет окна применяется к тексту, но также влияет на другие элементы GDI окна, включая растровые изображения, значки, расположение источника, кнопки, каскадные элементы управления деревом, а также увеличивается ли горизонтальная координата при переходе слева или вправо. Например, после установки макета RTL в приложении источник расположен в правом краю окна или устройства, а число, представляющее горизонтальную координату, увеличивается по мере перемещения влево. Однако не все объекты влияют на макет окна. Например, макет диалоговых окон, полей сообщений и контекстов устройств, которые не связаны с окном, например метафайла и контроллера принтера, должны обрабатываться отдельно. Конкретные сведения об этих параметрах упоминаются далее в этом разделе.

Функции окна позволяют указать или изменить макет окна в арабских и ивритских версиях 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. Чтобы отключить зеркальное отображение в контроллере домена, вызовите 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. Затем новое активное окно определяет, какое окно получает фокус клавиатуры.