Dialogs в Delphi


Содержание

OpenDialog — диалоговое окно выбора имени файла

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

Компонент OpenDialog реализует диалог открытия файла. При запуске этого диалога появляется окно (см. скриншот), в котором можно выбрать имя открываемого файла. В случае успешного закрытия диалогового окна (нажатием кнопки Open) в качестве результата возвращается выбранное имя файла.

Основные свойства компонентов OpenDialog и SaveDialog

Далее перечислены основные свойства компонентов OpenDialog и SaveDialog.

FileName типа String — указывает имя и полный путь файла, выбранного в диалоге. Имя файла отображается в строке редактирования списка Имя файла и является результатом диалога.

Title типа String— задает заголовок окна. Если свойство Title не установлено, то по умолчанию используется заголовок Open для OpenDialog и заголовок Save — для SaveDialog.

InitiaLDir типа String— определяет каталог, содержимое которого отображается при вызове диалогового окна. Если каталог не задан, то отображается содержимое текущего каталога.

DefaultExt типа String — задает расширение, автоматически используемое в имени файла, если пользователь не указал расширение.

Filter типа String— задает маски имен файлов, отображаемых в раскрывающемся списке Тип файлов. В диалоговом окне видны имена файлов, совпадающие с указанной маской (см. скриншот) это файл с расширением jpeg). По умолчанию значением Filter является пустая строка, что соответствует отображению имен файлов всех типов.

FilterIndex типа Integer — указывает, какая из масок фильтра отображается в списке. По умолчанию свойство FilterIndex имеет значение 1 (используется первая маска).

Options

Options типа TOpenOptions — применяется для настройки параметров, управляющих внешним видом и функциональными возможностями диалога. Каждый параметр (флажок) может быть установлен или снят. Свойство Options имеет около двух десятков параметров, наиболее важные перечислены ниже:

Основные параметры свойства Options

  • ofAllowMultiSelect (из списка можно выбрать одновременно более одного файла);
  • ofCreatePrompt (при вводе несуществующего имени файла выдается запрос на создание файла);
  • ofNoLongNames (имена файлов отображаются как короткие, не более 8 символов для имени и 3 символов для расширения);
  • ofOldStyleDialog (создает диалоговое окно в стиле Windows 3.11).

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

Здесь фильтр формируется с двумя масками — маской для текстовых файлов и маской для всех файлов (под текстовыми понимаются файлы типов doc и txt).

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

Фильтр обычно формируется при проектировании приложения. Для этого из окна Инспектора объектов щелчком в области значения свойства Filter вызывается Редактор фильтра (Filter Editor).

Рабочее поле окна Редактора фильтра представляет собой таблицу, состоящую из двух столбцов с заголовками Filter Name и Filter. Значения фильтра вводятся построчно, при этом в левом столбце указывается описание фильтра, а в правом — соответствующая маска (скриншот уже был выше).

Стандартные диалоговые окна выбора имени файла для открытия или сохранения файла вызываются на экран методом Execute. Эта функция в качестве результата возвращает логическое значение, позволяющее определить, как закрыт диалог. Если пользователь в процессе диалога нажал кнопку Open или Save, то диалог считается принятым, и функция Execute возвращает значение True. Если диалог был закрыт любым другим способом, то он считается не принятым, и функция возвращает значение False.

При нажатии кнопки Button2 появляется диалоговое окно OpenDialog1 выбора имени файла для открытия. При выборе имени текстового файла его содержимое загружается в компонент Memo1. Напомним, что многострочный редактор Memo позволяет работать с текстами в коде ANSI. При отмене диалога OpenDialog1 открытие файла не происходит.

Компоненты OpenPictureDialog и SavePictureDialog вызывают стандартные диалоги открытия и сохранения графических файлов. Эти стандартные диалоги отличаются от OpenDialog и SaveDialog видом окон (см. скриншот) и установленными значениями свойства Filter.

Так, по умолчанию свойство Filter установлено для отображения графических файлов следующих форматов:

При использовании диалогов OpenPictureDialog и SavePictureDialog, а также OpenDialog и SaveDialog значение свойства Filter можно установить ранее рассмотренными способами, а также с помощью функции GraphicFilter (GraphicClass: TGraphicCiass) : String.

Параметр GraphicClass принадлежит к одному из графических классов: TBitmap, TGraphic (и его потомки), TIcon, TMetafile или TJPEGimage. Для работы с классом TJPEGimage нужно подключить модуль jpeg. В качестве результата функция GraphicFilter () возвращает строку с фильтрами для указанного графического класса:

TBitmap — Bitmaps (*.bmp) |*.bmp;

TIcon—Icons (* . ico) I * . ico;

TMetafile — All (*.emf;*.wmf) |*.emf;*.wmf|Enhanced Metafiles(*.emf)| *.emf|Metafiles(*.wmf) |*.wmf;

TJPEGimage — All (*.jpeg;*.jpg) | *.jpeg;*.jpg| JPEG Image File (*.jpeg) |*.jpeg| JPEG Image File (*.jpg)| *.jpg;

TGraphic — All (*.jpeg;*.jpg;*.bmp;*.ico;*.emf;*.wmf) | *.jpeg;*.jpg; *.bmp;*.ico;*.emf; *.wmf|JPEG Image File (*.jpeg) | *.jpeg| JPEG Image File (*.jpg) |*.jpgI Bitmaps (*.bmp) | *.bmp| Icons(*.ico) |*.ico | Enhanced Metafiles(*.emf)|*.emf|Metafiles(*.wmf)I*.wmf.

Если модуль jpeg в разделе uses не указан, то фильтры, соответствующие формату JPEG, будут отсутствовать.

Например, фильтр, заданный как OpenDialog1.Filter := GraphicFilter(TGraphic); позволяет отображать имена графических файлов допустимых форматов.

Канал в Telegram

Вы здесь

Главное меню, диалоги открытия и сохранения файлов в Delphi. Блокнот v1.1. Часть 1

На прошлом уроке мы создали простейшую форму чтения из текстового файла test.txt, его редактирование и последующее сохранение в него же. Это, конечно же, очень далеко напоминает блокнот, идущий в комплекте с ОС Windows. В нашем блокноте открытие происходит только одного файла и сохранение в него же. Открытие производится при нажатии на кнопки, которые расположены на самой форме и никак не вписываются в удобство интерфейса. Первым делом давайте представим нашу программу пользователю в более удобном виде, добавим главное меню, которое является неотъемлемой частью всех прикладных приложений.

В Delphi уже разработан визуальный компонент «MainMenu», позволяющий быстро и легко реализовать стандартное главное меню. Этот компонент находится на вкладке «System» палитры компонентов:

При использовании этого компонента, в нашу форму встраивается поле под заголовком формы. Давайте немного изменим вид нашего блокнота (возьмем за основу MyNotepad v1). Уберем кнопки «Открыть» и «Закрыть», при этом очистите их код, достаточно удалить команду, расположенную в процедуре кнопок, между begin end, например, для кнопки «Открыть» удалить только «txt.Lines.LoadFromFile(ExtractFilePath(application.ExeName)+(‘\test.txt’));», после чего, при сохранении или запуске проекта, эти процедуры автоматически будут удалены. Немного расширим текстовое поле, например, так:

Для того что бы форма автоматически приняла размеры по краям расположенных на ней компонентов, можно включить свойство формы «AutoSize»:

Все. Немного видоизменили.

Теперь добавляем на форму компонент MainMenu, расположенный на вкладке «System» в палитре компонентов. Для добавления, достаточно его выбрать на палитре компонентов и щелкнуть один раз ЛКМ по форме. Для того чтобы создать пункты главного меню, кликните два раза ЛКМ по изображению компонента, находящегося на форме:

У вас откроется редактор пунктов меню:

Щелкаем ЛКМ по синей области, и вводим свойство «Caption» — «Файл»

Будет создан главный пункт меню «Файл». Кликните еще раз по созданному пункту «Файл», после чего у Вас появится вложенное пустое поле. В него введите «Открыть…» и задайте для этого пункта имя «fOpen» в свойстве Name

Для удобства работы с приложениями используются горячие клавиши. При задании горячих клавиш своим приложениям необходимо по максимум использовать общие для всех приложений сочетания, принятые в системе Windows. Например, Ctrl+O – открыть файл, Ctrl+S – сохранить и т.д.

Зададим нашему пункту сочетание Ctrl+O, по нажатию которого, будет происходить вызов диалога открытия файла. Для этого достаточно в свойстве «ShortCut» выбрать это сочетание из списка:

Добавим еще два пункта «Сохранить» и «Сохранить как…», при этом для «Сохранить» будем использовать горячую клавишу Ctrl+S, а для «Сохранить как» не будет горячих клавиш (Но Вы, при желании, можете установить). Имена пунктов «fSave» и «fSaveAs».

И еще добавим пункт «Выход» без горячих клавиш, который будет закрывать наше приложение.

Для удобного восприятия и группировки меню, необходимо его разделить на части. Чтоб это сделать, достаточно в новом пункте меню, в свойство Caption, записать «-», после чего будет создана разделительная черта. Итоговый вид меню будет выглядеть так:

Обратите внимание, на нашей форме появилось главное меню:

Диалоги OpenDialog и SaveDialog

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

Такие диалоговые окна уже реализованы в среде Delphi. Располагаются они на вкладке «Dialogs»

Для нашего приложения потребуются OpenDialog и SaveDialog, выберите их и добавьте на форму, аналогично компоненту MainMenu.

Задайте имена этим диалогам fOpenDialog, fSaveDialog

Если кликнуть два раза по иконке компонента, то откроется форма диалога:

Как Вы видите, диалоговое окно не имеет фильтров по типам файлов. Для того чтоб создать список поддерживаемых типов, необходимо выделить тип диалога и перейти в пункт «Filter»

Нажав на «» откроется окно редактирования фильтров:

Наш блокнот открывает файлы формата txt, а так же можно осуществлять попытки открытия файлов, которые предположительно содержат текст, например «html».

Создадим два фильтра следующим образом:

Теперь при двойном клике по диалогу открытия мы видим, что файлы отображаются согласно выбранного фильтра:

Если нужно чтоб по умолчанию стоял определенный фильтр, необходимо в свойстве «FilterIndex» указать номер фильтра в списке:

Аналогично создайте фильтр для диалога сохранения. Только в случае сохранения нам нужен один тип файла «Текстовый файл (*.txt)». Также, при сохранении неплохо бы включить сообщение, которое будет отображаться в случае перезаписи файла:

Для этого разверните список «Options» диалога fSaveDialog и измените параметр ofOverwritePrompt с false на true:

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

Нужен диалог выбора папки, а не файла

17.04.2020, 21:09

Диалог выбора папки
Подскажите пожалуйста, в Delphi 2007, для Windows 7 — есть ли диалог выбора не файла, а целой.

Показать диалог выбора папки
как в delphi 7 вызвать диалог выбора папки? в палитре инструментов во вкладке dialogs его нет.

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

Диалог выбора папки
Привет. Как мы знаем есть диалог открытия(open dialog), а можете дать мне типо такого же диалого.

Диалог для выбора директории или путя к ней.
Есть ли какой-нить диалог позволяющий выбирать директорию и соответственно возвращающий путь до неё.

17.04.2020, 21:15 2 18.04.2020, 00:27 [ТС] 3

Какой-то слабенький диалог, далеко конечно ему до OpenDialog. Не выводит иконки файлов, просто список.
А типа OpenDialog компонентов под делфи нету? (у меня Д2007)
Но все равно спасибо, это уже «ближе к телу».

Добавлено через 1 час 53 минуты
А такой вопрос, с помощью набора опций (или еще какими-нибудь действиями) к диалогу OpenDialog, можно-ли заставить его не зацикливаться в случае когда в окне «Имя файла» пусто, и мы жмем на кнопку «открыть» ?
Ну нравится мне этот диалог, хочу его себе применить. В принципе он у меня работает, но только приходится либо любой файл выбирать мышью, либо в окно «Имя файла», любую билеберду вписать.

Урок 21. Диалог для открытия файла

Диалог для открытия файла. Для добавления в программу стандартного диалога для открытия файла добавьте на форму компонент OpenDialog с вкладки Палитры компонентов.

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

Для того чтобы при нажатии на кнопку диалоговое окно появилось, добавьте в ее обработчик, следующий код:

procedure TForm1.Button1Click(Sender: TObject);

Разумеется, для работы с файлом не достаточно только вызвать наше диалоговое окно. Необходимо еще извлечь из него имя выбранного файла. Вот как это делается (в приведенном примере содержимое выбранного пользователем текстового файла показывается в компоненте Memo1 типа TMemo , который надо разместить на форме).

if OpenDialog1.Execute then

Таким образом для извлечения файла мы используем свойство FileName нашего диалога. Обратите внимание, что с помощью if мы проверяем, выбрал ли пользователь вообще что-нибудь. Если пользователь ничего не выбрал, то OpenDialog1.Execute возвращает false , и последующий код не выполняется. Вот еще несколько полезных свойств для нашего диалога для открытия файлов.

Для открытия в диалоге заранее определенной папки используем свойство InitialDir :

procedure TForm1.Button1Click(Sender: TObject);
begin
OpenDialog1.InitialDir:=’D:\’;
if OpenDialog1.Execute then
Memo1.Lines.LoadFromFile(OpenDialog1.FileName);
end;

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

Затем просто заполните левый и правый столбцы. Левый определяет, что за надпись увидит пользователь, а правый — что за файлы будут показываться.

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

Свойство FilterIndex диалогового окна определяет номер активного фильтра (т. е. того, который будет выбран при вызове диалога). Нумерация при этом начинается с единицы.

А вот так можно задать несколько фильтров в тексте программы:

Функции сообщений в Delphi

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

1. Функция MessageBox (Windows API)

Функция – отображает диалоговое окно с сообщением.

Синтаксис функции (Windows API):

function MessageBox (Wnd: HWND; lpText, lpCaption : PChar; uType : Cardinal) : integer;

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

Параметр hWnd – маркер (дескриптор) окна владельца, идентифицирует окно владельца окна сообщений. Если этот параметр НУЛЕВОЙ (ПУСТОЙ), окно сообщений не имеет никакого владельца.

Параметр ipText – указатель на строку, содержащую сообщение, с нулевым символом в конце. Текст сообщения может быть длинным, более чем 255 символов в случае необходимости.


Параметр ipCaption — заголовок, который появляется в области заголовка диалогового окна. Заголовки могут быть более длинными, чем 255 символов, из-за чего создается широкое окно сообщений.

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

Группа флажков, определяющая, какие кнопки появятся на окне сообщений

№ п.п. Описание
1 Окно сообщений содержит три кнопки: Abort, Retry, and Ignore.
2 Окно сообщений содержит одну кнопку: OK. Это значение по умолчанию.
3 Окно сообщений содержит две кнопки: OK и Cancel.
4 Окно сообщений содержит две кнопки: Retry and Cancel.
5 Окно сообщений содержит две кнопки: Yes и No.
6 Окно сообщений содержит три кнопки: Yes, No, и Cancel.

Функция MessageBox возвращает 0, если нет достаточного количества памяти, чтобы создать окно сообщений. Иначе она возвращает одно из следующих значений:

Возвращаемое значение функции Возвращаемое числовое значение функции Описание
1 IDOK 1 Пользователь выбрал кнопку OK.
2 IDCANCEL 2 Пользователь выбрал кнопку Cancel.
3 IDABORT 3 Пользователь выбрал кнопку Abort.
4 IDRETRY 4 Пользователь выбрал кнопку Retry.
5 IDIGNORE 5 Пользователь выбрал кнопку Ignore.
6 IDYES 6 Пользователь выбрал кнопку Yes.
7 IDNO 7 Пользователь выбрал кнопку No.

Группа флажков, определяющая, какие иконки отобразятся в окне сообщений

Значения параметра Описание
1 MB_ICONEXCLAMATIONMB_ICONWARNING В окне сообщений появляется значок восклицательного знака
2 MB_ICONINFORMATIONMB_ICONASTERISK В окне сообщений появляется значок, состоящий из символа I нижнего регистра в круге.
3 MB_ICONQUESTION В окне сообщений появляется вопросительный знак в круге.
4 MB_ICONSTOPMB_ICONERRORMB_ICONHAND В окне сообщений появляется знак Stop

Группа флажков, указывающая на основную кнопку

Значения параметра 1 Первая кнопка — основная кнопка.
MB_DEFBUTTON2 3 Третья кнопка — основная кнопка.
MB_DEFBUTTON4
Значения параметра Описание
MB_APPLMODAL
MB_SYSTEMMODAL
MB_TASKMODAL

Кроме того, можно определить следующие флажки:

Значения параметра Описание
3 MB_RIGHT
5 MB_SETFOREGROUND
7 MB_SERVICE_NOTIFICATION

Пример (фрагмент программы по созданию диалогового окна сообщений):

2. Функция MessageBoxEx (Windows API)

Функция – отображает диалоговое окно с сообщением.

Синтаксис функции (Windows API):

function MessageBox (Wnd: HWND; lpText, lpCaption : PChar; uType : Cardinal; wLanguageId: Word) : integer;

Функция используется, чтобы отобразить универсальное диалоговое окно сообщений с одной или более кнопками. Аналогична функции MessageBox, только добавлен еще один параметр wLanguageId, представляющий идентификатор языка, на котором будут отображаться надписи на кнопках, например:

$0409 English (United States);

$0407 German (Standard);

3. Функция MessageBox (класса TApplication, модуля Forms)

Синтаксис функции:

function MessageBox(const Text, Caption: PChar; Flags: Longint = MB_OK): Integer;

В данной функции отсутствует первый параметр – маркер (дескриптор) окна владельца, в остальном используется аналогично приведенной выше.

Результат выполнения программного кода

4. Функция MessageDlg (модуля Dialogs)

function MessageDlg(const Msg: string; DlgType: TMsgDlgType; Buttons: TMsgDlgButtons; HelpCtx: Longint): Word;

Описание

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

Параметр Msg – текст сообщения.

Параметр DlgType – определяет тип окна сообщений. Предлагаются следующие их типы:

Значение Описание
3 mtInformation
5 mtCustom

Параметр Buttons определяет следующие типы кнопок:

TMsgDlgBtn = (mbYes, mbNo, mbOK, mbCancel, mbAbort, mbRetry, mbIgnore, mbAll, mbNoToAll, mbYesToAll, mbHelp);

TMsgDlgButtons = set of TMsgDlgBtn;

Возвращаемое значение
mrOK
mrCancel
mrYes
mrNo
mrAbort
mrRetry
mrIgnore
mrAll
mrNoToAll
mrYesToAll
mrClose

Наборы кнопок также определены, как константы:

mbYesNoCancel = [mbYes, mbNo, mbCancel];

mbYesAllNoAllCancel = [mbYes, mbYesToAll, mbNo, mbNoToAll, mbCancel];

mbOKCancel = [mbOK, mbCancel];

mbAbortRetryIgnore = [mbAbort, mbRetry, mbIgnore];

mbAbortIgnore = [mbAbort, mbIgnore];

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

2. Если указывается набор кнопок, как константа, то писать нужно без скобок. Например, mbYesNoCancel.

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

Фрагмент программы по использованию функции MessageDlg

5. Функция MessageDlgPos (модуля Dialogs)

function MessageDlgPos(const Msg: string; DlgType: TMsgDlgType; Buttons: TMsgDlgButtons; HelpCtx: Longint; X, Y: Integer): Word;

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

6. Функция MessageDlgPosHelp (модуля Dialogs)

function MessageDlgPosHelp(const Msg: string; DlgType: TMsgDlgType; Buttons: TMsgDlgButtons; HelpCtx: Longint; X, Y: Integer; const HelpFileName: string): Word;

Отображает диалоговое окно сообщения, справка которого предоставлена в именованном файле справки (HelpFileName) с номером раздела HelpCtx. Выводится на экран с координатами X,Y левого верхнего угла окна относительно левого верхнего угла экрана.

Delphi. Компоненты страницы dialogs

Правила использования диалоговых панелей

Работа со стандартными диалоговыми окнами осуществляется в три этапа:

1. На форму помещается соответствующий компонент и осуществляется настройка его свойств. Следует обратить внимание на то, что компонент-диалог не виден в момент работы программы, видно лишь создаваемое им стандартное окно.

2. Осуществляется вызов стандартного для диалогов метода Execute, который создает и показывает настроенное окно на экране. Вызов этого метода обычно располагается внутри обработчика какого-либо события. После обращения к Execute на экране появляется соответствующее диалоговое окно. Окно диалога является модальным окном, поэтому сразу после обращения к нему дальнейшее выполнение программы приостанавливается до тех пор, пока пользователь не закроет окно.

3. Использование введенных из диалогового окна данных (имя файла, настройки принтера и т. д.) для продолжения работы программы.

TOpenDialog и TSaveDialog

Эти компоненты имеют идентичные свойства и различаются только внешним видом. Свойство FileName: (тип String) содержит маршрут поиска и имя выбранного файла при успешном завершении диалога программы. Для проверки наличия файла на диске глобальная функция FileExists Свойство Filter: String используется для фильтрации (отбора) файлов, показываемых в диалоговом окне. Это свойство можно устанавливать с помощью специального редактора или программно. Для доступа к редактору достаточно щелкнуть по кнопке в строке Filter окна инспектора объектов. При программном вводе фильтры задаются одной длинной строкой, в которой символы «|» служат для отделения фильтров друг от друга, а также для отделения описания фильтруемых файлов от соответствующей маски выбора. С помощью свойства DefaultExt: String[3] формируется полное имя файла, если при ручном вводе пользователь не указал расширение. В этом случае к имени файла прибавляется разделительная точка и содержимое этого свойства.

Настройка диалога может варьироваться с помощью свойства

TOpenOption = (of Readonly, ofOverwritePrompt, ofHideReadOnly,

ofNoChangeDir, ofShowHelp, ofNoValidate, ofAllowMuItiSelect,

ofExtensionDifferent, ofPathMustExist, ofFileMustExist, ofCreatePrompt, ofShareAware, ofNoReadOnlyReturn, ofNoTestFileCreate, ofNoNetworkButton, ofNoLongNames, ofOldStyleDialog, ofNoDereferenceLinks);

TOpenOptions = set of TOpenOption;

Property Options: TOpenOptions;

Значения этого свойства имеют следующий смысл:

Устанавливает переключатель “Только для чтения”

Требует согласия пользователя при записи в существующий файл

Прячет переключатель “Только для чтения”

Запрещает смену каталога.

Включает в окно кнопку Help

Запрещает автоматическую проверку правильности набираемых в имени файла символов

Разрешает множественный выбор файлов

При завершении диалога наличие этого значения в свойстве Options говорит о том, что пользователь ввел расширение, отличающееся от умалчиваемого

Разрешает указывать файлы только из существующих каталогов

Разрешает указывать только существующие файлы.

Требует подтверждения для создания несуществующего файла

Разрешает выбирать файлы, используемые другими параллельно выполняемыми программами

Запрещает выбор файлов, имеющих атрибут “Только для чтения“

Запрещает проверку доступности сетевого или локального диска

Запрещает вставку кнопки для создания сетевого диска

Запрещает использование длинных имен файлов

Создает диалог в стиле Windows З. х

TOpenPictureDialog и TSavePictureDialog

Специализированные диалоги для открытия и сохранения графических файлов являются расширенными вариантами компонентов TOpenDialog и TsaveDialog, в которых предусмотрены наличие стандартного фильтра для выбора графических файлов и панель предварительного просмотра.

Компонент используется для вызова стандартной диалоговой панели выбора шрифтов и их характеристик. Свойство Device определяет тип устройства, для которого выбирается fdScreen — экран; fdPrinter — принтер; fdBoth — шрифты, поддерживаемые и экраном, и принтером. Диапазон возможных значений размеров шрифтов определяется свойствами MinFontSize и MaxFontSize. Значения этих свойств задаются в пунктах (1 пункт равен приблизительно

0,36 мм). Если свойства содержат 0, ограничения на размер шрифта отсутствуют. Свойство Options используется для настройки диалога. Значения этого свойства имеют следующий смысл:

Показывает только шрифты с набором символов Windows

Показывает только TrueType-шрифты

Включает в окно переключатели “Подчеркнутый” и “Зачеркнутый”, а также список выбора цвета шрифта

Включает только моноширинные шрифты

Предупреждает о выборе несуществующего шрифта


Запрещает выделение имени шрифта в момент открытия окна

Запрещает выбор MS-DOS-шрифтов

Исключает шрифты, которые синтезируются графическим интерфейсом Windows

Запрещает выделение размера шрифта в момент открытия окна

Запрещает выделение стиля шрифта в момент открытия окна

Исключает векторные шрифты

Включает в диалоговое окно кнопку Help

Включает шрифты, которые поддерживаются и экраном, и принтером

Включает ограничения на размер шрифта, заданные свойствами MaxFontSize и MinFontSize

Включает только масштабируемые шрифты (векторные и TrueType)

Включает в окно кнопку “Применить“

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

Компонент служит для создания стандартного диалогового окна для выбора параметров печати.

Property Collate: Boolean;

Если имеет значение True, то окно показывается с выбранным переключателем “Разобрать” (Collate). Если этот переключатель выбран, печать нескольких копий документа будет идти по копиям: сначала первая копия, затем вторая и т. д., в противном случае – по страницам: сначала все копии первой страницы, затем второй и т. д.

Property Copies: Integer;

Определяет количество копий (0 — одна копия)

Property FromPage: Integer;

Определяет начальную страницу печати

Property MaxPage: Integer;

Определяет верхнюю границу диапазона страниц для свойств FromPage, ToPage

Property MinPage: Integer;

Определяет нижнюю границу диапазона страниц для свойств FromPage, ToPage

Property Options: TPrintDialogOptions;

Определяет настройку окна: ро PrintToFile — печатать в файл; poPageNums — разрешает выбор диапазона страниц; poSelection — разрешает печать выбранного текста; poWarning — предупреждать пользователя о неустановленном принтере; poHelp – вставить в окно кнопку Help; poDisablePrintToFile – запрещает печать в файл

Property PrintRange: TPrintRange;

Определяет диапазон печатаемых страниц: prAll Pages — все страницы; prSelection — выделенный фрагмент текста; prPageNums — страницы по номерам

Property PrintToFile: Boolean;

Содержит True, если пользователь выбрал печать в файл

Property ToPage: Integer;

Определяет конечную страницу печати

Компонент создает окно настройки параметров принтера, вид которого зависит от типа принтера. Этот диалог взаимодействует с драйвером принтера и не возвращает в программу никакой информации, поэтому его метод Execute — процедура, а не функция.

Стандартное диалоговое окно компонента TFindDialog используется для поиска фрагмента текста.

Property FindText: string;

Указывает образец для поиска

Property Left: Integer;

Содержит горизонтальную позицию левого верхнего угла места появления окна

Property Options: TfindOptions;

Определяет настройку диалога

Property Position: TPoint;

Содержит горизонтальную и вертикальную позицию левого верхнего угла места появления окна

Property Top: Integer;

Содержит вертикальную позицию левого верхнего угла места появления окна

Для компонента определен следующий тип, использующийся в свойстве Options: TfindOptions. Его значения имеют такой смысл:

Устанавливает поиск вперед по тексту

Сообщает программе, что пользователь нажал кнопку “Найти далее”

Убирает выбор в переключателе “С учетом регистра”

Убирает выбор в переключателе “Только слово целиком”

Прячет кнопки выбора направления поиска

Устанавливает выбор в переключателе “С учетом регистра»

Запрещает выбор “С учетом регистра“

Запрещает выбор направления поиска

Запрещает выбор Только слово целиком

Используется в компоненте TReplaceDialog и указывает на необходимость замены текущего выбора

Используется в компоненте Treplace Dialog и указывает на необходимость замены всех вхождений образца поиска

Устанавливает выбор в переключателе “Только слово целиком”

Включает в окно кнопку Help

Компонент создает и обслуживает окно поиска и замены текстового фрагмента. Класс TReplaceDialog наследует большинство свойств классаTFind-Dialog. Дополнительно в компоненте определено свойство ReplaceText (тип String), в котором содержится текст замены, и событие OnReplace, которое возникает при нажатии кнопки “Заменить” или “Заменить все”.

Работа с диалогами InputQuery, InputBox в Delphi 10.1 Berlin

Не прекращаю попыток в свободное от основной работы время разрабатывать небольшое приложение в Delphi для Andro >

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

Deprecated Members New Members
  • FMX.Dialogs.ShowMessage
  • FMX.Dialogs.ShowMessageFmt
  • FMX.Dialogs.ShowMessagePos
  • ShowMessageAsync
  • ShowMessageSync
  • FMX.Dialogs.MessageDlg
  • FMX.Dialogs.MessageDlgPos
  • FMX.Dialogs.MessageDlgPosHelp
  • FMX.Platform.IFMXDialogService.MessageDialog
  • MessageDialogAsync
  • MessageDialogSync
  • FMX.Dialogs.InputBox
  • FMX.Dialogs.InputQuery
  • FMX.Platform.IFMXDialogService.InputQuery
  • InputQueryAsync
  • InputQuerySync

При этом методы ShowMessage и ShowMessageFmt, несмотря на их наличие в разделе deprecated members, не являются таковыми, однако нам рекомендуется использовать вместо них аналогичный синхронный или асинхронный вариант. Хорошо, посмотрим, как использовать нововведение.

Модуль FMX.DialogService

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

Программирование на языке Delphi

Глава 9. Окна диалога


Авторы: А.Н. Вальвачев
К.А. Сурков
Д.А. Сурков
Ю.М. Четырько

Опубликовано: 12.06.2006
Исправлено: 10.12.2020
Версия текста: 1.0

Все мы любим иногда поболтать. Это человеческое свойство передалось программам, и они частенько у вас что-то спрашивают, а вы им что-то отвечаете, иногда невпопад. “Беседа”, правда, идет текстом, а не голосом. Так вот, разговор между программой и пользователем называется диалогом. Организация диалога — важнейшая часть любой программы. Ваша прямая обязанность сделать этот диалог приятным. По форме диалог прост — появляется окно с некоторым сообщением, полем для ввода вашего ответа и кнопкой OK. Вы внимательно читаете сообщение, набираете строку-ответ и нажимаете кнопку OK. Вот и все. Создатели среды Delphi предусмотрели все возможные типы диалогов и создали для вас ряд великолепных “домашних заготовок”.

9.1. Понятие окна диалога

В основе диалога между пользователем и компьютером лежит окно диалога (dialog box) — форма, содержащая компоненты для ввода данных: кнопки, текстовые поля, флажки, переключатели, списки и др. С помощью этих компонентов пользователь просматривает и вводит данные. В среде Delphi окно диалога создается на основе обычной формы.

Окна диалога могут работать в одном из двух режимов, монопольном (иногда говорят модальном, от англ. modal) и немонопольном (немодальном, от англ. modeless).

Монопольное окно диалога не дает пользователю возможности переключиться на другие окна программы до тех пор, пока работа с ним не будет завершена. Сразу заметим, что это не мешает пользователю переключаться на другие программы, например, с помощью панели задач Windows или нажатием комбинации клавиш Alt+Tab. Большинство окон диалога работает в монопольном режиме.

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

9.2. Окно «About»


9.2.1. Подготовка формы

Простейшим примером окна диалога является окно About («О программе»). Как правило, оно открывается по команде меню Help | About. , работает в монопольном режиме и служит лишь для информирования пользователя. В предыдущей главе мы рассматривали программу PicView, там как раз не достает окна About. Исправим это упущение и на практике познакомимся с созданием простейших окон диалога.

Шаг 1. Запустите среду Delphi и откройте проект PictureViewer. Добавьте в главное меню пункт Help (программный идентификатор HelpMenuItem ) с командой About. (программный идентификатор AboutMenuItem ). По команде About. (рисунок 9.1) будет вызываться окно диалога About, которое мы дальше разработаем.

Рисунок 9.1. Пункт меню для вызова окна About

Шаг 2. Добавьте в проект новую форму, переименуйте ее в AboutForm и сохраните модуль под именем About.pas. Придайте форме нужные размеры и установите ее заголовок (свойство Caption ) в значение About Picture Viewer . Далее сделаем из этой формы окно диалога.

Шаг 3. Обычная форма имеет много «фитюлек», которые совсем не нужны окну диалога, например раздвижную границу, меню управления окном, кнопки сворачивания и разворачивания окна. Чтобы их убрать, установите свойство BorderStyle в значение bsDialog (рисунок 9.2).

Рисунок 9.2. Превращение формы в окно диалога

Результат сделанного изменения проявится только во время работы программы и будет выражаться в следующем:

  • у пользователя не будет возможности изменить размеры формы;
  • у формы не будет кнопок сворачивания и разворачивания;
  • в управляющем меню будут лишь два пункта: Move и Close.

Шаг 4. Большинство монопольных окон диалога появляются в центре экрана. За это у формы отвечает свойство Position . Изначально оно равно poDesigned — форма появляется точно в том же месте, где она находится во время разработки. Чтобы центрировать форму на экране, установите свойство Position в значение poScreenCenter . Заметим, что другие значения свойства Position позволяют центрировать форму относительно главной формы, относительно формы-владельца или вообще не центрировать (см. параграф 7.3.4).

С формой разобрались, займемся компонентами. Окно About обычно содержит красивый рисунок, название программного продукта, замечания по поводу авторских прав или что-нибудь в этом роде и, конечно же, кнопку OK. Начнем с того, что добавим в форму кнопку.

9.2.2. Кнопка

Разрабатывая окно диалога, прежде всего необходимо обеспечить для пользователя возможность завершения диалога по окончание ввода данных. Вот тут как раз и нужны кнопки (buttons) . В простейшем окне диалога, каким является окно About, достаточно всего одной кнопки (она обычно называется OK или Close). В более сложных окнах может понадобиться несколько кнопок. Например, в том случае, когда окно диалога принимает от пользователя данные, в него помещают кнопки OK и Cancel, которые позволяют пользователю подтвердить или отменить результат диалога.

Обычная кнопка создается с помощью компонента Button , расположенного в палитре компонентов на вкладке Standard .

Рисунок 9.3. Компонент Button

Характерные свойства этого компонента кратко описаны в таблице 9.1.

Свойство Описание
Action Команда, хранящаяся в компоненте ActionList и выполняемая при нажатии кнопки.
Cancel Если равно значению True, то кнопка срабатывает при нажатии клавиши Esc.
Caption Текст на кнопке.
Default Если равно значению True, то кнопка срабатывает при нажатии клавиши Enter. Исключением является ситуация, когда в окне диалога активна другая кнопка — в этом случае срабатывает она.
ModalResult При нажатии кнопки значение этого свойства копируется в одноименное свойство формы, что приводит к закрытию монопольного окна диалога. Однако для этого значение свойства должно отличаться от mrNone.
WordWrap Если равно значению True, то работает перенос слов.
Таблица 9.1. Важнейшие свойства компонента Button

Текст на кнопке определяется значением свойства Caption . В тексте может присутствовать символ & , который не пишется на кнопке, а обеспечивает подчеркивание следующего за ним символа. Нажатие подчеркнутого символа на клавиатуре в комбинации с клавишей Alt вызывает срабатывание кнопки. Например, если свойство Caption содержит строку &Yes , то на кнопке будет написано Yes , и для нажатия кнопки можно воспользоваться комбинацией клавиш Alt + Y .

Пользователи, привыкшие работать с клавиатурой, знают, что одна из кнопок в окне диалога срабатывает при нажатии клавиши Enter. Это происходит при условии, что кнопка содержит значение True в свойстве Default . Такая кнопка, как правило, содержит текст OK и внешне отличается от остальных наличием жирной рамки.

Одна из кнопок окна диалога может срабатывать при нажатии клавиши Esc. Это происходит, если кнопка содержит значение True в свойстве Cancel. Как правило, такая кнопка подписывается текстом «Отмена» (Cancel).

Когда пользователь нажимает кнопку, в компоненте Button происходит событие OnClick . В обработчике этого события вы можете завершить диалог. Завершение немонопольного диалога выполняется вызовом метода Close у объекта формы. Завершение монопольного окна диалога выполняется установкой ненулевого значения в свойстве ModalResult формы. Впрочем, без этого можно обойтись, если воспользоваться свойством ModalResult компонента Button (мы не ошиблись, это свойство имеет и форма, и кнопка). Свойство ModalResult компонента Button устанавливается в окне свойств и по умолчанию равно значению mrNone . Если вы выберите другое значение, то нажатие кнопки будет вызывать автоматическое завершение диалога с копированием этого значения в свойство ModalResult формы. Анализируя свойство ModalResult после завершения диалога, программа узнает, какую кнопку нажал пользователь и в соответствии с этим направляет работу программы в нужное русло.

Помните, что свойство ModalResult работает только в монопольных окнах диалога.

Шаг 5. Перейдем теперь от теории к практике и создадим в нашем окне About кнопку OK (рисунок 9.4). Для этого выберите в палитре компонентов компонент Button , опустите его в форму и установите его свойства следующим образом:


  • Cancel = True
  • Caption = OK
  • Default = True
  • ModalResult = mrOk

Рисунок 9.4. Кнопка OK в окне About

9.2.3. Кнопка с рисунком

Каждый из нас в душе художник. Поэтому рано или поздно стандартные невзрачные кнопки, содержащие лишь “голый” текст, перестанут вам нравиться. Появится естественное желание их как-то приукрасить. В этом случае мы советуем вам вместо компонента Button воспользоваться компонентом BitBtn . Он расположен в палитре компонентов на вкладке Additional .

Рисунок 9.5. Компонент BitBtn

Компонент BitBtn обладает теми же возможностями, что и компонент Button , но кроме текста может содержать значок, который придает кнопке более привлекательный вид. По сравнению с компонентом Button компонент BitBtn имеет некоторые новые свойства, которые отражены в таблице 9.2.

Свойство Описание
Glyph Значок на кнопке.
NumGlyphs Количество вариантов значка. Компонент делит рисунок Glyph по горизонтали на заданное количество значков и рисует один из них в зависимости от состояния кнопки.
Layout Положение значка относительно текста: blGlyphLeft — слева, blGlyphRight — справа, blGlyphTop — сверху, blGlyphBottom — снизу.
Margin Расстояние от границы кнопки до значка. Если оно равно -1, то значок вместе с текстом центрируются на кнопке.
Spacing Расстояние от значка до текста. Если оно равно -1, то текст центрируется между значком и границей кнопки.
Kind Задает кнопку стандартного вида. Упрощает создание таких стандартных кнопок, как OK, Cancel, Yes, No, Close, Abort, Retry, Ignore, All, Help.
Таблица 9.2. Характерные свойства компонента BitBtn

Заметим, что кнопка, содержащая значок, принимает наиболее красивый вид, если свойство Margin равно значению 4, а свойство Spacing равно значению 1.

С помощью компонента BitBtn стандартные кнопки OK, Cancel, Yes, No, Close, Abort, Retry, Ignore, All и Help создаются проще, чем при использовании компонента Button . Для этого в свойстве Kind достаточно выбрать одно из значений, приведенных в таблице 9.3.

Значение Вид кнопки Результат установки значения Пояснения
bkOK Caption = ‘OK’
Default = True
ModalResult = mrOK
Кнопка, подтверждающая ввод данных.
bkCancel Caption = ‘Cancel’
Cancel = True
ModalResult = mrCancel
Кнопка, отменяющая ввод данных.
bkYes Caption = ‘&Yes’
Default = True
ModalResult = mrYes
Кнопка для положительного ответа на вопрос.
bkNo Caption = ‘&No’
Cancel = True
ModalResult = mrNo
Кнопка для отрицательного ответа на вопрос.
bkAll Caption = ‘&All’
ModalResult = mrAll
Кнопка для положительного ответа на все вопросы.
bkAbort Caption = ‘Abort’
ModalResult = mrAbort
Кнопка для прерывания операции.
bkRetry Caption = ‘&Retry’
ModalResult = mrRetry
Кнопка для повторения операции.
bkIgnore Caption = ‘&Ignore’
ModalResult = mrIgnore
Кнопка для игнорирования произошедших изменений и продолжения начатой операции.
bkHelp Caption = ‘&Help’ Кнопка для вызова справочника. Вы можете вызывать справочник в обработчике события OnClick или возложить эту работу на среду Delphi, установив у формы свойство HelpContext в нужное значение.
bkClose Caption = ‘&Close’ Кнопка, закрывающая форму.
bkCustom Любой Любой Кнопка для ваших собственных целей.
Таблица 9.3. Значения свойства Kind компонента BitBtn

Например, если вам нужна кнопка OK, установите свойство Kind в значение bkOK. В результате на кнопке появится зеленая «галочка» и текст «OK», свойство Default получит значение True и свойство ModalResult получит значение mrOK.

9.2.4. Украшение окна диалога рисунком

Хорошее приложение должно быть не только функционально, но и эстетично. Как говорится, хорошее блюдо должно быть красиво подано. Это относится и к нашему замечательному приложению, и конечно к его окну About. А что может лучше украсить окно About, чем яркий, запоминающийся рисунок.

Шаг 6. Как вы уже знаете, рисунок создается с помощью компонента Image , расположенного в палитре компонентов на вкладке Additinal . Выберите этот компонент и поместите его в форму AboutForm .

Шаг 7. Установите свойство AutoSize в значение True, чтобы компонент автоматически подгонял свои размеры под размеры рисунка, и установите свойство Transparent в значение True, чтобы рисунок отображался с прозрачным фоном.

Рисунок 9.6. Прозрачный фон для рисунка задается установкой свойства Transparent в значение True

Шаг 8. Чтобы установить рисунок, перейдите к свойству Picture и нажатием кнопки с многоточием откройте окно Picture Editor . Это окно должно быть вам уже знакомо. Загрузите файл Athena.bmp из папки «C:\Program Files\Common Files\Borland Shared\Images\Splash\16Color». Рисунок появится в форме (рисунок 9.7).

Рисунок 9.7. В компоненте Image загружен рисунок

9.2.5. Текстовая надпись

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

Следуя традиции, напишем название программы большими жирными буквами, а название средства разработки — обычным мелким шрифтом. Для этого воспользуемся компонентом Label , который находится в палитре компонентов на вкладке Standard .

Рисунок 9.8. Компонент Label

Характерные свойства компонента Label кратко описаны в таблице 9.4.

Свойство Описание
Align Способ выравнивания в пределах содержащего компонента.
Alignment Выравнивание текста в пределах компонента: taLeftJustify — прижат к левой границе, taRightJustify — прижат к правой границе, taCenter — центрирован.
AutoSize Если равно значению True, то размеры компонента автоматически подгоняются по ширине и высоте текста.
Caption Текст надписи. С помощью символа & в тексте может быть задана “горячая” клавиша.
FocusControl Компонент формы, получающий фокус ввода при нажатии “горячей” клавиши.
ShowAccelChar Если равно значению True, то записанный в тексте символ & транслируется в подчеркивание следующего за ним символа. Подчеркнутый символ используется в комбинации с Alt как “горячая” клавиша.
Transparent Если равно значению True, то фон надписи является прозрачным. Прозрачный фон полезен при наложении надписи на рисунок.
WordWrap Если равно значению True, то работает перенос слов.
Таблица 9.4. Важнейшие свойства компонента Label

Компонент Label отображает нередактируемый текст, хранящийся в свойстве Caption . Текст выравнивается в пределах компонента одним из трех способов: по левому краю, по правому краю или по центру. Способ выравнивания определяется свойством Alignment . Если текст надписи слишком велик, можно организовать его вывод в несколько строк (с переносом слов). Для этого достаточно установить свойство WordWrap в значение True. Еще одна удобная возможность — автоматическая подгонка размеров компонента по ширине и высоте текста. Она контролируется свойством AutoSize и по умолчанию включена.

Фон надписи можно сделать прозрачным, установив свойство Transparent в значение True. Такую надпись можно вынести наверх графического изображения, в результате получится текст на фоне рисунка.

С помощью компонента Label часто создаются подсказки к другим компонентам, в частности к полям ввода. При этом свойство Caption содержит не только текст, но и “горячую” клавишу, при выборе которой активизируется связанный с надписью компонент. Активизируемый компонент указывается в свойстве FocusControl .

Шаг 9. Вспомним, что компонент Label понадобился нам для того, чтобы сделать необходимые надписи в окне About. Опустите в форму первую надпись справа от изображения и установите ее свойства следующим образом:

  • WordWrap = True
  • Caption = Picture Viewer
  • Font Color = clNavy
  • Font Name = Times New Roman
  • Font Size = 20
  • Font Style = [fsBold]

Рисунок 9.9. Надпись выполнена с помощью компонента Label

Шаг 10. После этого поместите в форму еще один компонент Label с текстом «Developed in Delphi» в свойстве Caption .

9.2.6. Рельефная канавка

Окно диалога почти готово, но для полного ажура не хватает одной мелочи — рельефной канавки вокруг рисунка и надписей (это придаст окну законченность). Для решения подобных задач служит компонент Bevel , расположенный в палитре компонентов на вкладке Additional.

Рисунок 9.10. Компонент Bevel

Шаг 11. Поместите в форму компонент Bevel , придайте ему нужные размеры и положение, после чего установите свойство Shape в значение bsFrame.

Рисунок 9.11. Компонент Bevel в форме

9.2.7. Рельефная панель

Рельефные канавки удобно создавать с помощью компонента Bevel . Однако компонент Bevel не может быть контейнером для других компонентов, а следовательно, перемещение рамки не вызывает перемещение компонентов, находящихся внутри нее. Если нужна не просто рамка, а контейнер с рамкой, то пользуются рельефной панелью — компонентом Panel (вкладка Standard панели инструментов).

Рисунок 9.12. Компонент Panel

Отличительные свойства компонента Panel сведены в таблицу 9.5.

Свойство Описание
Align Способ выравнивания панели в пределах владельца.
BevelInner Внутренний скос рельефной рамки: bvNone — скос отсутствует, bvLowered — скос внутрь, bvRaised — скос наружу; bvSpace — скос заменяется отступом.
BevelOuter Внешний скос рельефной рамки: bvNone — скос отсутствует, bvLowered — скос внутрь, bvRaised — скос наружу; bvSpace — скос заменяется отступом.
BevelWidth Ширина скосов рельефной рамки.
BorderWidth Расстояние в пикселях между внутренним и внешним скосами.
BorderStyle Определяет, имеет ли панель рамку.
Caption Текст на панели.
DockSite Определяет, используется ли панель для стыковки других компонентов.
FullRepaint Свойство сохранено для совместимости с предыдущими версиями библиотеки VCL. Оно не влияет на способ перерисовки компонента.
Locked Если равно False, то OLE-серверу разрешено заменить панель на свою панель инструментов. Если равно True и панель выравнена по какой-нибудь стороне формы, то она остается нетронутой при активизации OLE-сервера по месту.
UseDockManager Включает режим автоматического размещения стыкуемых компонентов на панели. Компоненты стыкуются методом деления панели по горизонтали и вертикали. Если свойство равно значению False, то программист должен сам позаботиться о размерах и местоположении стыкуемых компонентов, определив обработчики событий OnGetSiteInfo и OnDockDrop .
OnCanResize Происходит при попытке изменить размеры панели. Запрос на изменение размеров может исходить от пользователя. Устанавливая значение параметра Resize , обработчик события OnCanResize может разрешить или запретить действительное изменение размеров панели.
OnConstrainedResize Происходит при изменении размеров панели и позволяет на лету изменять ее минимальные и максимальные размеры.
OnGetSiteInfo Происходит, когда у компонента запрашивается место для стыковки.
Таблица 9.5. Важнейшие свойства компонента Panel

Шаг 12. Уберите компонент Bevel из формы и поместите на его место компонент Panel . Откорректируйте его положение и размеры и установите свойства следующим образом (рисунок 9.13):

Рисунок 9.13. Компонент Panel заменил в форме компонент Bevel

Шаг 13. С помощью окна Object TreeView перенесите компоненты Image1 , Label1 и Label2 на панель Panel1 (рисунок 9.14).

Рисунок 9.14. Компоненты Image1, Label1 и Label2 переносятся на панель Panel1

Теперь рельефная рамка заменена рельефной панелью и при ее перемещении перемещаются все надписи и рисунок (рисунок 9.15).

Рисунок 9.15. Компоненты Image1, Label1 и Label2 — теперь на панели Panel1

Будьте аккуратны при удалении панели! Вместе с ней всегда удаляются внутренние компоненты.

9.2.8. Выполнение диалога

Визуальное проектирование окна About закончено, осталось обеспечить его вызов при выборе пользователем команды Help | About. главного меню. Для этого нужно сделать следующее:

  • создать команду AboutAction в компоненте ActionList и связать ее с пунктом меню About. ;
  • в модуле MainUnit подключить модуль AboutUnit. Это обеспечит доступ к форме AboutForm из главной формы PictureForm ;
  • создать обработчик события OnExecute команды AboutAction и обеспечить в нем монопольное выполнение диалога.

Шаг 14. Как реализовать первый пункт плана вы уже знаете, поэтому мы не будем на нем останавливаться, и сразу перейдем ко второму пункту плана. Активизируйте PictureForm , а затем выберите в меню File команду Use Unit. . На экране появится окно (рисунок 9.16):

Рисунок 9.16. С помощью окна Use Unit модуль About подключается в модуле Main

Выберите в этом окне модуль AboutUnit и щелкните на кнопке OK. Модуль AboutUnit, содержащий определение формы AboutForm , подключится в модуле MainUnit, содержащем определение главной формы PictureForm . Чтобы в этом убедиться, перейдите к редактору кода. В разделе implementation модуля MainUnit вы обнаружите строку

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

Шаг 15. Выполните теперь второй пункт плана — создайте обработчик события OnExecute для команды AboutAction компонента ActionList:

Метод ShowModal запускает окно диалога в монопольном режиме и возвращает управление только после его завершения. В нашем примере метод вызывается как процедура, но в действительности это функция, которая возвращает код завершения диалога. Код берется у формы из свойства ModalResult . Напомним, что для выполнения диалога в немонопольном режиме его нужно вызвать с помощью метода Show , а не метода ShowModal .

Шаг 16. Выполните компиляцию и запустите программу, затем проверьте работу новоиспеченного окна диалога, выполнив команду меню Help | About. (рисунок 9.17).

Рисунок 9.17. Диалоговое окно в работе

Все работает правильно, остается только выяснить один вопрос: где, когда и кем конструируется объект AboutForm . Ведь никаких усилий мы для этого не предпринимали, и тем не менее использовали объект при вызове метода ShowModal как уже существующий.

Объект AboutForm создается при запуске программы и существует на протяжении всей ее работы. В этом можно убедиться, заглянув в главный файл программы с помощью команды меню View | Project Source . В главном программном блоке вы найдете оператор:

Он-то и обеспечивает «автоматическое» создание объекта формы. Это удобно, но имеет и отрицательные стороны, так как память, выделенная объекту остается занятой даже тогда, когда форма невидима, т.е. до запуска диалога и после его завершения. Если программа имеет одну-две формы, это не так важно, а если много? В этом случае от автоматического создания всех форм, кроме главной, лучше отказаться.

Шаг 17. Чтобы исключить автоматическое создание формы AboutForm , откройте окно Project Options и на вкладке Forms отбуксируйте элемент AboutForm из списка Auto-create forms в список Available forms (рисунок 9.18):

Рисунок 9.18. Форма AboutForm исключена из списка автоматически создаваемых форм

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

Шаг 18. Разумеется, что после сделанных действий метод AboutItemClick , из которого вызывается окно диалога, нужно переписать:

Ну вот, теперь ресурс оперативной памяти используется более рационально. Кстати, обратите внимание, как обеспечивается защита объекта AboutForm от исключительных ситуаций, которые могут возникнуть в период его работы (это конечно маловероятно, но чего в этой жизни не бывает!). Если объект AboutForm успешно создается, то благодаря оператору try. finally. end он всегда корректно освобождается, даже в случае возникновения исключительной ситуации.

9.3. Компоненты для ввода данных

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

Использование компонентов для ввода данных рассмотрим на примере приложения Alarms. Эта полезная программа позволит создать список будильников для уведомления о предстоящих событиях. По сигналу будильника в заданные время и день появится окно с сообщением и прозвучит сигнал. Список будильников будет отображаться в главном окне программы, а установка их параметров будет выполняться в модальном окне диалога. В процессе разработки этого приложения вы познакомитесь с такими компонентами, как CheckBox , RadioButton , ComboBox , ListBox , GroupBox , Edit , MaskEdit и некоторыми другими. Итак, приступим.

Шаг 1. Сначала приготовьте новый проект с пустой формой, выбрав команду меню File | New Application . Дайте форме идентификатор MainForm , скорректируйте ее размеры и установите следующие значения свойств:

  • Caption = Clock Alarms
  • BorderIcons = [biSystemMenu,biMinimize]
  • BorderStyle = bsSingle
  • Position = poDefaultPosOnly

Сохраните модуль формы под именем MainUnit.pas, а проект — под именем Alarms.dpr.

Шаг 2. В форме MainForm будет отображаться список будильников. Для управления списком нужны кнопки: New, Edit и Delete. Для быстрого и удобного закрытия формы нужна еще кнопка Close. Поэтому поместите в форму соответствующее число компонентов Button (с идентификаторами NewButton , EditButton , DeleteButton , CloseButton ) и задайте для них надписи, размеры и положение как на рисунке 9.19.

Рисунок 9.19. Кнопки для управления списком будильников

Шаг 3. Установите в компоненте NewButton свойство Default в значение True, чтобы кнопка срабатывала при нажатии клавиши Enter.

Шаг 4. Для компонента CloseButton создайте следующий обработчик события OnClick :

Шаг 5. Необходимые подготовительные операции сделаны. Теперь перейдем к разработке окна диалога, предназначенного для ввода параметров будильника. Это окно будет вызываться при нажатии кнопок New и Edit. С этой целью добавьте в проект новую форму, дайте ей идентификатор AlarmDetailsForm , скорректируйте размеры и установите следующие значения свойств:

  • Caption = Alarm Details
  • BorderStyle = bsDialog
  • Position = poScreenCenter

Теперь сохраните модуль формы под именем AlarmDetailsUnit.pas.

Шаг 6. Добавьте в форму кнопки OK и Cancel и установите их свойства так, как показано на рисунке 9.20.

Рисунок 9.20. Стандартные кнопки OK и Cancel и их свойства

Шаг 7. Теперь займемся размещением компонентов для ввода данных. Прежде всего подумаем, какие параметры должны устанавливаться в диалоге. К ним относятся: текстовое сообщение, которое появится по сигналу будильника, время сигнала с точностью до минуты, признак того, нужно ли проигрывать звуковой сигнал, периодичность выдачи сигналов (ежедневно, в заданный день недели или в конкретный день). Учли все? Вроде бы, да. Тогда разместите в форме компоненты, обеспечивающие ввод перечисленных параметров (рисунок 9.21).

Рисунок 9.21. Эскиз окна для установки параметров будильника

Эскиз окна диалога создан (с помощью выносок на рисунке пояснены названия компонентов). Окинув его взором, вы обнаружите, что знакомых вам компонентов немного — это Bevel , Label и Button . Зато новых — хоть отбавляй: CheckBox , RadioButton , Edit , MaskEdit , GroupBox , ComboBox , DateTimePicker . Однако не пугайтесь, мы обо всех расскажем, и вы убедитесь, что обращаться с ними вовсе не сложно.

9.3.1. Фокус ввода

Во время работы программы только один из компонентов принимает клавиатурный ввод в текущий момент времени. Принято говорить, что такой компонент обладает фокусом ввода или просто — активен. Передача фокуса ввода осуществляется щелчками компонентов или нажатием клавиш Tab и Shift+Tab на клавиатуре. При использовании клавиатуры фокус ввода передается последовательно от одного компонента другому, причем клавиша Tab обеспечивает перебор элементов в прямом порядке, а сочетание клавиш Shift+Tab – в обратном.

Очередность, в которой компонент получает фокус ввода, задается его свойством TabOrder. Свойство TabOrder действует относительно содержащего компонента, например очередность перебора компонентов MessageEdit и TimeMaskEdit задается относительно формы, а очередность перебора компонентов WeeklyComboBox и DatePicker — относительно компонента GroupBox .

Если нужно исключить компонент из очереди на фокус ввода, установите свойство TabStop в значение False. Однако в этом случае фокус ввода можно насильно передать компоненту с помощью мыши или «горячей» клавиши.

Изначально порядок перебора соответствует порядку добавления компонентов в форму, но его можно изменить, устанавливая значения свойства TabOrder в компонентах. Если компонентов в окне диалога очень много, то это занятие может стать довольно утомительным. В этом случае удобнее пользоваться окном Edit Tab Order , которое открывается по команде меню Edit | Tab Order. (рисунок 9.22).

Рисунок 9.22. В окне Edit Tab Order выставляется порядок перебора компонентов формы

Шаг 8. В этом окне задайте порядок перебора компонентов формы AlarmDetailsForm таким, как показан на рисунке.

Ну хорошо, скажете вы, допустим, порядок перебора задан. А как управлять передачей фокуса ввода программно? Очень просто. Чтобы передать фокус ввода требуемому компоненту, у него нужно вызвать метод SetFocus . Кстати при управлении фокусом ввода очень полезным может оказаться свойство формы ActiveControl , которое указывает активный компонент. Это свойство доступно в окне свойств и часто используется для указания компонента, который первым получит фокус ввода (в обход номера очереди). Если значение свойства не задано, то первым фокус ввода получает компонент, в котором значение свойства TabOrder равно нулю.

Шаг 9. Хотя окно диалога Alarm Details еще не готово, вам, наверное, не терпится его опробовать и убедиться, что перебор компонентов происходит в нужном порядке. Для этого нужно связать выполнение диалога с нажатием в главной форме кнопки New. . Поэтому подключите модуль AlarmDetails в модуле Main и определите следующий обработчик события OnClick для кнопки NewButton :

Шаг 10. Теперь выполните компиляцию и запустите программу. В окне Clock Alarms нажмите кнопку New. . Вашему взору предстанет окно диалога Alarm Settings (рисунок 9.23).

Рисунок 9.23. Рабочий прототип окна для установки параметров будильника

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

9.3.2. Переключатели

Переключатели (check boxes) используются для установки параметров, характеризуемых двумя значениями – «Да» и «Нет» (True и False). Переключатели создаются с помощью компонента CheckBox , расположенного в палитре компонентов на вкладке Standard (рисунок 9.24).

Рисунок 9.24. Компонент CheckBox


Характерные свойства этого компонента собраны в таблице 9.6.

Свойство Описание
Alignment Определяет, с какой стороны от переключателя находится текст: taRightJustify – справа, taLeftJustify – слева.
AllowGrayed Если равно True, то переключатель имеет три состояния.
Caption Текст рядом с переключателем.
Checked Определяет, включен ли переключатель.
State Содержит текущее состояние переключателя.
WordWrap Если равно значению True, то работает перенос слов.
Таблица 9.6. Важнейшие свойства компонента CheckBox

Обычно переключатель имеет два состояния: включен или выключен . Текущее состояние определяется значением свойства Checked . Если оно равно значению True, то переключатель включен, иначе — выключен. Бывает, что переключатель имеет еще и третье состояние — неопределенное (grayed). В этом состоянии переключатель закрашивается серым цветом. Если переключатель имеет три состояния, то вместо свойства Checked используется свойство State , а в свойстве AllowGrayed (разрешает неопределенное состояние) устанавливается значение True.

Когда при работе программы пользователь щелкает переключатель, в нем изменяются значения свойств Checked и State , а также происходит событие OnClick . Обрабатывая это событие, можно установить любую зависимость между состоянием переключателя и состоянием других компонентов.

В нашем примере компонент CheckBox используется для установки параметра Play Sound , управляющего выдачей звукового сигнала (рисунок 9.25). Мы назвали его SoundCheckBox .

Рисунок 9.25. Переключатель Play Sound представлен компонентом CheckBox

Шаг 11. Чтобы при первом появлении окна диалога, режим Play Sound был включен, установите в компоненте SoundCheck свойство Checked в значение True.

9.3.3. Взаимоисключающие переключатели

Взаимоисключающие переключатели (radio buttons) служат для установки взаимоисключающих параметров. Они обычно объединяются в группы и позволяют пользователю выбрать одно значение из фиксированного (причем немногочисленного) набора вариантов. При включении одного такого переключателя остальные переключатели этой же группы выключаются.

Группа переключателей создается с помощью нескольких компонентов RadioButton . Компонент RadioButton находится в палитре компонентов на вкладке Standard (рисунок 9.26).

Рисунок 9.26. Компонент RadioButton

Характерные свойства компонента RadioButton описаны в таблице 9.7.

Свойство Описание
Alignment Определяет, с какой стороны от переключателя находится текст: taRightJustify — справа, taLeftJustify — слева.
Caption Текст рядом с переключателем.
Checked Определяет, включен ли переключатель.
WordWrap Если равно значению True, то работает перенос слов.
Таблица 9.7. Важнейшие свойства компонента RadioButton

В форму всегда помещаются несколько компонентов RadioButton , соответствующих возможным значениям устанавливаемого параметра. Например, в форме AlarmDetailsForm содержится три таких компонента ( EverydayRadioButton , WeeklyRadioButton и DateRadioButton ), которые используются для выбора периодичности срабатываний будильника (рисунок 9.27).

Рисунок 9.27. Переключатели Everyday, Weekly и Date представлены компонентами RadioButton

Внимание! Выбор положения переключателя осуществляется с помощью клавиш со стрелками.

Шаг 12. Текущее состояние переключателя контролируется свойством Checked . Если в одном переключателе оно устанавливается в значение True, то во всех остальных переключателях этой же группы оно устанавливается в значение False. Установите в компоненте EverydayRadioBox свойство Checked в значение True — этот переключатель будет изначально включен.

Шаг 13. Когда пользователь щелкает переключатель, в соответствующем компоненте RadioButton свойство Checked получает значение True и происходит событие OnClick . Обрабатывая это событие, можно установить любую зависимость между состоянием переключателя и состоянием других компонентов формы. Например, когда включен режим Everyday , компоненты для ввода дня недели и даты должны быть недоступны. Когда включен режим Weekly on , должен быть доступен выбор дня недели, но недоступна установка даты. Наконец, когда включен режим Date , установка дня недели должна быть недоступна, а установка даты — доступна. Чтобы достигнуть такой согласованности в работе, определите для переключателей EverydayRadioButton , WeeklyRadioButton и DateRadioButton единый обработчик события OnClick :

Шаг 14. Разумеется, компоненты WeeklyComboBox и DatePicker первоначально должны быть недоступны. Поэтому, удерживая клавишу Shift, выберите названную группу компонентов и установите свойство Enabled в значение False.

Теперь запустите программу и проверьте правильность ее работы.

9.3.4. Группа взаимоисключающих переключателей

Для быстрой организации группы взаимоисключающих переключателей очень удобен компонент RadioGroup , расположенный в палитре компонентов на вкладке Standard (рисунок 9.28).

Рисунок 9.28. Компонент RadioGroup

Его характерные свойства кратко описаны в таблице 9.8.

Свойство Описание
Align Способ выравнивания в пределах содержащего компонента.
Caption Подпись к группе переключателей.
Columns Число колонок в группе переключателей.
ItemIndex Номер выбранного элемента, начиная с нуля. Если все переключатели находятся в выключенном состоянии, то значение свойства равно -1.
Items Подписи к переключателям.
Таблица 9.8. Важнейшие свойства компонента RadioGroup

Компонент RadioGroup удобен тем, что заменяет группу компонентов RadioButton . Расположение переключателей, которые он отображает, подбирается автоматически с учетом заданного в свойстве Columns количества колонок. Номер активного зависимого переключателя хранится в значении свойства ItemIndex . Следующий рисунок 9.29 не относится к приложению Alarms, а просто поясняет, что такое компонент RadioGroup :

Рисунок 9.29. Четырехпозиционный переключатель представлен компонентом RadioGroup

Компонент RadioGroup создает группу, состоящую исключительно из переключателей. Однако он не годится в тех случаях, когда в группе должны присутствовать другие компоненты, что как раз имеет место в нашем примере. В этой ситуации для группировки компонентов применяется компонент GroupBox .

9.3.5. Панель группы компонентов

Компонент GroupBox служит для группировки компонентов, он расположен в палитре компонентов на вкладке Standard (рисунок 9.30).

Рисунок 9.30. Компонент GroupBox

Компонент GroupBox выглядит как панель с заголовком рисунок 9.31. Текст заголовка задается в свойстве Caption .

Рисунок 9.31. Панель с заголовком представлена компонентом GroupBox

Компонент GroupBox может содержать в себе другие компоненты. Это, например, означает, что установка его свойства Visible в значение False прячет группу со всеми расположенными внутри компонентами, а не только рамку с заголовком.

9.3.6. Поле ввода и редактор текста

Для ввода текста предназначены компоненты Edit и Memo . Они представляют собой соответственно поле ввода и редактор многострочного текста (кроме них существует еще компонент RichEdit , предназначенный для ввода и отображения форматированного текста, но о нем мы поговорим отдельно).

Поле ввода ( Edit ) служит для ввода различных слов, фраз и другого относительно короткого текста. Он не имеет полос прокрутки, но разрешает прокручивать текст по горизонтали клавишами перемещения курсора влево и вправо. Компонент Edit расположен в палитре компонентов на вкладке Standard (рисунок 9.32).

Рисунок 9.32. Компонент Edit

Характерные свойства компонента Edit описаны в таблице 9.9.

Свойство Описание
AutoSelect Если равно значению True, то при активизации редактора находящийся в нем текст автоматически выделяется.
AutoSize Если равно значению True, то высота редактора автоматически подгоняется по высоте текста.
BevelEdges Вложенные свойства beLeft , beTop , beRight и beBottom определяют видимость соответственно левой, верхней, правой и нижней сторон рельефной рамки.
BevelInner Внутренний скос рельефной рамки: bvNone — скос отсутствует, bvLowered — скос внутрь, bvRaised — скос наружу; bvSpace — скос заменяется отступом.
BevelKind Вид рельефной рамки: bkNone — рамки нет, bkTile — рамка с четкими скосами, bkSoft — рамка со сглаженными скосами, bkFlat — плоская рамка (без скосов).
BevelOuter Внешний скос рельефной рамки: bvNone — скос отсутствует, bvLowered — скос внутрь, bvRaised — скос наружу; bvSpace — скос заменяется отступом.
CharCase Преобразует текст к прописным или строчным буквам: ecUpperCase – к прописным буквам, ecLowerCase – к строчным буквам, ecNormal –преобразование символов не выполняется.
HideSelection Если равно значению True, то при потере редактором активности выделение текста снимается.
MaxLength Максимальное количество символов, которое пользователь может ввести. Если оно равно 0, то пользователь может ввести текст неограниченной длины.
OEMConvert Если равно значению True, то символы текста преобразуются в кодовую таблицу OEM.
PasswordChar Если не равно #0, то указанный в этом свойстве символ отображается вместо каждого символа текста. Применяется для ввода пароля.
ReadOnly Если равно значению True, то пользователь не сможет изменить текст в редакторе.
Text Редактируемый текст.
OnChange Происходит при изменении текста.
Таблица 9.9. Отличительные свойства и события компонента Edit

Редактируемый текст содержится в свойстве Text . Его максимальная длина определяется значением свойства MaxLength .

Иногда компонент Edit используется для отображения нередактируемого текста. Для этого свойство ReadOnly устанавливается в значение True. Вы спросите, чем он в таком состоянии лучше компонента Label ? А тем, что может получать фокус ввода. Кроме того, текст в поле ввода можно выделить и поместить в Буфер Обмена.

Компонент Edit легко приспособить для ввода паролей. Для этого достаточно установить в свойстве PasswordChar вместо символа #0 какой-нибудь другой символ, обычно символ звездочки ( * ). Символ, заданный в свойстве PasswordChar отображается вместо реально вводимых символов, что мешает подсмотреть пароль посторонним.

Шаг 15. В форме SettingsForm компонент Edit применяется для ввода текстового сообщения будильника. Выберите его в окне свойств и в значении свойства Text впишите «Reminder !» (рисунок 9.33). Этот текст будет появляться в редакторе при появлении окна диалога.

Рисунок 9.33. Компонент Edit используется для ввода текстового сообщения будильника

Шаг 16. Изменение текста во время работы программы приводит к возникновению в компоненте Edit события OnChange . Обрабатывая это событие, можно, например, устроить работу окна диалога таким образом, что кнопка OK будет недоступна, если в редакторе нет текста. Чтобы реализовать такое поведение нашего диалога, определите для компонента MessageEdit следующий обработчик события OnChange :

Выполните компиляцию программы и проверьте ее работу.

Прежде чем продолжить обсуждение примера Alarms, сделаем несколько замечаний по поводу редактирования многострочного текста. Редактор многострочного текста представлен компонентом Memo (рисунок 9.34).

Рисунок 9.34. Компонент Memo

Характерные свойства компонента Memo описаны в таблице 9.10.

Свойство Описание
Align Способ выравнивания компонента в пределах содержащего компонента.
Alignment Выравнивание текста: taLeftJustify – прижат к левой границе, taRightJustify – прижат к правой границе, taCenter – центрирован.
HideSelection Если равно значению True, то при потере редактором фокуса ввода выделение текста снимается.
Lines Текст в виде массива строк.
MaxLength Максимальное количество символов, которое пользователь может ввести. Если оно равно 0, то пользователь может ввести текст неограниченной длины.
OEMConvert Если равно значению True, то символы текста преобразуются в кодовую таблицу OEM.
ReadOnly Если равно значению True, то пользователь не сможет изменить текст в редакторе.
ScrollBars Управляет видимостью полос прокрутки: ssNone – полосы прокрутки скрыты, ssBoth – полосы прокрутки видны, ssHorizontal – видна лишь горизонтальная полоса прокрутки, ssVertical – видна лишь вертикальная полоса прокрутки.
WantReturns Если равно значению True, то клавиша Enter начинает в редакторе новую строку. Иначе нажатие клавиши Enter ассоциируется с нажатием стандартной кнопки окна диалога и для перевода строк применяется сочетание клавиш Ctrl+Enter.
WantTabs Если равно значению True, то клавиша Tab вставляет в текст символ табуляции, вместо того чтобы передать фокус ввода следующему компоненту.
WordWrap Если равно значению True, то работает перенос слов.
OnChange Происходит при изменении текста.
Таблица 9.10. Важнейшие свойства и события компонента Memo

Компонент Memo похож на Edit , но в отличие от него хранит не одну строку текста, а множество строк. Доступ к строкам обеспечивает свойство Lines , представляющее собой объект класса TStrings (см. главу 3). С помощью свойства Lines строки можно добавлять, вставлять, удалять и т.д. Свойство Lines доступно в окне свойств, поэтому на стадии проектирования вы можете заполнить компонент Memo некоторым исходным текстом (рисунок 9.35). Этот текст увидит пользователь при появлении формы на экране. Ввод исходного текста осуществляется в специальном редакторе текста ( String list editor ), которое вызывается нажатием кнопки с многоточием в поле значения свойства Lines .

Рисунок 9.35. Окно для ввода многострочного текста, отображаемого компонентом Memo

Компонент Memo часто имеет одну или две полосы прокрутки (вертикальную и горизонтальную). Их появление зависит от значения свойства ScrollBars .

В нашем приложении Alarms компонент Memo не нужен, но вам он безусловно пригодится в других программах.

9.3.7. Редактор с шаблоном

Поскольку компонент Edit не проверяет, что вводит пользователь, он не удобен для ввода данных строго определенного формата, например телефонных номеров, времени и др. На этот случай разработчики среды Delphi предусмотрительно создали компонент MaskEdit . Он находится в палитре компонентов на вкладке Additional (рисунок 9.36).

Рисунок 9.36. Компонент MaskEdit

Компонент MaskEdit представляет собой поле ввода, которое вынуждает пользователя вводить данные в строго заданном формате. Во многом аналогичный компоненту Edit , он отличается от последнего тем, что имеет свойство EditMask и не имеет свойств HideSelection и OEMConvert .

Свойство EditMask задает шаблон (маску) для ввода символов текста. Шаблон имеет вид текстовой строки, его символы называются форматными и управляют тем, что вводит пользователь: буквы или цифры, в каком порядке, сколько и т.д. Мы не будем утомлять вас подробным описанием форматных символов, при необходимости обратитесь к справочному руководству. Нас интересует только шаблон для ввода времени с точностью до минуты.

Шаг 17. Выберите компонент TimeMaskEdit , затем в окне свойств перейдите к свойству EditMask и щелчком кнопки с многоточием откройте специальный редактор для этого свойства — Input Mask Editor (рисунок 9.37):

Рисунок 9.37. Выбор шаблона для компонента MaskEdit

В этом окне вы можете ввести шаблон и проверить его работу. Часто используемые шаблоны, например шаблоны телефонных номеров, даты, времени и некоторые другие, можно просто выбрать среди уже имеющихся образцов. Этой возможностью мы и воспользуемся. Выберите в списке Sample Masks пункт Short Time и щелкните на кнопке OK. Шаблон для ввода времени задан и имеет вид !90:00;1;_ . Обратите внимание, как при этом изменился компонент TimeMaskEdit (рисунок 9.38):

Рисунок 9.38. Компонент MaskEdit настроен для ввода времени

Шаг 18. Теперь давайте сделаем так, чтобы при появлении окна диалога поле ввода TimeMaskEdit не было пустым, а содержало текущее время. Для этого создайте у формы обработчик события OnCreate :

Готово. Запустите программу и убедитесь, что она работает, как вы того ожидаете.

9.3.8. Раскрывающийся список

Раскрывающийся список (combo box) позволяет пользователю выбрать значение из большого множества альтернатив. Он представляет собой поле ввода, к которому прикреплен раскрывающийся список значений. Редактор служит для ввода нового значения, а список — для выбора существующего значения. Количество элементов в списке может быть произвольным, причем элементы можно динамически добавлять, удалять, заменять и т.д. Элементами списка обычно служат текстовые строки, но могут быть и графические рисунки (в последнем случае их редактирование невозможно).

Раскрывающийся список представлен компонентом ComboBox , который находится в палитре компонентов на вкладке Standard (рисунок 9.39):

Рисунок 9.39. Компонент ComboBox

Характерные свойства компонента ComboBox собраны в таблице 9.11.

Свойство Описание
AutoCloseUp Если равно True, то при вводе пользователем текста, который уже существует в списке Items , раскрытый список значений автоматически закрывается.
AutoComplete Если равно True, то компонент предугадывает вводимый пользователем текст на основе списка Items .
AutoDropDown Если равно True, то при вводе текста автоматически раскрывается список существующих значений.
BevelEdges Вложенные свойства beLeft , beTop , beRight и beBottom определяют видимость соответственно левой, верхней, правой и нижней сторон рельефной рамки.
BevelInner Внутренний скос рельефной рамки: bvNone — скос отсутствует, bvLowered — скос внутрь, bvRaised — скос наружу; bvSpace — скос заменяется отступом.
BevelKind Вид рельефной рамки: bkNone — рамки нет, bkTile — рамка с четкими скосами, bkSoft — рамка со сглаженными скосами, bkFlat — плоская рамка (без скосов).
BevelOuter Внешний скос рельефной рамки: bvNone — скос отсутствует, bvLowered — скос внутрь, bvRaised — скос наружу; bvSpace — скос заменяется отступом.
CharCase Автоматическое преобразование регистра букв: ecLowerCase — к строчным буквам, ecUpperCase — к заглавным буквам, ecNormal — без преобразования.
DropDownCount Количество одновременно видимых элементов раскрывающегося списка.
ItemHeight Высота отдельного элемента списка, когда значение свойства Style равно csOwnerDrawFixed.
ItemIndex Порядковый номер выбранного в списке элемента, начиная с нуля.
Items Элементы раскрывающегося списка.
MaxLength Максимальное количество символов, которое пользователь может ввести в строке редактора. Если оно равно 0, то пользователь может ввести текст неограниченной длины.
Sorted Если равно True, то элементы списка сортируются в алфавитном порядке.
Style Стиль отображения выпадающего списка (см. табл. 7.12).
Text Текст в строке редактора.
OnChange Происходит при вводе текста или выборе значения из списка. Не происходит при программном изменении свойства Text.
OnCloseUp Происходит при закрытии списка значений.
OnDrawItem Происходит при рисовании элемента раскрывающего списка, но только в том случае, если свойство Style содержит значение csOwnerDrawFixed или csOwnerDrawVariable .
OnDropDown Происходит при раскрытии списка значений.
OnMeasureItem Происходит перед рисованием элемента раскрывающего списка для расчета его высоты. Требует, чтобы свойство Style содержало значение csOwnerDrawVariable .
OnSelect Происходит при выборе значения в раскрывающемся списке.
Таблица 9.11. Важнейшие свойства компонента ComboBox

Раскрывающийся список умеет отображать себя по-разному в зависимости от значения свойства Style (см. таблицу 9.12).

Значение Описание
csSimple Редактор и постоянно отображаемый список.
csDropDown Редактор и ассоциированный с ним раскрывающийся список.
csDropDownList Раскрывающийся список без редактора. Все элементы списка имеют одинаковую высоту, которая рассчитывается автоматически.
csOwnerDrawFixed Раскрывающийся список без редактора. Все элементы списка имеют одинаковую высоту, заданную в свойстве ItemHeight .
csOwnerDrawVariable Раскрывающийся список без редактора. Элементы списка имеют разную высоту.
Таблица 9.12. Значения свойства Style компонента ComboBox

В двух последних случаях в компоненте ComboBox происходит событие OnDrawItem . Вы можете его перехватить и рисовать каждый элемент выпадающего списка как вам вздумается. Если элементы списка имеют разную высоту (стиль csOwnerDrawVariable), то компонент генерирует событие OnMeasureItem , чтобы узнать высоту каждого элемента. Стили csOwnerDrawFixed и csOwnerDrawVariable применяются в тех случаях, когда элементы списка должны быть рисунками.

Шаг 19. Раскрывающиеся списки пригодились нам в диалоге Alarm Details для выбора дня недели (компонент WeeklyComboBox ). Поскольку все дни недели заранее известны, выберите в свойстве Style значение csDropDownList (рисунок 9.40).

Рисунок 9.40. Для выбора дня недели применяется компонент ComboBox в стиле csDropDownList

Шаг 20. Теперь компонент WeeklyComboBox нужно заполнить списком исходных значений. Выберите его в форме, затем в окне свойств перейдите к свойству Items и нажмите кнопку с многоточием в поле значения. В появившемся окне введите список строк, как показано на рисунке 9.41.

Рисунок 9.41. В этом окне вводятся элементы списка — дни недели

Щелкните кнопку OK — список значений компонента WeeklyComboBox задан.

Шаг 21. Выбранный элемент раскрывающегося списка определяется значением свойства ItemIndex . Начальное значение свойства равно -1, что означает — ни один элемент не выбран. Однако в компоненте WeeklyComboBox должно быть выбрано то значение, которое соответствуют текущей дате. С этой целью нужно доработать у формы обработчик события OnCreate . В итоге он будет иметь следующий вид:

Реализация метода основана на том, что компонент DatePicker при создании формы сразу содержит текущую дату.

На этом с визуальной частью диалога Alarm Details покончено. Правда, мы ничего не сказали о компоненте DateTimePicker (рисунок 9.42).

Рисунок 9.42. Компонент DateTimePicker

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

Свойство Описание
BevelEdges Вложенные свойства beLeft , beTop , beRight и beBottom определяют видимость соответственно левой, верхней, правой и нижней сторон рельефной рамки.
BevelInner Внутренний скос рельефной рамки: bvNone — скос отсутствует, bvLowered — скос внутрь, bvRaised — скос наружу; bvSpace — скос заменяется отступом.
BevelKind Вид рельефной рамки: bkNone — рамки нет, bkTile — рамка с четкими скосами, bkSoft — рамка со сглаженными скосами, bkFlat — плоская рамка (без скосов).
BevelOuter Внешний скос рельефной рамки: bvNone — скос отсутствует, bvLowered — скос внутрь, bvRaised — скос наружу; bvSpace — скос заменяется отступом.
BevelWidth Ширина скосов рельефной рамки.
CalAlignment Способ выравнивания раскрывающегося диалога: dtaLeft — по левому краю, dtaRight — по правому краю.
CalColors Цвета: BackColor — ни на что не влияет, существует для унификации настройки цвета с другими компонентами; MonthBackColor — цвет фона раскрывающего диалога; TextColor — цвет текста; TitleBackColor — цвет фона заголовка; TitleTextColor — цвет текста заголовка; TrailingTextColor — цвет текста дат, не принадлежащих текущему месяцу.
Checked Значение переключателя, который отображается, если свойство ShowCheckbox содержит значение True.
Date Выбранная дата.
DateFormat Формат даты: dfShort — короткий, dfLong — длинный.
DateMode Режим работы компонента: dmComboBox — по щелчку кнопки со стрелкой раскрывается окно с месячным календарем, dmUpDown — вместо кнопки со стрелкой показывается пара кнопок со стрелками вверх и вниз, щелчки на которых прокручивают день, месяц или год.
Format Формат даты и времени.
Kind Если равно значению dtkDate , то компонент предназначен для выбора даты, а если значению dtkTime , то для выбора времени.
MaxDate Максимальное значение даты, которое может выбрать пользователь.
MinDate Минимальное значение даты, которое может выбрать пользователь.
ParseInput Если равно значению True, то по мере ввода значения пользователем происходит событие OnUserInput .
ShowCheckbox Показывает переключатель (флажок). Значение переключателя определяется свойством Checked .
Time Выбранное время.
OnChange Происходит при изменении значения даты и времени.
OnCloseUp Происходит при сворачивании раскрывающегося диалога.
OnUserInput Происходит по мере ввода данных пользователем.
Таблица 9.13. Важнейшие свойства и события компонента DateTimePicker

В очередной раз выполните компиляцию программы и запустите ее. Откройте окно диалога Alarm Details и хорошенько его потестируйте (рисунок 9.43).

Рисунок 9.43. Тестирование окна Alarm Details

Все компоненты работают правильно. Можете поздравить себя с очередным достижением. Вы создали важную часть приложения Alarms — окно диалога, а заодно разобрались с множеством новых компонентов.

9.3.9. Установка и получение данных

Окно диалога есть, но пользы от него пока нет. Все дело в том, что мы научились устанавливать параметры будильника, но не научились их принимать и хранить.

Шаг 22. Для хранения параметров будильника нам нужна новая структура данных, очевидно класс объектов. Немного поразмыслив, приходим к следующему описанию:

Поясним назначение полей и методов. Поле MsgText предназначено для хранения текстового сообщения. В поле DateTime записывается время и дата сигнала. Значение поля PlaySound показывает, требуется ли звуковое сопровождение сообщения. Поле Recurring определяет периодичность работы будильника и принимает следующие значения:

  • 0 – ежедневно;
  • 1..7 – в заданный день недели (1 — Пн, 2 — Вт, . 7 — Вс);
  • 8 – однажды в заданный день.

В первых двух случаях поле DateTime хранит только время, а в последнем еще и дату. Такое ухищрение позволяет организовать компактное хранение данных. Флаг Handled , объявленный в секции private , является служебным и позволит избежать повторных срабатываний, когда будильник уже прозвенел. Метод GetAlarmStr мы определили для удобства. Он будет формировать строку сообщения, содержащую время и текст напоминания. Метод CheckTime проверит, пора ли выдать сигнал и если да, то сделает это.

Шаг 23. Поместите описание класса TAlarm в раздел interface модуля AlarmDetails . Затем в разделе implementation наберите текст методов GetAlarmStr и CheckTime :

Для правильной работы будильника метод CheckTime должен вызываться не реже одного раза в минуту. Чем чаще вызывается метод, тем меньше инерционность будильника, но тем больше пустых опросов, а значит выше загруженность операционной системы. Компромиссная частота — два раза в секунду. Так как в одну и ту же минуту метод CheckTime будет вызван несколько раз, то для избежания повторных срабатываний используется флаг Handled . Будильник выдает сообщение только в том случае, если текущее время совпадает с временем, на которое будильник установлен и при условии, что в данную минуту он еще не звенел.

Шаг 24. Давайте теперь позаботимся о передаче данных в окно диалога перед его запуском и о приеме данных после завершения. Удобнее всего, чтобы за это отвечало само окно диалога, т.е. форма AlarmDetailsForm . С этой целью определите в классе TAlarmDetilasForm два метода — GetData и SetData . Методы следует поместить в секцию public :

В разделе implementation наберите программный текст методов:

Метод GetData просто заполняет поля переданного в параметре объекта Alarm значениями, которые установлены в компонентах окна диалога. Метод SetData выполняет обратные действия, заполняя компоненты окна диалога значениями, которые содержатся в полях объекта Alarm .

На этом с разработкой модуля AlarmDetails покончено и окно диалога Alarm Details полностью готово к использованию. Дальше необходимо обеспечить формирование, редактирование и визуализацию списка будильников. Эта задача решается с помощью компонента ListBox .

9.3.10. Список

Компонент ListBox отображает список элементов, которые пользователь может просматривать и выбирать, но не может непосредственно модифицировать. По умолчанию элементами списка являются строки, но могут быть и графические объекты. Элементы могут располагаться в одну или несколько колонок и автоматически сортироваться. При необходимости обеспечивается возможность прокрутки списка. Компонент ListBox находится в палитре компонентов на вкладке Standard (рисунок 9.44).

Рисунок 9.44. Компонент ListBox

Его характерные свойства собраны в таблице 9.14.


Свойство Описание
Align Способ выравнивания компонента в пределах содержащего компонента.
AutoComplete Если равно True, то можно быстро выбрать элемент, если начать набирать его текст на клавиатуре.
BevelEdges Вложенные свойства beLeft , beTop , beRight и beBottom определяют видимость соответственно левой, верхней, правой и нижней сторон рельефной рамки.
BevelInner Внутренний скос рельефной рамки: bvNone — скос отсутствует, bvLowered — скос внутрь, bvRaised — скос наружу; bvSpace — скос заменяется отступом.
BevelKind Вид рельефной рамки: bkNone — рамки нет, bkTile — рамка с четкими скосами, bkSoft — рамка со сглаженными скосами, bkFlat — плоская рамка (без скосов).
BevelOuter Внешний скос рельефной рамки: bvNone — скос отсутствует, bvLowered — скос внутрь, bvRaised — скос наружу; bvSpace — скос заменяется отступом.
BorderStyle Определяет, имеет ли список рамку.
Columns Количество колонок в списке.
ExtendedSelect Если равно значению True, то пользователь может выбрать в списке диапазон элементов (однако лишь в том случае, если MultiSelect тоже равно значению True).
IntegralHeight Если равно значению True, то высота списка автоматически уменьшается, чтобы быть кратной высоте элемента.
ItemHeight Высота элемента списка, когда значение свойства Style равно lbOwnerDrawFixed.
Items Элементы списка.
MultiSelect Если равно значению True, то пользователь может выбрать в списке несколько элементов.
ScrollWidth Логическая ширина списка в пикселях. Если значение свойства ScrollWidth больше значения свойства Width , то появляется горизонтальная полоса прокрутки. В противном случае полоса прокрутки не показывается.
Sorted Если равно значению True, то элементы списка сортируются в алфавитном порядке.
Style Стиль отображения списка (см. табл. 7.14).
OnData Предназначено для формирования списка элементов перед рисованием. Происходит только в том случае, если свойство Style содержит значение lbVirtual или lbVirtualOwnerDraw .
OnDataFind Происходит, когда пользователь пытается быстро перейти к элементу, набирая текст элемента на клавиатуре. Обработчик этого события должен на основании введенной пользователем строки вернуть номер соответствующего элемента. Возникает только в том случае, если свойство Style содержит значение lbVirtual или lbVirtualOwnerDraw .
OnDataObject Происходит при обращении к массиву Objects в списке Items , но только в том случае, если свойство Style содержит значение lbVirtual или lbVirtualOwnerDraw . Обработчик события должен вернуть соответствующий элементу объект.
OnDrawItem Происходит при рисовании отдельно взятого элемента списка, но только в том случае, если свойство Style содержит одно из следующих значений: lbOwnerDrawFixed , lbOwnerDrawVariable , lbVirtualOwnerDraw .
OnMeasureItem По замыслу разработчиков событие происходит при расчете высоты отдельно взятого элемента списка перед его рисованием на экране и лишь в том случае, если свойство Style содержит значение lbOwnerDrawVariable . Однако из-за дефекта в модуле StdCtrls событие OnMeasureItem не срабатывает.
Таблица 9.14. Важнейшие свойства и события компонента ListBox

Особенности хранения и отображения элементов списка определяются свойством Style , возможные значения которого описаны в таблице 9.15.

Значение Описание
LbStandard Все элементы списка имеют одинаковую высоту, которая рассчитывается исходя из размера шрифта.
LbOwnerDrawFixed Все элементы списка имеют одинаковую высоту, заданную в свойстве ItemHeight . За рисование элементов отвечает программист, который должен создать обработчик события OnDrawItem .
lbOwnerDrawVariable По замыслу разработчиков элементы списка имеют разную высоту, определяемую в обработчике события OnMeasureItem (из-за дефекта в модуле StdCtrls событие не срабатывает). За рисование элементов отвечает программист, который должен создать обработчик события OnDrawItem .
LbVirtual Элементы списка хранятся отдельно от компонента и запрашиваются с помощью события OnData . За рисование элементов отвечает компонент.
LbVirtualOwnerDraw Элементы списка хранятся отдельно от компонента и запрашиваются с помощью события OnData . За рисование элементов отвечает программист, который должен создать обработчик события OnDrawItem .
Таблица 9.15. Значения свойства Style компонента ListBox

Шаг 25. Давайте воспользуемся компонентом ListBox для организации списка будильников. Активизируйте форму MainForm , а затем опустите на нее компонент ListBox . Переименуйте компонент в AlarmListBox и скорректируйте его местоположение и размеры. Затем установите свойство TabOrder в значение 0, чтобы при отображении формы список первым получил фокус ввода (рисунок 9.45).

Рисунок 9.45. Компонент ListBox применяется для организации списка будильников

Решим теперь вопрос хранения будильников в компоненте AlarmListBox . Для хранения элементов служит свойство Items . Свойство Items — это объект класса TStrings , в нем свойство-массив Strings хранит отображаемые строки, а свойство-массив Objects — ассоциированные со строками объекты. В нашем примере массив Strings будет хранить выдаваемые по сигналу сообщения, а массив Objects — соответствующие им объекты класса TAlarm .

Теоретически все понятно, осталось реализовать все это практически. Создание, редактирование и удаление будильника осуществляется по щелчкам на кнопках NewButton , EditButton и DeleteButton соответственно. Поэтому в них требуется создать обработчики события OnClick .

Шаг 26. В кнопке New. обработчик события OnClick уже существует, но его необходимо доработать:

Метод NewButtonClick создает окно диалога Alarm Details и выполняет его в монопольном режиме. Если диалог завершается щелчком кнопки OK, создается новый объект будильника и в него переносятся данные из окна диалога. Затем этот объект добавляется в список AlarmList и его номер присваивается свойству списка ItemIndex . В результате новый элемент становится выделенным.

Вы, разумеется, хотите проверить работу новоиспеченного метода. Сейчас мы так и сделаем, но прежде нужно решить небольшой вопрос. Дело в том, что при уничтожении блока списка освобождаются только строки, но не освобождаются ассоциированные с ними объекты. Хотя память объектов так или иначе освобождается при завершении приложения, мы рекомендуем всегда освобождать память явно. Это считается «хорошим тоном» программирования и иногда позволяет выявить скрытые ошибки. Освобождение использованных в форме динамических данных осуществляется в обработчике события OnDestroy . Для формы MainForm он должен быть таким:

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

Шаг 27. Создайте в компоненте EditButton обработчик события OnClick :

Этот метод создает окно диалога Alarm Details , инициализирует его компоненты данными из выбранного в списке объекта будильника, а затем выполняет диалог в монопольном режиме. Если диалог завершился щелчком на кнопке OK, то данные из окна диалога переносятся обратно в объект будильника и соответственно изменяется отображаемая в блоке списка строка. Так как в результате последнего действия в списке пропадает полоса выбора (свойство ItemIndex получает значение -1), номер выделенного элемента предварительно сохраняется в локальной переменной SavedIndex , а затем восстанавливается.

Шаг 28. Осталось создать обработчик события OnClick в компоненте DeleteButton :

Метод DeleteButtonClick удаляет объект будильника и соответствующую ему строку в списке.

Обработчики событий для всех кнопок заданы, однако не спешите запускать приложение. Необходимо позаботиться о том, чтобы кнопки Edit. и Delete были доступны или недоступны в зависимости от того, выделен в списке элемент или нет. Как бы это сделать попроще? Первое решение, которое напрашивается — это вставить необходимые проверки в обработчики событий кнопок. Это неплохое решение, но оно больше подходит тем, кто привык решать задачу в лоб. Мы пойдем другим путем, воспользовавшись событием OnIdle объекта Application .

В объекте Application происходит событие OnIdle в период простоя программы, например во время ожидания пользовательского ввода. Благодаря этому событию программа может выполнять некоторую фоновую работу, которая в нашем случае заключается в управлении состоянием кнопок.

Для создания обработчика события OnIdle объекта Application воспользуемся уже знакомым вам компонентом ApplicationEvents (см. главу 8).

Шаг 29. Поместите в форму компонент ApplicationEvents , дайте ему одноименный идентификатор и создайте обработчик события OnIdle :

В передаваемом по ссылке параметре Done метод возвращает результат своей работы. Значение True показывает, что метод нужно вызывать не постоянно в течении простоя приложения, а только по одному разу в начале каждого периода простоя.

А сейчас выполните компиляцию, запустите программу и тщательно протестируйте работу главной формы (рисунок 9.46).

Рисунок 9.46. В этом окне создается список будильников

Будильники можно создавать, добавлять, удалять. Нам осталось сделать последний шаг — заставить будильники «звонить». Для этого нужно периодически вызывать метод CheckTime у каждого помещенного в список объекта TAlarm . Периодические по времени действия выполняются с помощью таймера, о котором мы дальше и поговорим.

9.4. Законченное приложение для выдачи сигналов в заданные моменты времени


9.4.1. Таймер

Таймер — это системный генератор событий, который периодически сообщает программе о завершении заданного промежутка времени. Интервал времени между событиями таймера может устанавливаться в диапазоне от 1 до 65535 миллисекунд. Используя таймер, учитывайте, что интервалы между этими событиями оказываются неточными из-за накладных расходов механизма обработки событий Windows.

В библиотеке VCL прием событий таймера обеспечивает компонент Timer . Он расположен в палитре компонентов на вкладке System (рисунок 9.47). Им мы и воспользуемся для «оживления» будильников в приложении Alarms.

Рисунок 9.47. Компонент Timer

Шаг 30. Активизируйте форму MainForm . Затем поместите в нее компонент Timer (рисунок 9.48). Если хотите, дайте ему любое имя.

Рисунок 9.48. Компонент Timer — на форме

Шаг 31. Интервал времени между событиями таймера задается в миллисекундах как значение свойства Interval . Изначально интервал равен 1000 миллисекунд (1 секунда). Частота контроля будильников должна быть два раза в секунду, поэтому установите свойство Interval в значение 500.

Шаг 32. Через заданные в свойстве Interval промежутки времени в компоненте Timer происходит событие OnTimer (единственное событие этого компонента). Для контроля за будильниками нам нужно создать обработчик этого события:

Смысл выполняемых действий очевиден: у каждого объекта в списке будильников вызывается метод CheckTime . Таким образом, каждый будильник периодически проверяет свое время и, если нужно, выдает предупреждение (рисунок 9.49).

Рисунок 9.49. Когда будильник срабатывает, звучит сигнал и на экран выдается сообщение

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

9.4.2. Файлы настроек

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

Сохранение и восстановление конфигурации осуществляется в Windows с помощью так называемых файлов настроек. Файл настроек (initialization file) — это текстовый файл, состоящий из секций. Секция начинается с имени, заключенного в квадратные скобки. В каждой секции содержатся определения некоторых связанных по смыслу параметров, представленные в виде пар Имя=Значение. Примером файла настроек может служить файл настроек проекта в системе Delphi. В нашем проекте это файл Alarms.dof.

Структуру файла настроек для программы Alarms выберем так, чтобы каждому будильнику соответствовала отдельная секция. Число секций, т.е. будильников, будем хранить в параметре AlarmCount секции Global Options. Вот как могло бы выглядеть содержимое файла:

Чтение и запись файла настроек осуществляется с помощью объектов TIniFile (заметьте, они не являются компонентами). Класс TIniFile описан в модуле IniFiles . Этот модуль необходимо самостоятельно добавить в вызывающий модуль с помощью оператора uses . При создании объекта TIniFile ему в конструктор передается имя INI-файла. Позже это имя можно узнать, обратившись к свойству FileName . Если в имени файла маршрут не был указан, считается что INI-файл находится в каталоге системы Windows.

Чтение переменных из INI-файла выполняется с помощью описанных ниже методов. В этих методах название секции передается в параметре Section , имя переменной – в параметре Ident , а значение по умолчанию – в параметре Default .

  • ReadBool (const Section, Ident: string; Default: Boolean): Boolean — возвращает значение булевской переменной.
  • ReadInteger (const Section, Ident: string; Default: Longint): Longint — возвращает значение целочисленной переменной.
  • ReadString (const Section, Ident, Default: string): string — возвращает значение строковой переменной.
  • ReadSection (const Section: string; Strings: TStrings) — читает из заданной секции имена всех переменных и помещает их в объект класса TStrings .
  • ReadSectionValues (const Section: string; Strings: TStrings) — читает из заданной секции все пары Имя=Значение и помещает их в список. Для доступа к Значению по Имени в объектах класса TStrings существуют свойства-массивы Names и Values .

При чтении значений из INI-файла может оказаться, что заданный идентификатор или секция отсутствует. В этом случае ошибки не происходит, а функции ReadBool , ReadInteger и ReadString возвращают значение, переданное в параметре Default .

Кроме методов чтения существуют также методы записи переменных INI-файла, которые описаны ниже. В этих методах название секции передается в параметре Section , имя переменной – в параметре Ident , а значение переменной — в параметре Value .

  • WriteBool (const Section, Ident: string; Value: Boolean) – записывает в INI-файл булевское значение.
  • WriteInteger (const Section, Ident: string; Value: Longint) – записывает в INI-файл целочисленное значение.
  • WriteString (const Section, Ident, Value: string) – записывает в INI-файл строковое значение.

Если в момент записи значения оказывается, что заданные секция и (или) идентификатор отсутствуют, они создаются.

Удаление секций INI-файла осуществляется с помощью метода EraseSection , в который передается единственный параметр — название секции.

Шаг 33. Давайте воспользуемся описанными методами для сохранения и восстановления будильников в программе ALARMS. Работу по сохранению и восстановлению параметров одного будильника лучше всего поручить классу TAlarm . Для этого добавьте в его описание два новых метода — LoadFromIniFile и SaveToIniFile .

Метод LoadFromIniFile предназначен для чтения из INI-файла полей объекта, а метод SaveToIniFile — для записи в INI-файл полей объекта. Секция INI-файла, с которой работают эти методы, передается в параметре Section.

Шаг 34. Наберите программный код методов в разделе implementation :

Шаг 35. Перейдем теперь от сохранения и восстановления одного будильника к загрузке и восстановлению всего списка. Эти действия следует выполнять соответственно при создании и уничтожении главной формы программы, т.е. в событиях OnCreate и OnDestroy . Создайте форме MainForm обработчик события OnCreate и доработайте обработчик события OnDestroy (не забудьте подключить модуль IniFiles ):

Вот пожалуй и все. Сохраните проект, выполните его компиляцию и запустите программу. Создайте несколько будильников, закройте программу, а затем запустите ее снова. Будильники на месте. Кстати, утилиту Alarms можно поместить в папку StartUp , тогда она всегда будет у вас под рукой.

9.5. Многостраничные окна диалога


9.5.1. Страницы с закладками

В сложных компьютерных системах предусмотрена настройка десятков различных параметров, которые пользователь просто обязан установить. Это означает либо перегруженность диалоговых окон, либо слишком большое их количество. Решение этой проблемы заключается в организации многостраничных окон диалога. Они создаются с помощью компонента, который изображается в виде множества снабженных закладками страниц, называемых вкладками (рисунок 9.50):

Рисунок 9.50. Пример вкладок в окне диалога

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

Создание вкладок рассмотрим на следующем примере. Представьте, что вкладками являются экзаменационные билеты по трем научным дисциплинам: математике, физике, химии. Каждая вкладка содержит один вопрос с возможными вариантами ответа. Пользователь должен на каждой вкладке выбрать правильный вариант ответа и завершить ввод щелчком на кнопке Result . При всех правильных ответах он получит оценку «отлично», при двух ответах — «хорошо», при ответе лишь на один вопрос — «удовлетворительно», а при всех неправильных ответах — «плохо».

Шаг 1. Приступим к реализации примера. Начните новый проект и установите для главной формы следующие свойства:

  • Name = ExamForm
  • Caption = Экзамен
  • BorderStyle = bsDialog
  • Position = poScreenCenter

Размеры формы подберите по своему усмотрению.

Шаг 2. Теперь поместите в форму компонент PageControl . Вы найдете его в палитре компонентов на вкладке Win32 (рисунок 9.51).

Рисунок 9.51. Компонент PageControl

Характерные свойства компонента PageControl кратко описаны в таблице 9.16.

Свойство Описание
ActivePage Активная вкладка (страница).
Align Способ выравнивания компонента в пределах содержащего компонента.
DockSite Определяет, используется ли компонент PageControl для стыковки других компонентов.
HotTrack Подсвечивает закладку при наведении на нее указателя мыши.
Images Список значков, отображаемых на закладках. Свойство Images используется совместно со свойством ImageIndex компонентов TabSheet . Компонент PageControl автоматически назначает каждой закладке номер значка в соответствии с очередностью добавления вкладок, однако программист может вручную указать номер значка.
MultiLine Располагает закладки в несколько рядов.
OwnerDraw Позволяет программно рисовать закладки в обработчике события OnDrawTab . Если свойство OwnerDraw равно значению False, то закладки имеют стандартный вид и событие OnDrawTab не происходит.
Pages Массив вкладок (страниц). Каждая вкладка является объектом класса TTabSheet . Свойство Pages доступно только из программы.
PageCount Общее количество вкладок. Доступно только из программы.
RaggedRight Если равно значению True, то при включенном режиме MultiLine закладки не выравниваются на ширину компонента.
ScrollOpposite Способ организации рядов закладок. Если равно значению False, то все ряды расположены вместе, например вверху. Если равно значению True, неактивные ряды переносятся на другую сторону компонента, например вниз.
Style Стиль закладок: tsTabs — обычные трехмерные закладки, tsFlatButtons — плоские закладки, tsButtons — закладки в виде кнопок.
TabIndex Номер выбранной закладки (первая закладка имеет номер 0).
TabPosition Местоположение закладок: tpTop — сверху, tpRight — справа, tpLeft — слева, tpBottom — снизу.
TabWidth, TabHeight Ширина и высота закладок. Если эти свойства равны нулю, то размеры закладок подбираются автоматически, исходя из размеров надписей.
OnChange Происходит после смены закладки.
OnChanging Происходит перед сменой закладки.
OnDrawTab Происходит при рисовании закладки на экране. Требует, чтобы свойство OwnerDraw содержало значение True.
OnGetImageIndex Обработчик этого события должен вернуть номер значка для отображаемой закладки.
OnGetSiteInfo Происходит, когда у компонента запрашивается место для стыковки.
Таблица 9.16. Важнейшие свойства и события компонента PageControl

Шаг 3. Первоначально компонент PageControl не содержит ни единой вкладки. Для создания вкладки щелкните правой кнопкой мыши на компоненте и выберите в контекстном меню команду New Page (рисунок 9.52).

Рисунок 9.52. Создание новой вкладки в компоненте PageControl

Будет создана первая вкладка с заголовком TabSheet1 (рисунок 9.53).

Рисунок 9.53. В компоненте PageControl создана первая вкладка

Каждая вкладка в компоненте PageControl представлена объектом класса TTabSheet . Свойства отдельной вкладки устанавливаются в окне свойств. Характерные свойства кратко описаны в таблице 9.17.

Свойство Описание
BorderWidth Ширина внутреннего отступа.
Caption Надпись на закладке.
Highlighted Подсветка закладки цветом.
ImageIndex Номер значка в списке Images компонента PageControl . Значок отображается рядом с названием закладки. Отрицательное значение свойства ImageIndex говорит о том, что для закладки значок не задан.
PageControl Ссылка на компонент PageControl, которому принадлежит вкладка. Доступно только из программы.
PageIndex Номер вкладки в массиве Pages компонента PageControl .
TabIndex Номер вкладки среди видимых вкладок. Если вкладка не видна, то свойство TabIndex равно -1. Свойство доступно только программно и только для чтения.
TabVisible Определяет, видна ли закладка.
OnHide Происходит при переключении на другую вкладку.
OnShow Происходит при активизации вкладки.
Таблица 9.17. Важнейшие свойства компонента TTabSheet

Шаг 4. Перейдите к окну свойств и замените текст закладки, вписав в свойстве Caption значение Mathematics . Действуя аналогично, добавьте вкладки Physics и Chemistry (рисунок 9.54).

Рисунок 9.54. В компоненте PageControl созданы три вкладки

Шаг 5. Ну вот, у нас уже есть три пустых вкладки и можно приступать к наполнению их содержанием. Сначала щелчком мыши активизируйте вкладку Mathematics . Затем поместите на нее группу взаимоисключающих переключателей — компонент RadioGroup . Заголовок группы будет содержать условие вопроса, а текст переключателей — возможные варианты ответа. Вопрос по математике будет из области тригонометрии (рисунок 9.55).

Рисунок 9.55. Содержимое первой вкладки

Шаг 6. Чтобы группа переключателей выглядела так, как на рисунке, подберите ей соответствующие размеры и установите значения следующих свойств:

Caption = The right expression is (правильным является выражение)

Items = sin 50( cos 50(

ItemIndex = 0 (номер варианта принимаемый по умолчанию)

Tag = 1 (номер правильного варианта, считая от нуля)

Свойство Tag не несет смысловой нагрузки в компонентах среды Delphi. Поэтому его можно использовать по своему усмотрению. Помещая в него номер правильного ответа, мы заботимся об упрощении подсчета оценки. Когда пользователь укажет ответ, мы сравним значения свойств ItemIndex и Tag . Ответ будет считаться правильным лишь в том случае, если номера совпадут.

Шаг 7. Билет по математике готов, приступим к подготовке билета по физике. Активизируйте вкладку Physics и поместите на нее компонент RadioGroup . Подберите для него подходящие размеры и установите следующие свойства:

Caption = When the ice in water dissolves then (когда лед в воде тает)

Items = the level of water becomes higher (уровень воды поднимается)

the level of water becomes lower (уровень воды понижается)

the level of water remains unchanged (уровень воды остается неизменным)

ItemIndex = 0 (номер варианта принимаемый по умолчанию)

Tag = 2 (номер правильного варианта, считая от нуля)

Результат должен быть таким, как на рисунке 9.56:

Рисунок 9.56. Содержимое второй вкладки

Шаг 8. Осталось создать билет по химии. Мы надеемся, что после всех предыдущих испытаний это не составит для вас труда. Кратко поясним, что нужно сделать. Активизируйте вкладку Chemistry и поместите на нее компонент RadioGroup . Подберите для него подходящие размеры и установите следующие свойства:

Caption = The right way of mixing acid and water is (чтобы разбавить кислоту, нужно)

Items = to add acid to water (добавить кислоту в воду)

to add water to acid (добавить воду в кислоту)

ItemIndex = 0 (номер варианта принимаемый по умолчанию)

Tag = 0 (номер правильного варианта, считая от нуля)

После всех ваших действий вкладка Chemistry будет выглядеть так, как на рисунке 9.57.

Рисунок 9.57. Содержимое третьей вкладки

Шаг 9. Все вкладки с экзаменационными билетами вроде бы готовы, но как вы считаете, какая из них будет активной при запуске программы? Конечно та, которая осталась активной при проектировании, т.е. вкладка Chemistry . А надо, чтобы первой оказалась вкладка Mathematics . Поэтому активизируйте ее щелчком мыши. Кроме того, установите у формы свойство ActiveControl в значение RadioGroup1 . Компонент, указанный в свойстве ActiveControl первым получает фокус ввода при появлении формы на экране.

Шаг 10. Теперь вас ждет самая ответственная работа — выставление пользователю оценки. Для этого поместите в форму две кнопки (компонент Button ). Первая кнопка предназначена для выдачи результата экзамена, сделайте ее свойства такими:

  • Name = ResultButton
  • Caption = Result
  • Default = True


Вторая кнопка служит для закрытия окна, ее сделайте такой:

  • Name = CloseButton
  • Caption = Close
  • Cancel = True

Рисунок 9.58. Кнопка Result выдает оценку, кнопка Close завершает диалог

Шаг 11. Создайте для кнопок следующие обработчики события OnClick :

Оценка вычисляется элементарно. Сначала предполагается, что она равна нулю (ни одного правильного ответа), а затем она уточняется в соответствии с тем, дал ли пользователь правильный ответ по математике, физике и химии. Под конец вызывается процедура ShowMessage , которая выдает в маленьком окне диалога заключение экзаменатора (рисунок 9.59).

Рисунок 9.59. По щелчку на кнопке Result выставляется оценка

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

Поупражняйтесь с компонентом PageControl , например, измените размеры закладок (свойства TabHeight и TabWidth ), добавьте больше страниц. Когда закладки перестанут умещаться в одной строке, обнаружится, что их можно прокручивать (рисунок 9.60). Кнопки прокрутки появляются автоматически.

Рисунок 9.60. Вкладки могут прокручиваться с помощью кнопок со стрелками

Если это вам не нравится, закладки можно расположить в несколько рядов, установив свойство MultiLine в значение True (рисунок 9.61):

Рисунок 9.61. Вкладки размещены в несколько рядов

А можно ли получить страницы без закладок? Да, для этого в компонентах TTabSheet нужно установить свойство TabVisible в значение False. Заметьте, это свойство не управляет видимостью вкладки, а влияет лишь на ее заголовок — закладку. Переключение между такими страницами становится вашей заботой и осуществляться программно.

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

9.5.2. Закладки без страниц

Для создания многостраничных окон диалога иногда используется еще один компонент — TabControl , который расположен в палитре компонентов по соседству с компонентом PageControl (рисунок 9.62).

Рисунок 9.62. Компонент TabControl

Характерные свойства компонента TabControl описаны в таблице 9.18.

Свойство Описание
Align Способ выравнивания компонента в пределах содержащего компонента.
DockSite Определяет, используется ли компонент TabControl для стыковки других компонентов.
HotTrack Подсвечивает закладку при наведении на нее указателя мыши.
Images Список значков, отображаемых на закладках. Каждая закладка получает значок в соответствии со своим порядковым номером.
MultiLine Располагает закладки в несколько рядов.
MultiSelect Если равно значению True, то пользователь может выбрать сразу несколько закладок, удерживая клавишу Ctrl. Работает только в том случае, если свойство Style содержит значение tsFlatButtons или tsButtons .
OwnerDraw Позволяет программно рисовать закладки в обработчике события OnDrawTab . Если свойство OwnerDraw равно значению False, то закладки имеют стандартный вид и событие OnDrawTab не происходит.
RaggedRight Если равно значению True, то при включенном режиме MultiLine закладки не выравниваются на ширину компонента.
ScrollOpposite Способ организации рядов закладок. Если равно значению False, то все ряды расположены вместе, например вверху. Если равно значению True, неактивные ряды переносятся на другую сторону компонента, например вниз.
Style Стиль закладок: tsTabs — обычные трехмерные закладки, tsFlatButtons — плоские закладки, tsButtons — закладки в виде кнопок.
Tabs Закладки в виде списка строк.
TabIndex Номер выбранной закладки. Если ни одна закладка не выбрана, то значение свойства равно -1.
TabPosition Местоположение закладок: tpTop — сверху, tpRight — справа, tpLeft — слева, tpBottom — снизу.
TabWidth, TabHeight Ширина и высота закладки. Если эти свойства равны нулю, то ширина и высота каждой закладки подбирается автоматически по ширине и высоте содержащегося на ней текста.
OnChange Происходит после смены закладки.
OnChanging Происходит перед сменой закладки.
OnDrawTab Происходит при рисовании закладки на экране. Требует, чтобы свойство OwnerDraw содержало значение True.
OnGetImageIndex Обработчик этого события должен вернуть номер значка для отображаемой закладки.
OnGetSiteInfo Происходит, когда у компонента запрашивается место для стыковки.
Таблица 9.18. Важнейшие свойства и события компонента TabControl

Компонент TabControl — это фактически одна страница с множеством закладок. Компонент применяется в том случае, если страницы имеют одинаковый вид, а их переключение влечет лишь изменение отображаемых данных. А ведь так произошло с нашими экзаменационными билетами — все страницы содержали по одному единственному компоненту RadioGroup .

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

Шаг 12. Удалите из формы ExamForm компонент PageControl и поместите на его место компонент TabControl .

Рисунок 9.63. Компонент TabControl заменил в форме компонент PageControl

Шаг 13. В окне свойств выберите свойство Tabs и щелкните кнопку с многоточием. На экране появится редактор строк.

Рисунок 9.64. Список закладок для компонента TabControl

Шаг 14. Введите названия закладок и щелчком кнопки OK закройте окно. Закладки появятся на экране (рисунок 9.65).

Рисунок 9.65. В компоненте TabControl созданы три закладки

Шаг 15. Теперь внутрь компонента TabControl поместите группу взаимоисключающих переключателей и придайте ей соответствующие размеры и положение (рисунок 9.66).

Рисунок 9.66. Группа переключателей RadioGroup1 заготовлена для экзаменационного вопроса с вариантами ответа

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

На этом визуальная часть проектирования закончена. Все остальное придется программировать вручную.

Шаг 16. Сначала нужно позаботится о хранении содержания вопросов и их ответов, поэтому добавьте следующие описания в текст модуля MainUnit , поместив их перед всеми обработчиками событий:

Шаг 17. Для промежуточного хранения ответов пользователя воспользуемся инициализированной переменной-массивом:

Шаг 18. Значения элементов этого массива должны изменяться, когда пользователь выбирает ответ, поэтому создайте компоненту RadioButton1 обработчик события OnClick :

Шаг 19. При смене закладки должен изменяться вопрос экзаменационного билета и возможные варианты ответов. Для этого создайте в компоненте TabControl1 обработчик события OnChange :

Шаг 20. Все готово? Не совсем. Нужно заполнить компонент RadioGroup1 данными первого билета при появлении формы на экране. Проще всего это можно сделать, вставив вызов метода TabControl1Change в обработчик события создания формы:

Шаг 21. Последний штрих — доработка метода выставления оценки:

А теперь выполните компиляцию и запустите программу. С точки зрения пользователя оно не будет отличаться от программы, созданной ранее с помощью компонента PageControl . Думаем, что получив такой практический опыт, вы сможете сами сделать вывод о том, какой из двух компонентов ( PageControl или TabControl ) и в каких случаях следует использовать.

9.6. Итоги

Нелегкая тропа создания окон диалога пройдена. Вы в этом деле стали настоящим гуру. Не верите? Да, этот так, ибо вы познали:

  • тайны создания монопольных и немонопольных окон диалога,
  • технологию работы с разного рода переключателями;
  • методы ввода текста и чисел со всеми нюансами, включая шаблоны;
  • тайны разработки многостраничных окон диалога с десятками параметров;
  • способ хранения параметров в INI-файлах.

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

Dialogs в Delphi

Компоненты OpenDialog — диалог «Открыть файл» и SaveDialog — диалог «Сохранить файл как. », пожалуй, используются чаще всего, в большинстве приложений. Примеры открываемых ими диалоговых окон приведены на рис. 8.1 и 8.2.

Рис. 8.1
Диалоговое окно открытия файла
Рис. 8.2
Диалоговое окно сохранения файла

Все свойства этих компонентов одинаковы, только их смысл несколько различен для открытия и закрытия файлов. Основное свойство, в котором возвращается в виде строки выбранный пользователем файл, — FileName. Значение этого свойства можно задать и перед обращением к диалогу. Тогда оно появится в диалоге как значение по умолчанию в окне Имя файла (см. рис. 8.1, 8.2).

Типы искомых файлов, появляющиеся в диалоге в выпадающем списке Тип файла (рис. 8.1, 8.2), задаются свойством Filter. В процессе проектирования это свойство проще всего задать с помощью редактора фильтров, который вызывается нажатием кнопки с многоточием около имени этого свойства в Инспекторе Объектов. При этом открывается окно редактора, вид которого представлен на рис. 8.3. В его левой панели Filter Name вы записываете тот текст, который увидит пользователь в выпадающем списке Тип файла диалога. А в правой панели Filter записываются разделенные точками с запятой шаблоны фильтра. В примере рис. 8.3 задано два фильтра: текстовых файлов с расширениями .txt и .doc и любых файлов с шаблоном *.*.

Рис. 8.3
Окно редактора фильтров

После выхода из окна редактирования фильтров заданные вами шаблоны появятся в свойстве Filter в виде строки вида:

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

Свойство FilterIndex определяет номер фильтра, который будет по умолчанию показан пользователю в момент открытия диалога. Например, значение FilterIndex = 1 задает по умолчанию первый фильтр.

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

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

Свойство Title позволяет вам задать заголовок диалогового окна. Если это свойство не задано, окно открывается с заголовком, определенным в системе (например, «Открытие файла» в окне на рис. 8.1). Но вы можете задать и свой заголовок, подсказывающий пользователю ожидаемые действия. Например, «Укажите имя открываемого файла».

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

ofAllowMultiSelect Позволяет пользователю выбирать несколько файлов
ofCreatePrompt В случае, если пользователь написал имя несуществующего файла, появляется замечание и запрос, надо ли создать файл с заданным именем
ofEnableIncludeNotify Разрешает посылать в диалог сообщения
ofEnableSizing Разрешает пользователю изменять размер диалогового окна
ofExtensionDifferent Этот флаг, который можно прочитать после выполнения диалога, показывает, что расширение файла, выбранного пользователем, отличается от DefaultExt
ofFileMustExist В случае, если пользователь написал имя несуществующего файла, появляется сообщение об ошибке
ofHideReadOnly Удаляет из диалога индикатор Открыть только для чтения
ofNoChangeDir После щелчка пользователя на кнопке OK восстанавливает текущий каталог, независимо от того, какой каталог был открыт при поиске файла
ofNoDereferenceLinks Запрещает переназначать клавиши быстрого доступа в диалоговом окне
ofNoLongNames Отображаются только не более 8 символов имени и трех символов расширения
ofNoNetworkButton Убирает из диалогового окна кнопку поиска в сети. Действует только если флаг ofOldStyleDialog включен
ofNoReadOnlyReturn Если пользователь выбрал файл только для чтения, то генерируется сообщение об ошибке
ofNoTestFileCreate Запрещает выбор в сети защищенных файлов и не доступных дисков при сохранении файла
ofNoValidate Не позволяет писать в именах файлов неразрешенные символы, но не мешает выбирать файлы с неразрешенными символами
ofOldStyleDialog Создает диалог выбора файла в старом стиле (см. рис. 8.4)
ofOverwritePrompt В случае, если при сохранении файла пользователь написал имя существующего файла, появляется замечание, что файл с таким именем существует, и запрашивается желание пользователя переписать существующий файл
ofPathMustExist Генерирует сообщение об ошибке, если пользователь указал в имени файла несуществующий каталог
ofReadOnly По умолчанию устанавливает индикатор Открыть только для чтения при открытии диалога
ofShareAware Игнорирует ошибки нарушения условий коллективного доступа и разрешает, несмотря на них, производить выбор файла
ofShowHelp Отображает в диалоговом окне кнопку Справка

По умолчанию все перечисленные опции, кроме ofHideReadOnly, выключены. Но, как видно из их описания, многие из них полезно включить перед вызовом диалогов.

Если вы разрешаете с помощью опции ofAllowMultiSelect множественный выбор файлов, то список выбранных файлов можно прочитать в свойстве Files типа TStrings.

В приведенной таблице даны опции, используемые в 32-разрядных версиях Delphi. В Delphi 1 диалоговое окно имеет вид, представленный на рис. 8.4. Аналогичный вид имеет диалог и в 32-разрядных версиях Delphi при включении опции ofOldStyleDialog. В примере рис. 8.4 диалог открыт с заданным значением свойства Title и заданный текст отображается в заголовке окна. Кроме того, в этом примере выключена опция ofHideReadOnly (в Delphi 1 она выключена по умолчанию), что привело к появлению индикатора « Только чтение ».

Рис. 8.4
Диалог в старом стиле при включенной опции ofOldStyleDialog и выключенной опции ofHideReadOnly

В компонентах диалогов открытия и сохранения файлов предусмотрена возможность обработки ряда событий. Такая обработка может потребоваться, если рассмотренных опций, несмотря на их количество, не хватает, чтобы установить все диктуемые конкретным приложением ограничения на выбор файлов. Событие OnCanClose возникает при нормальном закрытии пользователем диалогового окна после выбора файла. При отказе пользователя от диалога — нажатии кнопки Отмена , клавиши Esc и т.д. событие OnCanClose не наступает. В обработке события OnCanClose вы можете произвести дополнительные проверки выбранного пользователем файла и, если по условиям вашей задачи этот выбор недопустим, вы можете известить об этом пользователя и задать значение false передаваемому в обработчик параметру CanClose. Это не позволит пользователю закрыть диалоговое окно.

Можно также написать обработчики событий OnFolderChange — изменение каталога, OnSelectionChange — изменение имени файла, OnTypeChange — изменение типа файла. В этих обработчиках вы можете предусмотреть какие-то сообщения пользователю.

Теперь приведем примеры использования диалогов OpenDialog и SaveDialog. Пусть ваше приложение включает окно редактирования Memo1, в которое по команде меню Открыть вы хотите загружать текстовый файл, а после каких-то изменений, сделанных пользователем, — сохранять по команде Сохранить текст в том же файле, а по команде Сохранить как. — в файле с другим именем.

Введите на форму компоненты — диалоги OpenDialog и SaveDialog. Предположим, что вы оставили их имена по умолчанию — OpenDialog1 и SaveDialog1. Поскольку после чтения файла вам надо запомнить его имя, чтобы знать под каким именем потом его сохранять, вы можете определить для этого имени переменную, назвав ее, например, FName:

Тогда обработка команды Открыть может сводиться к следующему оператору:

Этот оператор вызывает диалог, проверяет, выбрал ли пользователь файл (если выбрал, то функция Execute возвращает true), после чего имя выбранного файла (OpenDialog1.FileName) сохраняется в переменной FName и файл загружается в текст Memo1 методом LoadFromFile.

Обработка команды Сохранить выполняется оператором

В данном случае нет необходимости обращаться к какому-то диалогу, поскольку имя файла известно: оно хранится в переменной FName.

Обработка команды Сохранить как. выполняется операторами:

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

Мы рассмотрели диалоги открытия и сохранения файлов произвольного типа. Начиная с Delphi 3 в библиотеке имеются специализированные диалоги открытия и закрытия графических файлов: OpenPictureDialog и SavePictureDialog. Диалоговые окна, открываемые этими файлами, приведены на рис. 8.5 и 8.6. От окон, открываемых компонентами OpenDialog и SaveDialog (рис. 8.1, 8.2), они отличаются удобной возможностью просматривать изображения в процессе выбора файла.

Рис. 8.5
Диалоговое окно открытия файла изображения
Рис. 8.6
Диалоговое окно сохранения файла изображения

Свойства компонентов OpenPictureDialog и SavePictureDialog ничем не отличаются от свойств компонентов OpenDialog и SaveDialog. Единственное отличие — заданное значение по умолчанию свойства Filter в OpenPictureDialog и SavePictureDialog. В этих компонентах заданы следующие фильтры:

All (*.jpg; *.jpeg; *.bmp; *.ico; *.emf; *.wmf) *.jpg; *.jpeg; *.bmp; *.ico; *.emf; *.wmf
JPEG Image File (*.jpg) *.jpg
JPEG Image File (*.jpeg) *.jpeg
Bitmaps (*.bmp) *.bmp
Icons (*.ico) *.ico
Enhanced Metafiles (*.emf) *.emf
Metafiles (*.wmf) *.wmf

В этих фильтрах перечислены все типы графических файлов, с которыми может работать диалог. Так что вам остается удалить, если хотите, фильтры тех файлов, с которыми вы не хотите работать, добавить, может быть, фильтр «Все файлы (*.*)» и перевести на русский язык названия типов.

TDelphiBlog

Блог Delphi-программиста. Обзоры инструментов и экспертов для Delphi. Описание JCL, JVCL, cnWizards. Дженерики в Delphi. Дневник разработки Lazy Delphi Builder. Переводы.

Страницы

Motto

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

четверг, 25 декабря 2008 г.

Описание диалогов в JVCL. JvDialogs. Часть 2.

В отличие от диалогов описанных в предыдущем посте, диалоги описанные здесь, выполняют более полезные функции. =)

Диалоги, построенные на Delphi

TJvDesktopAlert и TJvDesktopAlertStack

Компоненты для показа всплывающих окошек.(Popup hint window).

Можно настраивать любые параметры, окошки появляются на заданное время и тают по истечении. При наведении мышки, они перестают пропадать. Есть возможность перетаскивать их мышкой, обрабатывать клики на разных областях, присваивать Popup menu для стрелочки. TJvDesktopAlert отвечает за прорисовку окошка. TJvDesktopAlertStack отвечает за список активных окошек. Единственный минус с которым я столкнулся при использовании этого компонента – это то, что всё работает хорошо до тех пор пока мы не попытаемся уместить на нём больше текста. Советую посмотреть демку: JVCL\examples\JvDesktopAlert.

TJvDSADialog

Компонент для создания собственных диалогов(MessageDlg) с галочкой «Не показывать больше это окно»(Don’t Show Again), а также диалогов закрывающихся по таймеру. Прежде чем его использовать обратите внимание на готовые функции предоставленные в модуле JvDSADialogs.pas. Там полно функций, позволяющих показывать диалог с заданными параметрами. Также там есть функции заменяющие стандартные ShowMessage, MessageDlg, MessageDlgEx.
Этот компонент подробно описан в JVCL Help-е. Также советую посмотреть демку JVCL\Examples\JvDSADialogs\MessageDlgEditor.dpr.

TJvTipOfDay

Диалог “Совет Дня”. Умеет автоматически показывать себя при старте программы(отключаемо), сохранять свои свойства в AppStorage[1]. Хранит советы в Tips:Tstrings. Имеет два вида отображения.

TJvFindReplace

TJvLoginDialog

Диалог запрашивающий имя пользователя и пароль. По умолчанию автоматически запускается при старте программы(свойство Active) и в случае неправильного пароля, не позволяет запуститься программе. Имеет свойства: Caption; Количество попыток ввода пароля; Максимальная длина пароля, умеет сохраняться в AppStorage[1].

TJvProgressDialog

диалог с прогрессбаром.

TJvProgressComponent

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

TJvDualListDialog

TJvBrowseForFolderDialog

Диалог для выбора папки(Browse For Folder). Обёртка вокруг функции SHBrowseForFolder.

Диалоги для выбора цвета

JvColorDialog : TJvColorDialog

JvFullColorDialog : TJvFullColorDialog

JvFullColorCircleDialog : TJvFullColorCircleDialog

Из бесплатных контролов для выбора цвета, хочу упомянуть ещё Color Picker Control от Soft-Gems. Версии для D2009 там пока нет.

Устаревшие диалоги

TJvOpenDialog, TJvSaveDialog – немного расширенные диалоги для загрузки/сохранения файлов. В Висте визуально ничем не отличаются от стандартных TOpenDialog, TSaveDialog.
TJvSelectDirectory – устаревший аналог TJvBrowseForFolderDialog. Надеюсь, что его уберут из следующей версии.

Проблемные диалоги

Диалоги с которыми у меня возникли проблемы. Причины проблем в совокупности этих параметров: Windows Vista 32 bit, Delphi 2009, JVCL 3.36 =) Описанные фичи и баги актуальны для JVCL 3.35, точнее для исходников в репозитории на 24-12-2008.
TJvImageDialog – при тестовом запуске подвесил IDE.
TJvPageSetupDialog, TJvPageSetupTitledDialog, TJvAddHardwareDialog – глючат.

Илон Маск рекомендует:  Получить количество строк в TextArea
Понравилась статья? Поделиться с друзьями:
Кодинг, CSS и SQL