Диалоговое окно, отображаемое методом Application.MessageBox
Если пользователь в нем нажмет кнопку Да, то приложение закрывается методом Application.Terminate. Обработчики событий OnActivate и OnDeactivate: procedure TForm1.ApplicationEvents1Activate( Sender: TObject); begin Label1.Caption := 'Уpa! Я работаю!'; end; procedure TForm1.ApplicationEvents1Deactivate( Sender: TObject); begin Label1.Caption: = 'Увы! Меня покинули!'; end; обеспечивают появление в метке Label1 соответствующей надписи каждый раз, когда пользователь переключается из данного приложения в другое и возвращается назад.
Диспетчеризация событий — компоненты, связанные с ActionList
Начиная с Delphi 4 появился инструментарий, который, не добавляя никаких принципиально новых возможностей, позволяет систематизировать и упорядочить разработку объектно-ориентированных приложений. К тому же грамотное его использование позволяет сэкономить немало времени при проектировании. Для организации диспетчеризации событий введены следующие понятия.
Действие (action) — реализация некоторого поведения, являющегося реакцией на поступок пользователя, такой, как щелчок на кнопке или на разделе меню — инициаторе действия. Разработан класс TAction и ряд его наследников, реализующих многие стандартные действия, характерные для приложений Windows.
Список действий — компонент типа ActionList, содержащий предусмотренные в приложении действия. Это интерфейс разработчика, упорядочивающий его работу с действиями в процессе проектирования.
Редактор связей — объект типа TActionLink, который поддерживает связь между действиями и инициаторами действий. Редактор связей определяет, какое действие должно выполняться для данного инициатора.
Цель действия — объект, в котором отражается результат действия. Это может быть окно отображения или редактирования текста, набор данных и т.п.
В начале проектирования приложения разработчик должен представить себе список тех действий, которые может осуществлять пользователь. Конечно, в процессе проектирования этот список будет пополняться и изменяться, но некоторое начальное приближение очень полезно продумать заранее. Практическая реализация составленного вами списка действий может начинаться с переноса на проектируемую форму невизуального компонента ActionList, расположенного на странице библиотеки Standard. Сделав на этом компоненте двойной щелчок, вы попадаете в редактор действий (Рисунок 9.1), позволяющий вводить и упорядочивать действия.
Объект экрана — Screen
В приложении Delphi автоматически создается глобальный объект Screen (экран) типа TScreen, свойства которого определяются из информации Windows о мониторе, на котором запускается приложение. Вы можете в любом приложении использовать, например, такие параметры объекта Screen, как Height — высота экрана и Width — его ширина. Так как вы используете в процессе проектирования один тип монитора, а приложение в дальнейшем может работать на мониторе другого типа, то не исключено, например, что ваша форма не поместится на экране или наоборот — будет слишком маленького размера для данного монитора. Чтобы избежать этих неприятностей, можно автоматически масштабировать свою форму, вводя, например, в обработчик ее события OnCreate код: Form1.Width := Screen.Width div 2; Form1.Height := Screen.Height div 2;
Этот код задает размеры формы равными половине соответствующих размеров экрана.
Разрешающую способность экрана можно определить, воспользовавшись свойством PixelsPerInch, указывающим количество пикселей экрана на дюйм в вертикальном направлении. Это справедливо именно для вертикального направления, поскольку во многих мониторах коэффициенты масштабирования по горизонтали и вертикали различаются.
Screen имеет свойство Forms[I], содержащее список форм, отображаемых в данный момент на экране, и свойство FormCount, отражающее количество таких форм. Вы можете использовать это свойство, например, для того, чтобы гарантировать, что на данном типе монитора размеры ни одной формы не превысят размеров экрана. Соответствующий код может выглядеть так: with Screen do for I := 0 to FormCount - 1 do begin if Forms[I].Height > Height then Forms[I].Height := Height; if Forms[I].Width > Width then Forms[I].Width := Width; end;
Размеры форм, превышающие размер экрана, урезаются этим кодом.
В приведенных примерах надо, конечно, предусмотреть, чтобы при изменении размеров формы адекватно изменялось и расположение компонентов на ее поверхности.
Еще одно полезное свойство объекта Screen — Fonts (шрифты). Это свойство типа TStrings содержит список шрифтов, доступных на данном компьютере (свойство только для чтения). Его можно использовать в приложении, чтобы проверять, имеется ли на компьютере тот или иной шрифт, используемый в приложении. Если нет — то можно или дать пользователю соответствующее предупреждение, или сменить шрифт в приложении на один из доступных, или дать пользователю возможность самому выбрать соответствующий шрифт. Например, вы можете поместить в вашем приложении компонент списка TComboBox и при событии формы OnCreate загрузить его доступными шрифтами с помощью операторов: ComboBox1.Items := Screen.Fonts; ComboBox1.ItemIndex := 0;
Тогда в нужный момент пользователь может выбрать подходящий шрифт из списка. Пример использования свойства Screen.Fonts приведен в .
В Delphi 5 в тип TScreen введено два новых свойства: HintFont и MenuFont типа TFont. Они хранят установленные в Windows шрифты отображения ярлычков и разделов меню.
Свойство Cursor объекта Screen определяет вид курсора. Если это свойство равно crDefault, то вид курсора при перемещении над компонентами определяется установленными в них свойствами Cursor. Но если свойство Cursor объекта Screen отлично от crDefault, то соответствующие свойства компонентов отменяются и курсор имеет глобальный вид, заданный в Screen. Этим можно воспользоваться для такой частой задачи, как изменение курсора на форму «песочные часы» во время выполнения каких-то длинных операций. Это можно сделать следующим образом: Screen.Cursor := crHourGlass; try <выполнение требуемых длинных операций> finally Screen.Cursor := crDefault; end;
При успешном или аварийном окончании длинных операций курсор в любом случае возвращается в значение по умолчанию. Если в приложении в какие-то отрезки времени используется отличный от crDefault глобальный вид курсора, то приведенный код можно изменить, чтобы по окончании длинных операций восстановить прежнее глобальное значение: var OldCursor: TCursor; begin OldCursor := Screen.Cursor; Screen.Cursor := crHourGlass; try <выполнение требуемых долгих операций> finally Screen.Cursor := OldCursor; end;
С помощью Screen можно получить доступ к активной в текущий момент форме вашего приложения через свойство ActiveForm. Если в данный момент пользователь переключился с вашего приложения на какое-то другое и, следовательно, ни одна форма вашего приложения не активна, то ActiveForm указывает на форму, которая станет активной, когда пользователь вернется к вашему приложению. В момент переключения фокуса с одной вашей формы на другую, генерируется событие OnActiveFormChange.
Аналогично с помощью свойства ActiveControl можно получить доступ к активному в данный момент оконному компоненту на активной форме. При смене фокуса генерируется событие OnActiveControlChange.
Начиная с Delphi 4 предусмотрена возможность разработки мультиэкранных приложений, работающих одновременно с множеством мониторов. При этом приложение может решать, какие формы и диалоги надо отображать на том или ином мониторе. Свойства различных мониторов, используемых в таком приложении, можно найти с помощью свойства Screen.Monitors[I], где I — индекс монитора. Индекс 0 относится к первичному монитору. Свойство Screen.Monitors[I] является списком объектов типа TMonitor, содержащих информацию о конкретных мониторах.
Среди свойств объектов типа TMonitor имеются Height — высота и Width — ширина экрана монитора. Кроме того имеются свойства Left и Тор. Эти свойства означают следующее. Все доступное экранное пространство можно представить себе разбитым на экраны отдельных мониторов, размещающихся слева направо и сверху вниз. Соответственно свойства Left и Тор определяют координаты левого верхнего угла экрана монитора в этом логическом экранном пространстве. Объекты типа TMonitor имеют также свойство MonitorNum — номер монитора, представляющий собой его индекс в свойстве Screen.Monitors[I].
Для управления тем, на каком мониторе должна появляться та или иная форма, служит свойство формы DefaultMonitor. Это свойство может принимать значения:
dmDesktop | не предпринимается попыток разместить форму на конкретном мониторе |
dmPrimary | форма размещается на первом мониторе в списке Screen.Monitors |
dmMainForm | форма появляется на том мониторе, на котором размещена главная форма |
dmActiveForm | форма появляется на том мониторе, на котором размещена текущая активная форма |
Общая характеристика
Имеется несколько компонентов, которые сами по себе не выполняют никаких действий, но помогают организовать взаимодействие компонентов в приложении и обмен информацией между приложениями. Это компоненты, представленные в таблице 9.1. Компоненты ActionList и ImageList организуют управление внутри приложения и позволяют сделать его код более четким и понятным, отвечающим принципам объектно-ориентированного программирования.
Компоненты OLEContainer, DDEClientConv, DDEClientItem и TDDEServerItem организуют взаимодействие одновременно выполняемых приложений по двум различным технологиям: OLE и DDE. Вопросы взаимодействия приложений требуют развернутых пояснений, выходящих за рамки данной книги. Поэтому компоненты, связанные с технологиями OLE и DDE, рассматриваться далее не будут.
К компонентам, организующим управление приложением, можно также отнести объекты Application — приложение и Screen — экран. Эти объекты отсутствуют в палитре компонентов, но всегда создаются автоматически в каждом приложении. Некоторые характеристики этих объектов также будут рассмотрены в данной главе.
Пикто- грамма | Компонент | Страница | Описание |
ActionList (список событий) | Standard | Обеспечивает диспетчеризацию событий | |
ImageList (список изображений) | Win32 | Предназначен для работы со списками изображений одинакового размера в меню, инструментальных панелях и т.п. | |
АррlicationEvents (события приложения) | Additional | Перехватывает события приложения | |
OLEContainer (контейнер OLE) | System | Используется при создании области клиента для объекта OLE | |
DDEClientConv (диалог с сервером DDE) | System | Используется клиентом DDE для организации диалога с сервером DDE | |
DDEClientItem (данные, передаваемые серверу DDE) | System | Используется для определения данных клиента, передаваемых в диалоге серверу DDE | |
TDDEServerItem (данные, передаваемые клиенту DDE) | System | Используется для определения данных сервера, передаваемых клиенту DDE в течение диалога |
Окно редактора действий
Щелчок правой кнопкой мыши или щелчок на маленькой кнопочке со стрелкой вниз правее первой быстрой кнопки окна редактирования позволит вам выбрать одну из команд: New Action (новое действие) или New Standard Action... (новое стандартное действие). Первая из них относится к вводу нового действия любого типа. По умолчанию эти действия будут получать имена Action1, Action2 и т.д. Вторая команда открывает окно (Рисунок 9.2), в котором вы можете выбрать необходимое вам стандартное действие (или сразу несколько действий). После этого в правом окне (Actions) редактора появятся имена выбранных действий, а в левом (Categories) — категории действий.
Окно редактора списков изображений
В окне редактора списков изображений вы можете добавить в списки изображения, пользуясь кнопкой Add, удалить изображение из списка кнопкой Delete, очистить весь список кнопкой Clear. При добавлении изображения в список открывается обычное окно открытия файлов изображений, в котором вы можете выбрать интересующий вас файл. Только учтите, что размер всех изображений в списке должен быть одинаковым. Как правило, это размер, используемый для пиктограмм в меню, списках, кнопках. При добавлении в список изображений для кнопок надо иметь в виду, что они часто содержат не одно, а два и более изображений (см. ). В этих случаях при попытке добавить изображение задается вопрос: «Bitmap dimensions for... are greater then imagelist dimensions. Separate into ... separate bitmaps?» (Размерность изображения ... больше размерности списка. Разделить на ... отдельных битовых матрицы?). Если вы ответите отрицательно, то все изображения уменьшатся в горизонтальном размере и лягут как одно изображение. Использовать его в дальнейшем будет невозможно. Поэтому на заданный вопрос надо отвечать положительно. Тогда загружаемая битовая матрица автоматически разделится на отдельные изображения и потом вы можете удалить те из них, которые вам не нужны, кнопкой Delete.
Как видно из Рисунок 9.3, каждое загруженное в список изображение получает индекс. Именно на эти индексы впоследствии вы можете ссылаться в соответствующих свойствах разделов меню, списков, кнопок и т.д., когда вам надо загрузить в них то или иное изображение. Изменить последовательность изображений в списке вы можете просто перетащив изображение мышью на новое место.
В редакторе списков изображений вы можете, выделив то или иное изображение, установить его свойства: Transparent Color и Fill Color. Но это можно делать только в том сеансе работы с редактором списков изображений, в котором загружено данное изображение. Для изображений, загруженных в предыдущих сеансах, изменение этих свойств невозможно.
Свойство Transparent Color определяет цвет, который используется в маске для прозрачного рисования изображения. По умолчанию это цвет левого нижнего пикселя изображения. Для пиктограмм данное свойство устанавливается в clNone, поскольку пиктограммы уже маскированы.
Свойство Fill Color определяет цвет, используемый для заполнения пустого пространства при перемещении и центрировании изображения. Для пиктограмм данное свойство устанавливается в clNone.
Группа радиокнопок Options определяет способ размещения изображения битовой матрицы с размерами, не соответствующими размерам, принятым в списке:
Теперь рассмотрим основные свойства TImageList:
Остальные свойства определяют цвета и способы рисования изображения.
Окно выбора стандартных действий
Каждое действие, которое вы внесли в список — это объект типа TAction для нестандартных действий или других производных типов для стандартных. Выбрав в окнах редактора ту или иную категорию или [AllActions] (все категории), а в правом — конкретное действие, вы можете увидеть в Инспекторе Объектов его свойства и события. Вы можете установить свойство Name (имя) — оно появится в правом окне редактора свойств и будет в дальнейшем фигурировать в заголовках обработчиков событий. Можете также установить надпись (Caption), которая далее будет появляться в инициаторах действия — кнопках, разделах меню и т.д. Можете задать быстрые клавиши (Shortcut), надписи на ярлычках подсказок и в строке состояний (Hint), идентификатор темы контекстной справки (HelpContext) и другие обычные для многих компонентов свойства.
Можно для каждого или некоторых действий указать свойство ImageIndex, которое является индексом (начиная с 0) изображения, соответствующего данному действию, в отдельном компоненте списка изображений ImageList (см. ). Этот индекс передастся в дальнейшем компонентам, связанным с данным событием — разделам меню, кнопкам. Если в свойстве Images компонента ActionList указать имя списка, размещенного на форме и заполненного изображениями, то эти изображения появятся также в окне редактора действий (Рисунок 9.1).
Свойство Category (категория) не имеет отношения к выполнению приложения. Задание категории просто позволяет в процессе проектирования сгруппировать действия по их назначению. Вы можете для каждого действия выбрать категорию из выпадающего списка, или написать имя новой категории и отнести к ней какие-то действия. Например, на Рисунок 9.1 видна введенная пользователем категория Файлы, к которой отнесены действия, связанные с меню Файл.
На странице событий Инспектора Объектов для каждого действия определено три события: OnExecute, OnUpdate и OnHint.
Событие OnExecute возникает в момент, когда пользователь инициализировал действие, например, щелкнув на компоненте (разделе меню, кнопке), связанном с данным действием. Обработчик этого события должен содержать процедуру, реализующую данное действие. Например, обработчик события OnExecute действия Exit может в простейшем случае иметь вид procedure TForm1.ExitExecute(Sender: TObject); begin Close; end; а в более сложных случаях может содержать проверку возможности закрыть приложение, запросы пользователю и т.д. Одним из преимуществ использования действий является то, что заголовки обработчиков приобретают осмысленный характер и код становится более прозрачным. Действительно, гораздо понятнее заголовок ExitExecute, чем, например, Button7Click или N14Click (попробуйте найти в вашем большом приложении, где эта кнопка Button7 или раздел меню N14). В результате вы избавляетесь от необходимости давать осмысленные имена кнопкам и разделам меню, т.е. облегчаете свою работу с компонентами.
Событие OnUpdate периодически возникает в промежутках между действиями. Возникновение этих событий прекращается только во время реализации события или во время, когда пользователь ничего не делает и компьютер находится в состоянии ожидания действий. Обработчик события OnUpdate может содержать какие-то настройки, подготовку ожидаемых дальнейших действий или выполнение каких-то фоновых операций.
Событие OnHint возникает в момент, когда на экране отображается ярлычок подсказки в результате того, что пользователь задержал курсор мыши над компонентом, инициализирующим событие.
Наличие в объекте действия событий OnUpdate и OnHint обогащает ваши возможности по проектированию приложения. Без этого объекта подобные события отсутствуют и их при необходимости приходится моделировать более сложными приемами.
Связь объектов действий с конкретными инициализаторами действий — управляющими элементами типа кнопок, разделов меню и т.д., осуществляется через свойство Action, имеющееся у всех управляющих элементов. Поместите на вашу форму кнопку, и вы увидите в Инспекторе Объектов это свойство. Раскройте его выпадающий список и выберите из него действие, которое вами было предварительно описано. Вы сможете заметить, что после этого в кнопку перенесутся такие свойства объекта действия, как Caption, Hint и др., и что в ее событие OnClick подставится обработчик, предусмотренный вами для данного действия. Если далее вы введете в приложение меню с разделом, соответствующим тому же действию, и укажете в нем то же значение свойства Action, то свойства и обработчики событий объекта действия будут перенесены и на этот раздел меню. Вам не придется повторно задавать значение Hint, Caption и др.
Подобная связь между свойствами объекта действия и свойствами управляющих элементов выполняется классом TActionLink и его наследниками. Передаются в компоненты такие свойства действия, как Caption, Checked, Enabled, HelpContext, Hint, ImageIndex, Shortcut, Visible. Впрочем, в любом компоненте разработчик может изменить переданное в него свойство. Обратной связи TActionLink с компонентами нет, так что эти изменения будут локальными и не отразятся на других компонентах. Если же требуется изменить свойства всех связанных с одним действием компонентов, надо изменять свойство объекта действия. Это облегчает программное управление компонентами, связанными с одним и тем же действием. Например, если в какой-то момент вам надо сделать недоступными (или, наоборот, доступными) два компонента — кнопку Button3 и раздел меню N5, связанные с одним событием (назовем его объект Do), то при отсутствии централизованной диспетчеризации событий через ActionList вам пришлось бы писать два оператора: Button3.Enabled := false; N5.Enabled := false; а при наличии объекта Do — всего один: Do.Enabled := false;
Дело не только в экономии кода, но и в его прозрачности, понятности его как для вас самих, так и для тех, кому придется, может быть, в дальнейшем сопровождать ваше приложение.
Приложение — компонент ApplicationEvents и объект Application
В каждом приложении автоматически создается объект Application типа TApplication — приложение. Этот компонент отсутствует в палитре библиотеки, вероятно, только потому, что он всегда один в приложении. Application имеет ряд свойств, методов, событий, характеризующих приложение в целом.
Рассмотрим сначала некоторые свойства Application. Булево свойство Active (только для чтения) характеризует активность приложения. Оно равно true, если форма приложения находится в фокусе. Если же пользователь переключился на работу с другим приложением, свойство Active равно false.
Свойство ExeName является строкой, содержащей имя выполняемого файла с полным путем к нему. Это свойство удобно использовать, чтобы определять каталог, из которого запущено приложение и который может содержать другие файлы (настройки, документы, базы данных и т.п.), связанные с приложением. Выражение ExtractFilePath(Application.ExeName) дает этот каталог. Обычно свойство ExeName тождественно функции ParamStr(0), возвращающей нулевой параметр командной строки — имя файла с путем.
Свойство Title определяет строку, которая появляется около пиктограммы свернутого приложения. Если это свойство не изменяется во время выполнения, то оно равно опции Title, задаваемой во время проектирования на странице Application окна опций проекта (команда Project | Options). Свойство может изменяться программно, например, изменяя надпись в зависимости от режима работы приложения.
Свойство MainForm типа TForm определяет главную форму приложения. Булево свойство ShowMainForm определяет, должна ли главная форма быть видимой в момент запуска приложения на выполнение. По умолчанию оно равно true, что обеспечивает видимость главной формы в момент начала работы приложения. Если же установить в головном файле проекта Application.ShowMainForm равным false до вызова метода Application.Run и если при этом свойство Visible главной формы тоже равно false, то главная форма в первый момент будет невидимой.
Свойство HelpFile указывает файл справки, который используется в приложении в данный момент как файл по умолчанию. Если это свойство не изменяется во время выполнения, то оно равно опции Help File, задаваемой во время проектирования на странице Application окна опций проекта (команда Project | Options). Свойство можно изменять программно, назначая в зависимости от режима работы приложения тот или иной файл справки.
Ряд свойств объекта Application определяет ярлычки подсказок компонентов приложения. Свойство Hint содержит текст подсказки Hint того визуального компонента или раздела меню, над которым в данный момент перемещается курсор мыши. Смена этого свойства происходит в момент события OnHint, которое будет рассмотрено позднее. Во время этого события текст подсказки переносится из свойства Hint компонента, на который переместился курсор мыши, в свойство Hint объекта Application. Свойство Application.Hint можно использовать для отображения этой подсказки или для установки и отображения в полосе состояния текста, характеризующего текущий режим приложения.
Свойство HintColor типа TColor определяет цвет фона окна ярлычка. По умолчанию это цвет clInfoBk, но его значение можно изменять программно. Свойство HintPause определяет задержку появления ярлычка в миллисекундах после переноса курсора мыши на очередной компонент (по умолчанию 500 миллисекунд или половина секунды). Свойство HintHidePause аналогичным образом определяет интервал времени, после которого ярлычок становится невидимым (по умолчанию 2500 миллисекунд или две с половиной секунды). Свойство HintShortPause определяет аналогичным образом задержку перед появлением нового ярлычка, если в данный момент отображается другой ярлычок (по умолчанию 50 миллисекунд). Это свойство позволяет предотвратить неприятное мерцание, если пользователь быстро перемещает курсор мыши над разными компонентами.
Теперь остановимся на некоторых методах объекта Application. Методы Initialize — инициализация проекта, и Run — запуск выполнения приложения, включаются в каждый проект автоматически — вы можете это увидеть в головном файле проекта, если выполните команду Project | View Source. Там же вы можете увидеть применение метода создания форм CreateForm для всех автоматически создаваемых форм проекта. Если же в вашим проекте есть форма, которая исключена из списка автоматически создаваемых (команда Project | Options и соответствующая установка на странице Forms), то когда эта форма вам потребуется, вы должны будете вызвать этот метод: procedure CreateForm(FormClass: TFormClass; var Reference); где FormClass — класс создаваемой формы, Reference — ссылка на создаваемый объект (его имя). Например: Application.CreateForm(TForm2, Form2);
Метод Terminate завершает выполнение приложения. Если вам надо завершить приложение из главной формы, то вместо метода Application.Terminate вы можете использовать метод Close главной формы. Но если вам надо закрыть приложение из какой-то вторичной формы, например, из диалога, то надо применять метод Application.Terminate.
Метод Minimize сворачивает приложение, помещая его пиктограмму в полосу задач Windows.
Ряд методов связан с работой со справочными файлами. Выше уже говорилось о свойстве HelpFile, указывающем текущий файл справки. Метод HelpContext: function HelpContext(Context: THelpContext): Boolean; вызывает переход в файл справки на тему с идентификатором Context. Это идентификатор, который при проектировании справки поставлен в соответствие некоторой теме. Метод HelpJump: function HelpJump(const JumpID: string): Boolean; выполняет аналогичные действия, но его параметр JumpID — не идентификатор темы, а имя соответствующей темы в файле справки, задаваемое в нем сноской #.
Метод HelpCommand: function HelpCommand(Command: Word; Data: Longint): Boolean; позволяет выполнить указанную параметром Command команду API WinHelp с параметром Data. Метод генерирует событие OnHelp активной формы или приложения, а затем выполняет указанную команду WinHelp. Полный список команд WinHelp вы можете найти в теме WinHelp справочного файла win32.hlp, расположенного в каталоге ...\Program Files\Common Files\Borland Shared\MSHelp. Приведем только некоторые из них. Команда HELP_CONTENTS с параметром 0 отображает окно Содержание справки. Команда HELP_INDEX с параметром 0 отображает окно Указатель справки. Команда HELP_CONTEXT с параметром, равным идентификатору темы, отображает тему с заданным идентификатором (это тождественно рассмотренному ранее методу HelpContext). Команда HELP_CONTEXTPOPUP с параметром, равным идентификатору темы, делает то же самое, но отображает тему во всплывающем окне.
В классе TApplication имеется еще немало методов, но часть из них используется в явном виде очень редко (вы можете посмотреть их во встроенной справке Delphi), а часть будет рассмотрена ниже при обсуждении событий объекта Application. Хотелось бы только обратить внимание читателя на очень полезный метод MessageBox, позволяющий вызывать диалоговое окно с указанным текстом, указанным заголовком и русскими надписями на кнопках (в русифицированных версиях Windows). Это наиболее удачный полностью русифицируемый стандартный диалог, но его рассмотрение, к сожалению, выходит за рамки данной книги. См. о нем в следующих книгах серии «Все о Delphi».
В классе TApplication определено множество событий, которые очень полезны для организации приложения. Ранее для использования этих событий было необходимо вводить соответствующие обработчики и указывать на них объекту Application специальными операторами. В Delphi 5 введен компонент ApplicationEvents, существенно облегчивший эту задачу. Этот компонент перехватывает события объекта Application и, следовательно, обработчики этих событий теперь можно писать как обработчики событий невизуального компонента ApplicationEvents. На каждой форме приложения можно разместить свой компонент ApplicationEvents. События объекта Application будут передаваться всем этим компонентам. Если вы хотите, чтобы событие передавалось прежде всего какому-то одному из них, примените к нему метод Activate, который поставит его в начало очереди компонентов ApplicationEvents. Если же вы при этом не хотите, чтобы другие компоненты ApplicationEvents получали события, примените к привилегированному компоненту метод CancelDispatch. Тогда после обработки события в данном компоненте другие компоненты ApplicationEvents вообще не будут реагировать на эти события.
Во многие обработчики событий компонента ApplicationEvents передается по ссылке параметр Handled. По умолчанию его значение равно false. Если вы обработали соответствующее событие и не хотите, чтобы оно далее обрабатывалось другими компонентами ApplicationEvents, надо в обработчике установить Handled = true. Если же вы оставите Handled = false, то событие будут пытаться обрабатывать другие компоненты ApplicationEvents (если они есть). Если событие так и останется необработанным, то его будет пытаться обработать активный компонент, а если не обработает — то активная форма. Предотвратить обработку события другими компонентами можно, используя описанный ранее метод CancelDispatch.
Ниже приведена таблица событий компонента ApplicationEvents с их краткими описаниями.
Свойство | Описание |
OnActionExecute | Возникает при выполнении (Execute) некоторого действия, объявленного в компоненте ActionList, но не обработанного им (не написан соответствующий обработчик). Инициализация этого события может быть, например, выполнена методом Application.ExecuteAction(<имя действия>). Если событие не обработано в ActionList, то оно может быть обработано на уровне приложения. В обработчик OnActionExecute передается параметр Action — действие и по ссылке передается параметр Handled (см. выше). |
OnActionUpdate | Возникает при обновлении (Update) некоторого действия, объявленного в компоненте ActionList, но не обработанного им (не написан соответствующий обработчик). Если событие не обработано в ActionList, то оно может быть обработано на уровне приложения. В обработчик OnActionUpdate передается параметр Action — действие и по ссылке передается параметр Handled (см. выше). |
OnActivate | Возникает, когда приложение становится активным. Это происходит при начале выполнения и в случаях, когда пользователь, перейдя к другим приложениям, вернулся в данное. Если это событие обработано в ApplicationEvents, то предотвратить дальнейшую его обработку можно методом CancelDispatch. |
OnDeactivate | Возникает перед тем моментом, когда приложение перестает быть активным (пользователь переключается на другое приложение). Если событие обработано в ApplicationEvents, то предотвратить дальнейшую его обработку можно методом CancelDispatch. |
OnException | Возникает, когда в приложении сгенерировано исключение, которое нигде не перехвачено. В обработчик передается параметр Sender — источник исключения, и параметр Е типа Exception — объект исключения. Параметр Е помогает определить тип исключения. Например, if(E is EDivByZero) then ... .B обработчике события OnException вы можете предусмотреть нестандартную обработку исключений на уровне приложения, например, русифицировать стандартные сообщения об исключениях и дать пользователю какие-то рекомендации. Учтите, что введение вами обработчика OnException отключит стандартную реакцию приложения на исключительные ситуации. |
OnHelp | Возникает при запросе приложением справки. Это событие возникает, в частности, при выполнении рассмотренных ранее методов приложения HelpContext, HelpJump и HelpCommand. Обработчик может использоваться для каких-то подготовительных операций, например, для задания файла справки (параметр Application.HelpFile). В обработчик передаются параметры — Command команда API WinHelp (см. выше описание HelpCommand), Data — параметр этой команды и по ссылке передается булев параметр CallHelp. Если его установить в true, то после завершения обработчика будет вызван WinHelp, в противном случае вызова WinHelp не будет. |
OnHint | Возникает в момент, когда курсор мыши начинает перемещаться над компонентом или разделом меню, в котором определено свойство Hint. При этом свойство Hint компонента переносится в свойство Hint приложения (Application.Hint) и в обработчике данного события может отображаться, например, в строке состояния. |
OnIdle | Возникает, когда приложение начинает простаивать, ожидая, например, действий пользователя. В обработчик передается по ссылке булев параметр Done, который по умолчанию равен true. Если оставить его без изменения, то по окончании работы обработчика данного события будет вызвана функция WaitMessage API Windows, которая займется в период ожидания другими приложениями. Если задать Done = false, то эта функция вызываться не будет. Это может снизить производительность Windows. |
OnMessage | Возникает, когда приложение получает сообщение Windows (но не переданное функцией SendMessage API Windows). В обработчике события OnMessage можно предусмотреть нестандартную (отличную от определенной в TApplication) обработку сообщения. В обработчик передается параметр Msg — полученное сообщение и по ссылке передается параметр Handled (см. выше). Учтите, что в Windows передаются тысячи сообщений в секунду, так что обработчик OnMessage может серьезно снизить производительность приложения. |
OnMinimize | Возникает при сворачивании приложения. |
OnRestore | Возникает при восстановлении ранее свернутого приложения. |
OnShortCut | Возникает при нажатии пользователем клавиши. Событие возникает до того, как возникло стандартное событие OnKeyDown компонента или формы. Обработчик позволяет предусмотреть нестандартную реакцию на нажатие какой-то клавиши. В него передается параметр сообщения Windows Msg, поле CharCode которого (Msg.CharCode) содержит виртуальный код нажатой клавиши. Передается также по ссылке параметр Handled. Если задать ему значение true, то стандартные события OnKeyDown, OnKeyPress, OnKeyUp не наступят. |
OnShowHint | Возникает, когда приложение собирается отобразить ярлычок с текстом подсказки Hint. В обработчик передается по ссылке параметр HintStr — первая часть свойства Hint компонента, ярлычок которого должен отображаться. В обработчике этот текст можно изменить. Так же по ссылке передается параметр CanShow. Если в обработчике установить его равным false, то ярлычок отображаться не будет. Третий параметр, передаваемый по ссылке — HintInfo. Это структура, поля которой (см. встроенную справку Delphi) содержат информацию о ярлычке: его координаты, цвет, задержки появления и т.п. В частности, имеется поле HintControl — компонент, сообщение которого должно отображаться в ярлычке, и поле HintStr — отображаемое сообщение. По умолчанию HintInfo.HintStr — первая часть свойства Hint компонента. Но в обработчике это значение можно изменить. |
Приведем примеры использования событий компонента ApplicationEvents.
Обработчик события OnHint: procedure TForm1.ApplicationEvents1Hint( Sender: TObject); begin StatusBar1.SimpleText := Application.Hint; end; отображает в полосе состояния StatusBar1 (см. ) вторую часть свойства Hint любого компонента, в котором определено это свойство и над которым перемещается курсор мыши. Отображение происходит независимо от значения свойства ShowHint компонента.
Обработчик события OnShowHint: procedure TForm1.ApplicationEvents1ShowHint( var HintStr: String; var CanShow: Boolean; var HintInfo: THintInfo); begin if (HintInfo.HintControl.ClassName = 'TEdit') then begin HintStr := (HintInfo.HintControl as TEdit).Text; ApplicationEvents1.CancelDispatch; end; end; подменяет для окон редактирования типа TEdit текст ярлычков на текст, содержащийся в этих окнах редактирования. Такой прием позволяет пользователю, подведя курсор мыши к окну редактирования, увидеть во всплывающем окне полный текст, который может не быть виден обычным образом, если он длинный и не помещается целиком в окне редактирования. Обработчик события OnHelp: function TForm1.ApplicationEvents1Help(Command: Word; Data: Integer; var CallHelp: Boolean): Boolean; begin if (Command = HELP_CONTEXT) and (Datathen begin Application.HelpCommand(HELP_CONTEXTPOPUP, Data); CallHelp := false; end; Result := true; end; обеспечивает отображение всех контекстных справок с номерами идентификаторов тем, меньшими 10, во всплывающем окне, не вызывая при этом WinHelp. Это дает возможность отобразить многострочные (в отличие от ярлычков) всплывающие окна, поясняющие назначение тех или иных элементов приложения. Обработчик события OnShortCut: procedure TForm1.ApplicationEvents1ShortCut( var Msg: TWMKey; var Handled: Boolean); begin if Msg.CharCode = Ord('Q') then if Application.MessageBox( 'Действительно хотите завершить работу?', 'Подтвердите завершение', MB_YESNOCANCEL + MB_ICONQUESTION) = IDYES then Application.Terminate; end; перехватывает нажатие пользователем клавиш и, если нажата клавиша с символом «Q» (в любом регистре и независимо от установки русского или английского языка), то пользователю методом Application.MessageBox предлагается диалоговое окно, изображенное на Рисунок 9.4.
Список изображений — компонент ImageList
Компонент ImageList представляет собой набор изображений одинаковых размеров, на которые можно ссылаться по индексам, начинающимся с 0. Во многих рассмотренных ранее компонентах (меню, списках и др.) встречались свойства, представляющие собой ссылки на компонент ImageList. Этот компонент позволяет организовать эффективное и экономное управление множеством пиктограмм и битовых матриц. Он может включать в себя монохромные битовые матрицы, содержащие маски для отображения прозрачности рисуемых изображений.
Изображения в компонент TImageList могут быть загружены в процессе проектирования с помощью редактора списков изображений. Окно редактора, представленное на Рисунок 9.3, вызывается двойным щелчком на компоненте TImageList или щелчком правой кнопки мыши и выбором команды контекстного меню ImageList Editor.