для чего предназначен компонент button
Информационные технологии. 11 класс (Базовый уровень)
§ 3. Проектирование интерфейса оконного приложения с использованием элементов управления
3.1. Основные элементы управления
Элементами управления называются объекты, которые используются для отображения данных или выполнения операций с данными. Действия с элементами управления можно осуществлять с помощью мыши или клавиатуры. Управление различными программами более или менее единообразно, потому что в составе ОС имеется набор элементов управления: типовых кнопок, редактируемых полей, списков выбора, флажков, переключателей и т. д. Все элементы управления собраны в специальные библиотеки компонентов. Среда разработки программ Delphi использует библиотеку VCL (Visual Component Library) — библиотеку визуальных компонентов.
Компоненты библиотеки VCL размещаются на различных страницах палитры компонентов (пример 2.7.). Каждая страница имеет свое название. На страницах Standard (пример 3.1.) и Additional (пример 3.2.) размещены наиболее употребляемые компоненты.
Расположение компонентов по страницам палитры компонентов запоминать необязательно. Можно воспользоваться поиском (пример 3.3.).
Каждому элементу управления в среде Delphi соответствует один или несколько компонентов.
Пример 3.1. Палитра компонентов Standard:
Пример 3. 2. Палитра компонентов Additional:
Пример 3.3. Поиск компонента Button:
Программирование на языке Delphi
Глава 9. Окна диалога
Авторы: А.Н. Вальвачев
К.А. Сурков
Д.А. Сурков
Ю.М. Четырько
Опубликовано: 12.06.2006
Исправлено: 10.12.2016
Версия текста: 1.0
Все мы любим иногда поболтать. Это человеческое свойство передалось программам, и они частенько у вас что-то спрашивают, а вы им что-то отвечаете, иногда невпопад. “Беседа”, правда, идет текстом, а не голосом. Так вот, разговор между программой и пользователем называется диалогом. Организация диалога — важнейшая часть любой программы. Ваша прямая обязанность сделать этот диалог приятным. По форме диалог прост — появляется окно с некоторым сообщением, полем для ввода вашего ответа и кнопкой OK. Вы внимательно читаете сообщение, набираете строку-ответ и нажимаете кнопку OK. Вот и все. Создатели среды Delphi предусмотрели все возможные типы диалогов и создали для вас ряд великолепных “домашних заготовок”.
9.1. Понятие окна диалога
В основе диалога между пользователем и компьютером лежит окно диалога (dialog box) — форма, содержащая компоненты для ввода данных: кнопки, текстовые поля, флажки, переключатели, списки и др. С помощью этих компонентов пользователь просматривает и вводит данные. В среде Delphi окно диалога создается на основе обычной формы.
Окна диалога могут работать в одном из двух режимов, монопольном (иногда говорят модальном, от англ. modal) и немонопольном (немодальном, от англ. modeless).
Монопольное окно диалога не дает пользователю возможности переключиться на другие окна программы до тех пор, пока работа с ним не будет завершена. Сразу заметим, что это не мешает пользователю переключаться на другие программы, например, с помощью панели задач Windows или нажатием комбинации клавиш Alt+Tab. Большинство окон диалога работает в монопольном режиме.
Немонопольные окна диалога предоставляют пользователю свободу выбора, позволяя вводить данные сразу в нескольких окнах.
9.2. Окно «About»
9.2.1. Подготовка формы
Шаг 1. Запустите среду Delphi и откройте проект PictureViewer. Добавьте в главное меню пункт Help (программный идентификатор HelpMenuItem ) с командой About. (программный идентификатор AboutMenuItem ). По команде About. (рисунок 9.1) будет вызываться окно диалога About, которое мы дальше разработаем.

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

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

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

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

Рисунок 9.5. Компонент BitBtn
Заметим, что кнопка, содержащая значок, принимает наиболее красивый вид, если свойство Margin равно значению 4, а свойство Spacing равно значению 1.
| Значение | Вид кнопки | Результат установки значения | Пояснения |
|---|---|---|---|
| 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 | Любой | Любой | Кнопка для ваших собственных целей. |
Например, если вам нужна кнопка OK, установите свойство Kind в значение bkOK. В результате на кнопке появится зеленая «галочка» и текст «OK», свойство Default получит значение True и свойство ModalResult получит значение mrOK.
9.2.4. Украшение окна диалога рисунком
Хорошее приложение должно быть не только функционально, но и эстетично. Как говорится, хорошее блюдо должно быть красиво подано. Это относится и к нашему замечательному приложению, и конечно к его окну About. А что может лучше украсить окно About, чем яркий, запоминающийся рисунок.
Шаг 7. Установите свойство AutoSize в значение True, чтобы компонент автоматически подгонял свои размеры под размеры рисунка, и установите свойство Transparent в значение True, чтобы рисунок отображался с прозрачным фоном.

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

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

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

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

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

Рисунок 9.11. Компонент Bevel в форме
9.2.7. Рельефная панель

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

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

Рисунок 9.14. Компоненты Image1, Label1 и Label2 переносятся на панель Panel1
Теперь рельефная рамка заменена рельефной панелью и при ее перемещении перемещаются все надписи и рисунок (рисунок 9.15).

Рисунок 9.15. Компоненты Image1, Label1 и Label2 — теперь на панели Panel1
Будьте аккуратны при удалении панели! Вместе с ней всегда удаляются внутренние компоненты.
9.2.8. Выполнение диалога
Визуальное проектирование окна About закончено, осталось обеспечить его вызов при выборе пользователем команды Help | About. главного меню. Для этого нужно сделать следующее:

Рисунок 9.16. С помощью окна Use Unit модуль About подключается в модуле Main
Ее можно было бы набрать и вручную, но мы решили продемонстрировать вам еще одну возможность визуальной среды программирования.
Шаг 15. Выполните теперь второй пункт плана — создайте обработчик события OnExecute для команды AboutAction компонента ActionList:
Шаг 16. Выполните компиляцию и запустите программу, затем проверьте работу новоиспеченного окна диалога, выполнив команду меню Help | About. (рисунок 9.17).

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

Рисунок 9.18. Форма AboutForm исключена из списка автоматически создаваемых форм
В результате среда Delphi удалит приведенный выше оператор из главного файла программы, переложив заботу о создании формы на ваши плечи.
Ну вот, теперь ресурс оперативной памяти используется более рационально. Кстати, обратите внимание, как обеспечивается защита объекта AboutForm от исключительных ситуаций, которые могут возникнуть в период его работы (это конечно маловероятно, но чего в этой жизни не бывает!). Если объект AboutForm успешно создается, то благодаря оператору try. finally. end он всегда корректно освобождается, даже в случае возникновения исключительной ситуации.
9.3. Компоненты для ввода данных
Вы получили первое представление об окнах диалога, научились создавать и выполнять простейшие из них. Но вы еще не знаете, как организовать диалог для получения данных от пользователя. Эта задача решается с помощью компонентов для ввода данных, к изучению которых мы сейчас приступаем.
Сохраните модуль формы под именем MainUnit.pas, а проект — под именем Alarms.dpr.

Рисунок 9.19. Кнопки для управления списком будильников
Шаг 3. Установите в компоненте NewButton свойство Default в значение True, чтобы кнопка срабатывала при нажатии клавиши Enter.
Шаг 4. Для компонента CloseButton создайте следующий обработчик события OnClick :
Теперь сохраните модуль формы под именем AlarmDetailsUnit.pas.
Шаг 6. Добавьте в форму кнопки OK и Cancel и установите их свойства так, как показано на рисунке 9.20.

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

Рисунок 9.21. Эскиз окна для установки параметров будильника
9.3.1. Фокус ввода
Во время работы программы только один из компонентов принимает клавиатурный ввод в текущий момент времени. Принято говорить, что такой компонент обладает фокусом ввода или просто — активен. Передача фокуса ввода осуществляется щелчками компонентов или нажатием клавиш Tab и Shift+Tab на клавиатуре. При использовании клавиатуры фокус ввода передается последовательно от одного компонента другому, причем клавиша Tab обеспечивает перебор элементов в прямом порядке, а сочетание клавиш Shift+Tab – в обратном.
Если нужно исключить компонент из очереди на фокус ввода, установите свойство TabStop в значение False. Однако в этом случае фокус ввода можно насильно передать компоненту с помощью мыши или «горячей» клавиши.

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

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

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

Рисунок 9.25. Переключатель Play Sound представлен компонентом CheckBox
Шаг 11. Чтобы при первом появлении окна диалога, режим Play Sound был включен, установите в компоненте SoundCheck свойство Checked в значение True.
9.3.3. Взаимоисключающие переключатели
Взаимоисключающие переключатели (radio buttons) служат для установки взаимоисключающих параметров. Они обычно объединяются в группы и позволяют пользователю выбрать одно значение из фиксированного (причем немногочисленного) набора вариантов. При включении одного такого переключателя остальные переключатели этой же группы выключаются.

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

Рисунок 9.27. Переключатели Everyday, Weekly и Date представлены компонентами RadioButton
Внимание! Выбор положения переключателя осуществляется с помощью клавиш со стрелками.
Шаг 14. Разумеется, компоненты WeeklyComboBox и DatePicker первоначально должны быть недоступны. Поэтому, удерживая клавишу Shift, выберите названную группу компонентов и установите свойство Enabled в значение False.
Теперь запустите программу и проверьте правильность ее работы.
9.3.4. Группа взаимоисключающих переключателей

Рисунок 9.28. Компонент RadioGroup
Его характерные свойства кратко описаны в таблице 9.8.

Рисунок 9.29. Четырехпозиционный переключатель представлен компонентом RadioGroup
9.3.5. Панель группы компонентов
Компонент GroupBox служит для группировки компонентов, он расположен в палитре компонентов на вкладке Standard (рисунок 9.30).

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

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

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

Рисунок 9.33. Компонент Edit используется для ввода текстового сообщения будильника
Выполните компиляцию программы и проверьте ее работу.
Прежде чем продолжить обсуждение примера 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.35. Окно для ввода многострочного текста, отображаемого компонентом Memo
В нашем приложении Alarms компонент Memo не нужен, но вам он безусловно пригодится в других программах.
9.3.7. Редактор с шаблоном

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

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

Рисунок 9.38. Компонент MaskEdit настроен для ввода времени
Шаг 18. Теперь давайте сделаем так, чтобы при появлении окна диалога поле ввода TimeMaskEdit не было пустым, а содержало текущее время. Для этого создайте у формы обработчик события OnCreate :
Готово. Запустите программу и убедитесь, что она работает, как вы того ожидаете.
9.3.8. Раскрывающийся список
Раскрывающийся список (combo box) позволяет пользователю выбрать значение из большого множества альтернатив. Он представляет собой поле ввода, к которому прикреплен раскрывающийся список значений. Редактор служит для ввода нового значения, а список — для выбора существующего значения. Количество элементов в списке может быть произвольным, причем элементы можно динамически добавлять, удалять, заменять и т.д. Элементами списка обычно служат текстовые строки, но могут быть и графические рисунки (в последнем случае их редактирование невозможно).

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

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

Рисунок 9.41. В этом окне вводятся элементы списка — дни недели
Щелкните кнопку OK — список значений компонента WeeklyComboBox задан.
Реализация метода основана на том, что компонент DatePicker при создании формы сразу содержит текущую дату.
На этом с визуальной частью диалога Alarm Details покончено. Правда, мы ничего не сказали о компоненте DateTimePicker (рисунок 9.42).

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

Рисунок 9.43. Тестирование окна Alarm Details
Все компоненты работают правильно. Можете поздравить себя с очередным достижением. Вы создали важную часть приложения Alarms — окно диалога, а заодно разобрались с множеством новых компонентов.
9.3.9. Установка и получение данных
Окно диалога есть, но пользы от него пока нет. Все дело в том, что мы научились устанавливать параметры будильника, но не научились их принимать и хранить.
Шаг 22. Для хранения параметров будильника нам нужна новая структура данных, очевидно класс объектов. Немного поразмыслив, приходим к следующему описанию:
Поясним назначение полей и методов. Поле MsgText предназначено для хранения текстового сообщения. В поле DateTime записывается время и дата сигнала. Значение поля PlaySound показывает, требуется ли звуковое сопровождение сообщения. Поле Recurring определяет периодичность работы будильника и принимает следующие значения:
В разделе implementation наберите программный текст методов:
9.3.10. Список
Компонент ListBox отображает список элементов, которые пользователь может просматривать и выбирать, но не может непосредственно модифицировать. По умолчанию элементами списка являются строки, но могут быть и графические объекты. Элементы могут располагаться в одну или несколько колонок и автоматически сортироваться. При необходимости обеспечивается возможность прокрутки списка. Компонент ListBox находится в палитре компонентов на вкладке Standard (рисунок 9.44).

Рисунок 9.44. Компонент ListBox
Его характерные свойства собраны в таблице 9.14.

Рисунок 9.45. Компонент ListBox применяется для организации списка будильников
Шаг 26. В кнопке New. обработчик события OnClick уже существует, но его необходимо доработать:
Шаг 27. Создайте в компоненте EditButton обработчик события OnClick :
Шаг 28. Осталось создать обработчик события OnClick в компоненте DeleteButton :
Метод DeleteButtonClick удаляет объект будильника и соответствующую ему строку в списке.
В объекте Application происходит событие OnIdle в период простоя программы, например во время ожидания пользовательского ввода. Благодаря этому событию программа может выполнять некоторую фоновую работу, которая в нашем случае заключается в управлении состоянием кнопок.
Для создания обработчика события OnIdle объекта Application воспользуемся уже знакомым вам компонентом ApplicationEvents (см. главу 8).
В передаваемом по ссылке параметре Done метод возвращает результат своей работы. Значение True показывает, что метод нужно вызывать не постоянно в течении простоя приложения, а только по одному разу в начале каждого периода простоя.
А сейчас выполните компиляцию, запустите программу и тщательно протестируйте работу главной формы (рисунок 9.46).

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

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

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

Рисунок 9.49. Когда будильник срабатывает, звучит сигнал и на экран выдается сообщение
Выполните компиляцию и запустите программу, чтобы проверить работу всех элементов программы. Ура! Все работает, терпение и упорство вознаграждены.
9.4.2. Файлы настроек
Программа Alarms имеет один существенный недостаток: после его завершения все установленные будильники теряются, так что при следующем запуске программы их приходится создавать снова. Для решения этой проблемы необходимо, чтобы между сеансами работы программы будильники хранились в конфигурационном файле на диске.
Сохранение и восстановление конфигурации осуществляется в Windows с помощью так называемых файлов настроек. Файл настроек (initialization file) — это текстовый файл, состоящий из секций. Секция начинается с имени, заключенного в квадратные скобки. В каждой секции содержатся определения некоторых связанных по смыслу параметров, представленные в виде пар Имя=Значение. Примером файла настроек может служить файл настроек проекта в системе Delphi. В нашем проекте это файл Alarms.dof.
Структуру файла настроек для программы Alarms выберем так, чтобы каждому будильнику соответствовала отдельная секция. Число секций, т.е. будильников, будем хранить в параметре AlarmCount секции Global Options. Вот как могло бы выглядеть содержимое файла:
Если в момент записи значения оказывается, что заданные секция и (или) идентификатор отсутствуют, они создаются.
Метод LoadFromIniFile предназначен для чтения из INI-файла полей объекта, а метод SaveToIniFile — для записи в INI-файл полей объекта. Секция INI-файла, с которой работают эти методы, передается в параметре Section.
Шаг 34. Наберите программный код методов в разделе implementation :
9.5. Многостраничные окна диалога
9.5.1. Страницы с закладками
В сложных компьютерных системах предусмотрена настройка десятков различных параметров, которые пользователь просто обязан установить. Это означает либо перегруженность диалоговых окон, либо слишком большое их количество. Решение этой проблемы заключается в организации многостраничных окон диалога. Они создаются с помощью компонента, который изображается в виде множества снабженных закладками страниц, называемых вкладками (рисунок 9.50):

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

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

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

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

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

Рисунок 9.55. Содержимое первой вкладки
Шаг 6. Чтобы группа переключателей выглядела так, как на рисунке, подберите ей соответствующие размеры и установите значения следующих свойств:
Caption = The right expression is (правильным является выражение)
Items = sin 50( cos 50(
ItemIndex = 0 (номер варианта принимаемый по умолчанию)
Tag = 1 (номер правильного варианта, считая от нуля)
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. Содержимое второй вкладки
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. Содержимое третьей вкладки
Шаг 10. Теперь вас ждет самая ответственная работа — выставление пользователю оценки. Для этого поместите в форму две кнопки (компонент Button ). Первая кнопка предназначена для выдачи результата экзамена, сделайте ее свойства такими:
Вторая кнопка служит для закрытия окна, ее сделайте такой:

Рисунок 9.58. Кнопка Result выдает оценку, кнопка Close завершает диалог
Шаг 11. Создайте для кнопок следующие обработчики события OnClick :

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

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

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

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

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

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

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

Рисунок 9.66. Группа переключателей RadioGroup1 заготовлена для экзаменационного вопроса с вариантами ответа
Единственная группа взаимоисключающих переключателей будет поочередно играть роль билета по математике, по физике и по химии в зависимости от выбранной закладки.
На этом визуальная часть проектирования закончена. Все остальное придется программировать вручную.
Шаг 17. Для промежуточного хранения ответов пользователя воспользуемся инициализированной переменной-массивом:
Шаг 18. Значения элементов этого массива должны изменяться, когда пользователь выбирает ответ, поэтому создайте компоненту RadioButton1 обработчик события OnClick :
Шаг 19. При смене закладки должен изменяться вопрос экзаменационного билета и возможные варианты ответов. Для этого создайте в компоненте TabControl1 обработчик события OnChange :
Шаг 20. Все готово? Не совсем. Нужно заполнить компонент RadioGroup1 данными первого билета при появлении формы на экране. Проще всего это можно сделать, вставив вызов метода TabControl1Change в обработчик события создания формы:
Шаг 21. Последний штрих — доработка метода выставления оценки:
9.6. Итоги
Нелегкая тропа создания окон диалога пройдена. Вы в этом деле стали настоящим гуру. Не верите? Да, этот так, ибо вы познали:
Напоследок позволим себе дать два совета: не заставляйте программу болтать лишнее и не загромождайте экран сложными окнами диалога без особой необходимости. Помните, что хороший пользовательский интерфейс должен быть простым.










