Эта статья описывает программные элементы, которые приложения могут использовать для создания и управления окнами; управления отношениями между окнами; изменения размера, перемещения и отображения окон.
Содержание:
- Окно рабочего стола
- Окна приложений
- Элементы управления и диалоговые окна
- Атрибуты окон
- Примечания переводчика (специфика Delphi)
Окно рабочего стола
Когда вы запускаете систему, она автоматически создаёт окно рабочего стола (desktop window). Окно рабочего стола - это системное окно, которое отвечает за отрисовку фона экрана и служит базой для всех остальных окон, показываемых приложениями. И поэтому, окно рабочего стола является особым окном.Окно рабочего стола использует растр (bitmap) для рисования фона экрана. Этот рисунок называется обоями рабочего стола (desktop wallpaper). По умолчанию окно рабочего стола использует растр из .bmp файла, указанного в настройках системы.
Функция
GetDesktopWindow
возвращает описатель окна рабочего стола.Приложения настройки системы (такие как апплет Панели управления) могут изменять обои рабочего стола, используя функцию
SystemParametersInfo
с wAction = SPI_SETDESKWALLPAPER
и lpvParam = имени файла с обоями. Функция SystemParametersInfo
загрузит растр из указанного файла и будет использовать его для отрисовки фона экрана, и, кроме того, сохранит имя файла в настройках.Окна приложений
Каждое графическое приложение Windows имеет как минимум одно окно, называемое главным окном (main window), которое обеспечивает первичный интерфейс между пользователем и приложением. Большинство приложений создаёт дополнительные окна (явно или неявно), чтобы выполнять задачи приложения. Каждое окно играет свою роль в отображении информации и приёма ввода от пользователя.Когда вы запускаете приложение, система также ассоциирует с приложением кнопку на панели задач (taskbar button). Кнопка на панели задач содержит значок программы и заголовок. Когда приложение активно, эта кнопка показывается как нажатая, либо выделяется цветом.
Окно приложения может включать в себя элементы вроде заголовка (title bar), оконного меню (window menu, ранее известного как "системное меню"), меню (menu bar), кнопок минимизации и максимизации, кнопки восстановления (restore button), кнопки закрытия (close button), бордюра (border), клиентской области (client area), горизонтальной и вертикальной полосок прокрутки (scroll bar). Главное окно приложений часто включает в себя все эти элементы сразу. Рисунок ниже иллюстрирует эти элементы в типичном главном окне программы:
Клиентская область
Клиентская область (client area) является той частью окна, где приложение показывает основную информацию (текст или графику). Например, текстовый редактор отображает документ в клиентской области главного окна. Чтобы управлять клиентской областью окна (принимать ввод пользователя и отображать в ней информацию), приложение должно указать функцию обратного вызова, называемую оконной процедурой (window procedure). См. Window Procedures для дальнейшего обсуждения.Неклиентская область
Заголовок, меню, оконное меню, кнопки минимизации, максимизации, закрытия и восстановления, бордюр и полосы прокрутки собирательно называются неклиентской областью окна (nonclient area). Система автоматически управляет большинством аспектов неклиентской области; приложение же управляет поведением клиентской области окна.Заголовок окна (title bar) показывает значок окна (указывается приложением) и строку текста; обычно текст указывает название приложения и цель окна. Приложение указывает значок и текст при создании окна. Кроме того заголовок также позволяет перемещать окно по экрану, используя мышь или иное указующее устройство.
Большинство приложений добавляют окнам меню (menu bar), которое включает в себя команды, поддерживаемые приложением. Элементы в полоске меню соответствуют категориям команд меню. Щелчок по элементу меню обычно приводит к его "раскрытию": показу всплывающего меню с элементами, соответствующими заданной категории. Щёлкая по элементу-команде, пользователь просит приложение выполнить эту задачу.
Оконное меню (window menu) создаётся и управляется системой (и поэтому оно ранее называлось системным меню). Оно содержит стандартный набор команд по управлению окном - вроде изменения размера и положения окна, его закрытия. Для получения дальнейшей информации - см. Menus.
Кнопки в верхнем-правом углу окна влияют на размер и положение окна. Когда пользователь щёлкает по кнопке максимизации (maximize button), система увеличивает окно до размера текущего монитора, так что оно займёт весь рабочий стол минус панель задач (в одномониторной конфигурации). Одновременно с этим система заменит кнопку максимизации кнопкой восстановления. Когда вы щёлкаете по кнопке восстановления (restore button), система восстанавливает окно на его исходной позиции и с исходным размером. Когда вы щёлкаете по кнопке минимизации (minimize button), система уменьшает окно до размера её кнопки на панели задач, размещает окно поверх его кнопки на панели задач и показывает кнопку на панели задач в поднятом (нормальном) состоянии (прим. пер.: это описание - упрощение). Чтобы восстановить приложение с его исходными положением и размерами - щёлкните по кнопке в панели задач. Когда вы щёлкаете по кнопке закрытия (close button), приложение выходит.
Бордюр (border) - это область по периметру окна, которая позволяет пользователю изменять размер окна, используя мышь или иное указующее устройство.
Полосы прокрутки (scroll bar) переводят ввод с клавиатуры и мыши в смещения, которые используются приложением для сдвига содержимого клиентской области. К примеру, приложение текстовый редактор может показывать большой документ с вертикальной полосой прокрутки, чтобы пользователь мог использовать её для перемещения по документу.
Элементы управления и диалоговые окна
Приложение может создавать несколько типов окон в дополнение к его главному окну, включая элементы управления (controls) и диалоговые окна (dialog box).Элемент управления (control) - это окно, которое приложение использует для получения информации от пользователя. Приложения также используют элементы управления, чтобы управлять определённой возможностью приложения. К примеру, элементами управления являются кнопки, списки, поля ввода, дополнительные полосы прокрутки, панели, панели инструментов и т.п. Для дальнейшей информации -см. Windows Controls.
Элементы управления не могут использовать сами по себе и всегда используются с другим окном - обычно, диалоговым окном. Диалоговое окно (dialog box) - это окно, которое содержит один или более элементов управления. Приложение использует диалоговые окна, чтобы запросить у пользователя информацию для выполнения команды. К примеру, приложение, которое имеет команду открытия файла, может показывать диалоговое окно, которое включает в себя элементы управления для указания имени и пути файла. Диалоговые окна обычно не используют те же компоненты окна, что и главные окна приложения. Большинство диалоговых окон имеют заголовок, системное меню, кнопки минимизации/максимизации и закрытия, бордюр (часто - не позволяющий менять размеры окна) и клиентскую область, но они обычно не имеют меню и полос прокрутки. Для получения дополнительной информации - см. Dialog Boxes.
Окно-сообщение (message box) - это специальное диалоговое окно, которое показывает сообщение, предупреждение или сообщение об ошибке пользователю. К примеру, окно-сообщение может использоваться, чтобы сообщить пользователю о невозможности выполнения запрошенной им операции. Для дальнейшей информации - см. Message Boxes.
Оконные атрибуты
Приложение должно указывать следующую информацию при создании окна (за исключением оконного описателя, который создаёт сама функция создания окон):- Имя класса
- Имя окна
- Стиль окна
- Дополнительный стиль окна
- Положение
- Размер
- Описатель родительского окна или окна-владельца
- Описатель меню или идентификатор дочернего окна
- Описатель экземпляра
- Пользовательские данные
- Оконный описатель
Имя класса
Каждое окно принадлежит оконному классу. Приложение должно зарегистрировать оконный класс до создания окна этого класса. Оконный класс (window class) определяет большинство аспектов поведения и отображения окна. Главным компонентом оконного класса является оконная процедура (window procedure) - функция обратного вызова, которая принимает весь ввод пользователя и все запросы, отправленные окну. Система предоставляет ей ввод и запросы в виде оконных сообщений (window message). Для дальнейшей информации - см. Window Classes, Window Procedures и Messages and Message Queues.Имя окна
Имя окна (window name) - это текстовая строка, которая идентифицирует окно для пользователя. Главное окно, диалоговое окно или окно-сообщение обычно показывают это имя в заголовке окна. Элемент управления также может показывать имя окна, в зависимости от своего оконного класса. К примеру, кнопки, поля ввода и статический текст показывают имя окна в прямоугольнике элемента управления. С другой стороны, элементы вроде списков и списков выбора не показывают имена окон.Чтобы изменить имя окна после создания окна, используйте функцию
SetWindowText
. Используйте функции GetWindowTextLength
и GetWindowText
для получения имени окна.См. также: тайная жизнь
GetWindowText
.Стиль окна
Каждое окно имеет один или несколько оконных стилей. Оконный стиль (window style) - это числовая константа, которая определяет аспект поведения или отображения, не указанный в оконном классе. Приложение обычно устанавливает стили во время создания окна. Но оно также может изменить некоторые стили после создания окна, используя функциюSetWindowLong
.Стили интерпретируются системой и, в некотором роде, оконной процедурой класса окна.
Некоторые оконные стили применимы к любым окнам, но большинство стилей специфичны для оконных классов. Общие стили представлены константами, которые начинаются с префикса
WS_
; вы можете комбинировать стили, используя оператор or
. Стили окна, специфичные для оконного класса, определяют поведение и отображение окон, принадлежащих этому классу. К примеру, класс SCROLLBAR
создаёт элемент управления "полоса прокрутки". При этом стили SBS_HORZ
и SBS_VERT
указывают создаётся ли вертикальная или горизонтальная полоса прокрутки.Вот описание стилей для некоторых стандартных системных оконных классов:
- Window Styles
- Button Styles
- Combo Box Styles
- Edit Control Styles
- List Box Styles
- Rich Edit Control Styles
- Scroll Bar Control Styles
- Static Control Styles
Расширенный стиль окна
Каждое окно опционально может иметь один или несколько дополнительных (расширенных) оконных стилей. Расширенный оконный стиль (extended window style) - это числовая константа, которая определяет аспект окна, не указанный в классе окна или простом стиле окна. Приложение обычно устанавливает расширенные стили во время создания окна. Но оно также может изменить некоторые стили после создания окна, используя функциюSetWindowLong
.Для дальнейшей информации - см.
CreateWindowEx
.Положение
Положение окна определяется как координаты его левого-верхнего угла, измеряемые в пикселях экрана. Эти координаты (иногда называемые оконными координатами (window coordinates)) всегда относительны левого-верхнего угла экрана или (для child окон) - левого-верхнего угла клиентской области родительского окна. К примеру, окно верхнего уровня с координатами (10,10) размещается на 10 пикселей правее левого-верхнего угла экрана и на 10 пикселей ниже его. С другой стороны, child окно с координатами (10,10) размещается на 10 пикселей правее и на 10 пикселей ниже левого-верхнего угла клиентской области родительского окна.Функция
WindowFromPoint
ищет окно, занимающее указанную точку на экране, и возвращает его описатель. Аналогичным образом, функция ChildWindowFromPoint
и функция ChildWindowFromPointEx
возвращают описатель дочернего окна, занимающего указанную точку в родительском окне. Хотя ChildWindowFromPointEx
может игнорировать невидимые, отключенные и прозрачные окна - ChildWindowFromPoint
перечисляет их все.Размер
Размер окна (высота и ширина) измеряется в пикселях. Окно может иметь нулевую высоту или нулевую ширину. Если приложение задаст нулевые высоту или ширину, то система установит размер в минимально допустимый. Чтобы определить минимально возможный размер окон, приложение может вызвать функциюGetSystemMetrics
с флагами SM_CXMIN
и SM_CYMIN
.Приложению может потребоваться создать окно с клиентской областью определённого размера (обычно приложение задаёт размеры окна, а клиентская область получается по окну за вычетом размера рамки, заголовка и т.п.). Функция
AdjustWindowRect
и функция AdjustWindowRectEx
могут быть использованы для вычисления нужного размера окна, основываясь на желаемом размере клиентской области окна. Приложение может передать вычисленные значения размера в функцию CreateWindowEx
.Приложение может изменить размер окна на чрезмерно большой; однако ему не следует изменять размер окна на размер, больший экрана. До изменения размеров окна, приложение может узнать размеры экрана, используя функцию
GetSystemMetrics
с флагами SM_CXSCREEN
и SM_CYSCREEN
.Описатель родительского окна или окна-владельца
Окно может иметь родительское окно. Окно, которое имеет родительское окно, называется дочерним окном (child window). Родительское окно (parent window) предоставляет своим дочерним окнам систему координат для относительного позиционирования. Если у окна есть окно-родитель, то это влияет на его отображение; к примеру, дочернее окно обрезается так, чтобы оно не выходило за пределы родительского окна и (опционально) за пределы клиентской области родительского окна. Окно, у которого нет родителя, либо же родительским окном является окно рабочего стола, называется окном верхнего уровня (top-level window). Приложение может использовать функциюEnumWindows
, чтобы получить описатель каждого окна верхнего уровня в системе.Кроме того, окно может владеть другим окном или иметь окно-владельца (owner window). Владетельное окно всегда появляется поверх своего владельца, оно также сворачивается, когда сворачивается его владелец, и уничтожается, когда уничтожается его владелец. Для дальнейшей информации - см. Owned окна.
Описатель меню или идентификатор дочернего окна
Child окно может иметь идентификатор дочернего окна (child-window identifier) - это уникальное число, присваиваемое приложением. Идентификатор дочернего окна особенно полезен для приложений, создающих несколько дочерних окон. Когда приложение создаёт дочернее окно, оно может указать идентификатор для этого окна. После создания окна приложение может поменять идентификатор функциейSetWindowLong
или получить его функцией GetWindowLong
.Каждое окно, кроме child-окон, может иметь меню. Приложение может добавить меню в окно, указав описатель меню либо при регистрации оконного класса, либо непосредственно при создании окна.
Описатель экземпляра
Каждый исполняемый модуль (exe или DLL) имеет описатель, ассоциированный с ним. Система использует этот идентификатор, чтобы отличать оконные классы, создаваемые разными модулями.Пользовательские данные
Каждое окно может иметь ассоциированные с ним пользовательские данные, не используемые системой. Когда создаётся окно, система передаёт указатель на пользовательские данные в оконную процедуру создаваемого окна. Оконная процедура может использовать эти данные для инициализации окна и (опционально) для сохранения данных с окном.Описатель окна
После создания окна функция создания возвращает оконный описатель (window handle), который уникально идентифицирует окно в системе. Оконный описатель имеет типHWND
. Приложение может использовать этот описатель в других функциях работы с окнами.Примечания переводчика
Приложения Delphi имеют некоторые особенности по сравнению с вышеизложенным материалом.Предупреждение: я не являюсь экспертом в интерфейсе пользователя, поэтому текст ниже может содержать ошибки.
Окна в VCL
В Delphi вся работа с окнами заключается в класс-оболочкуTWinControl
. Формы, кнопки, списки - всё это классы, наследуемые от TWinControl
. К примеру: TForm1 -> TForm -> TCustomForm -> TScrollingWinControl -> TWinControl
или TButton -> TCustomButton -> TButtonControl -> TWinControl
.У каждого объекта типа
TWinControl
есть описатель - свойство Handle
типа HWND
. Этот описатель создаётся по запросу - при первом обращении к свойству Handle
. Эту проверку выполняет метод HandleNeeded
. Создание описателя выполняет метод CreateHandle
, который является обёрткой к методу CreateWnd
. Фактически, метод CreateHandle
просто вызывает CreateWnd
, выполняя пост-настройку объекта после создания окна (настройка якорей и ассоциация объекта TWinControl
с окном).Само создание окна выполняется так: сперва метод
CreateWnd
строит параметры окна, используя метод CreateParams
, который заполняет запись типа TCreateParams
. Эти параметры проверяются на допустимость, в них записывается оконная процедура и вызывается метод CreateWindowHandle
, который, собственно, и создаёт окно (и является простой обёрткой к функции CreateWindowEx
).Если вы заинтересованы в изменении создаваемого окна, то вы можете заместить метод
CreateParams
(если вам нужно просто поменять параметры создания окна), CreateWindowHandle
(если вы хотите задавать параметры явно вручную), либо CreateWnd
(если вы хотите сделать пост-обработку создания окна).Оконной процедурой (точкой входа) в
TWinControl
является метод MainWndProc
. Этот метод не виртуален, но всё, что он делает - вызывает настоящую оконную процедуру WindowProc
, обернув вызов в try
/except
и вызывая Application.HandleException
при ошибке. Именно это - то самое место, в котором вы получаете сообщение об ошибке при исключении в обработчике сообщения (например, нажатия на кнопку) вместо вылета программы. Сама же оконная процедура WindowProc
является и вовсе свойством, которое можно присвоить в любое значение (для установки своей оконной процедуры). По умолчанию, WindowProc
указывает на (виртуальный) метод WndProc
того же объекта. Как правило, если вы хотите дополнить или заменить оконную процедуру, то вы должны заметить метод WndProc
в классе-наследнике (если вы хотите выполнить замещение в "вашем" классе), либо изменить свойство WindowProc
(если вы хотите изменить поведение внешнего объекта).Метод
WndProc
является конечной реализацией оконной процедуры. Собственно, это даже не "изобретение" TWinControl
- этот метод появился у предка TWinControl
: TControl
. TControl
является базовым классом для всех элементов управления, необязательно оконных. Оконные элементы управления наследуются от TWinControl
.Таким образом, цепочка вызовов при обработке сообщений выглядит так:
MainWndProc -> WindowProc -> WndProc
. WndProc
может сама обработать сообщение, а может оставить его на обработку по умолчанию. В последнем случае сообщение дополнительно проходит такой путь: WndProc -> Dispatch -> DefaultHandler -> DefWndProc
. Метод Dispatch
сначала пытается направить сообщение message-методам. И только при их отсутствии - вызывает DefaultHandler
. DefWndProc
вызывается только для оконных контролов при наличии описателя. Таким образом, если вы заинтересованы в необработанных сообщениях - то вам нужно использовать DefWndProc
для окон и DefaultHandler
для неоконных контролов.Заметьте, что
Dispatch
, DefaultHandler
и message-методы вводятся аж в TObject
, что означает доступность диспетчеризации сообщений для любого объекта Delphi.Почти все вышеупомянутые методы являются виртуальными - т.е. доступными для замещения и модификации в классах-наследниках, что позволяет нам менять стандартное поведение в широких пределах.
TComponent
(который является предком TControl
, а, следовательно и TWinControl
) вводит понятие "владельца" компонента (Owner). Заметьте, что это не то же самое понятие, что окно-владелец в терминах системы, как обсуждается выше. Окно-владелец и окно-родитель (в терминах системы) указываются одинаковым образом - как поле WndParent
в записи TCreateParams
, параметр hWndParent
в функции CreateWindowEx
и аналогичных местах. То, как трактуется это окно (как родитель или владелец) зависит от типа создаваемого окна (дочернее или верхнего уровня). Поведение этих окон описано выше.Delphi же вводит понятие владельца в ином смысле. Владелец (в терминах Delphi) - это компонент, который отвечает за удаление владеемого компонента. Его можно указать при создании компонента, либо сменить/задать уже после создания (что бывает редко). При удалении компонента-владельца удаляются и все компоненты, которыми владеет владелец. Вы можете не указывать владельца, если хотите удалять компонент сами, вручную. Как правило, форма является владельцем всех компонентов, размещённых на ней.
Вам не следует путать владельца в терминах системы и владельца в терминах Delphi. Владелец в терминах системы отвечает за взаимодействие окон. Владелец в терминах Delphi не связан с окнами, он контролирует время жизни объекта. Фактически, он применим также и к неоконным элементам управления и даже невизуальным компонентам.
Примечание: Delphi также позволяет вам изменить родительское окно уже после создания объекта. Это позволяет вам сделать "перескакивание" дочернего контрола с одного контейнера (формы, панели) на другой.
Окно Application
Следующий тонкий момент связан со специальным окном Application в Delphi. Как вам должно быть известно, в Delphi есть глобальный объектApplication
, представляющий собой "приложение". В нём содержатся глобальные параметры и некоторые служебные методы-помощники. Сейчас нас интересует тот факт, что в Application
есть окно. Это - служебное окно. Его описатель доступен через свойство Application.Handle
. Это окно является обычным окном. Оно видимо, находится на экране (в центре), но... имеет нулевой размер! Так что реально вы его увидеть не можете, не можете и щёлкнуть по нему.Примечание: окно
Application
создаётся только в программе, но не в DLL.Хорошо, а чем ещё интересно это окно? Вспомните правила, по которым окна появляются на панели задач. Идеология системы: одно окно - одна кнопка. Каждое окно имеет кнопку (некоторые окна не имеют кнопок как служебные), окно не может иметь две кнопки. Если на панели задач есть кнопка, то она имеет взаимно-однозначное соответствие с окном (текст, меню, иконка). Это достаточно простая и понятная модель.
В Delphi принята несколько иная идеология. Кнопка в панели задач представляет собой "приложение", а не отдельное окно. У неё свой заголовок, своя иконка, она сворачивает все окна приложения - и так далее. Поскольку в системе окна работают не так, то Delphi эмулирует такое поведение. Кнопка в панели задач - это, на самом деле, окно Application, а реальные окна программы там не появляются. Все окна приложения имеют владельца - окно Application. Сворачивание приложения на самом деле заключается в скрытии окон (реально сворачивается только окно Application). При этом, конечно же, куча сил уходит на синхронизацию различных состояний между участниками подобной системы. Отсюда идёт множество вопросов вроде "как мне свернуть/развернуть приложение в трей", вопросов про правильную связку окон и им подобных.
Когда вышла Windows Vista, в которой появились новые возможности вроде "живого предпросмотра", анимации сворачивания/разворачивания окон и других Aero-эффектов, обнаружились пробелы в модели эмуляции поведения Delphi. Delphi приложения в новых условиях вели себя не лучшим образом. Реализованная в Delphi эмуляция не смогла покрыть возможности новой системы. Delphi приложения усиленно притворялись нормальными, но это им не удалось.
Поэтому, вместо того, чтобы допиливать эмуляцию до нового уровня (и снова "проиграть" при выходе новой системы Windows с новыми возможностями), разработчики Delphi просто решили играть по правилам системы. Начиная с Delphi 2007 окна ведут себя так, как положено, не пытаясь эмулировать иную концепцию взаимодействия окон. Теперь на панели задач показывается настоящее главное окно (и именно поэтому
Application.Title
и Application.Icon
не будут иметь эффекта). Вы можете переключаться между старым и новым поведением приложения переключая свойство MainFormOnTaskBar
. Предполагается, что вы измените его один раз - сразу после вызова Application.Initialize
в .dpr-файле проекта и не будете трогать в дальнейшем.Я бы рекомендовал по возможности использовать новое поведение на Delphi 2007+. Гораздо лучше, когда ваше приложение играет по правилам системы, и вам будет проще разбираться с вопросами взаимодействия окон (если у вас не будет дополнительного скрытого окна в цепочке).
Заметьте, что новые правила поведения окон отличаются от старых. К примеру, если раньше вы создавали немодальное окно - оно появлялось наравне со старым. Вы могли переключаться между ними и выносить любое из них на передний план. Это потому, что оба окна (и главное и немодальное) были равноценны - они имели окно-владельца Application. Они сворачивались вместе с ним, но между собой они были равны. Теперь же, если вы создадите окно, то ему придётся включить главное окно как своего владельца. Это даст вам сворачивание вместе с владельцем, единую кнопку на панели задач (т.е. старое поведение вида "единое приложение"), но это также будет означать, что вы не сможете вынести на передний план главное окно - вторичное окно всегда будет поверх окна-владельца (как указано в информации выше). Вам нужно научится играть по новым правилам или от чего-то отказаться.
К примеру, вы можете перегрузить
CreateParams
и очистить поле WndParent
. Тогда вы получите два равноценных окна, не связанных друг с другом. Вы можете вынести любое из них на передний план, но при этом второе окно будет иметь иконку на панели задач и сворачивание одного окна не приведёт к сворачиванию другого. Вы можете бороться с этим дальше, но... нужно ли? Короче говоря, либо вы связываете окна (и миритесь с ограничениями в виде Z-порядка), либо не связываете (и миритесь с ограничениями в виде... не связанности окон).Примечание: окно
Application
всё ещё создаётся - даже при MainFormOnTaskBar = True
. Но только теперь оно используется лишь для служебных целей - реакции на события системы и т.п., но не для управления окнами приложения, как это было ранее. Модальные окна
Ещё одним моментом, где Delphi эмулирует нетипичное поведение в системе, являются модальные окна. В дизайне системы модальность предназначена для диалоговых окон, которые создаются специальными функциями по шаблону из ресурса. Причём модальность диалога указывается специальным флагом -DS_MODALFRAME
. Иными словами, это означает, что одно и то же окно не может показываться в разных режимах - модальном и не модальном. Разумеется, такая модель не подходит для Delphi, где вы можете показывать окно различными способами - вызывая
Show
или ShowModal
. Поэтому Delphi не использует системный механизм модальных окон. Вместо этого она эмулирует поведение модальных окон. Когда вы показываете "модальное" окно, VCL отключает все прочие окна в программе, а после окончания показа окна - восстанавливает их доступность. Отключение окна блокирует взаимодействие с пользователем - вы не можете переключиться в окно и вводить в него информацию. Как правило, отключение окна приводит к изменению его вида: окно-контрол показывается "затенённым". Однако окна-формы не изменяют свой вид. Поэтому отключенное окно визуально не отличается от обычного окна. Так что у вас создаётся впечатление, что окно не отключено, а просто сейчас показывается другое (модальное) окно.Заметьте, что это отличается от модальности в смысле системы. К примеру, приложению приходится рассылать служебные сообщения (вроде
WM_CANCELMODE
) вручную и самому делать вложенный модальный цикл. Второе отличие - модальное окно в смысле системы отключает только своего владельца. Модальное же окно Delphi отключает все окна в приложении (т.е. оно "модально" в более сильном смысле). Именно в этом отличии заключается суть флага MB_TASKMODAL
функции MessageBox
: если вы укажете флаг, то вместо поведения по умолчанию (отключения только окна-владельца), система отключит все окна приложения (как это делает Delphi).
> Владелец (в терминах Delphi) - это компонент, который отвечает за удаление владеемого компонента. Его можно указать при создании компонента и нельзя изменить в дальнейшем.
ОтветитьУдалитьЭто не совсем так. Владельца можно сменить используя методы TComponent.InsertComponent/RemoveComponent
Это не "не совсем так", а это "совсем не так" :)
ОтветитьУдалитьИнтересно, откуда я это взял...
Здравствуйте Александр! Подскажите пожалуйста, можно ли удалить Title bar или написать скрипт для удаления этого элемента окна?
ОтветитьУдалить