Компоненты GroupBox и CheckBox
GroupBox во многом похож на обычную панель. Он предназначен для группировки схожих по смыслу компонентов. Текст из свойства Caption выходит не посреди панели, а вверху, создавая таким образом заглавие этой панели. При перемещении GroupBox, будут перемещаться и все компоненты, расположенные на нем.
Создайте новое приложение. Мы сделаем полезную утилиту, меняющую вид формы в зависимости от настроек. На форму установите компонент GroupBox, присвоив его свойствам Left и Top значение 6, чтобы прижать его к верхнему левому краю окна. В свойствеCaption этого компонента напишите текст "BorderIcons". Поскольку обрамление компонента вплотную подходит к тексту – заголовку, с дизайнерской точки зрения будет нелишним добавить пару пробелов перед текстом, и столько же после него.
Мы уже знаем, что BorderIcons – это свойство формы, программирующее ее внешний вид. Это свойство имеет 4 значения, каждое из которых можно включить, либо выключить. Таким образом, нам нужно 4 классических "флажка", в которые можно будет поставить "галочку" или убрать ее. Роль таких флажков выполняет компонент CheckBox. Установите 4 CheckBox прямо на панель GroupBox, один над другим:
Рис. 7.1. Внешний вид приложения
Измените свойство Caption этих компонентов, написав там, соответственно, "biSystemMenu", "biMinimize", "biMaximize" и "biHelp". Свойство Checked компонента CheckBox показывает включен ли компонент, другими словами, установлена ли в нем "галочка". У формы по умолчанию первые три значения включены, также сделаем и здесь – у первых трех компонентов CheckBox установите свойство Checked в True.
Компонент RadioGroup
Этот компонент также имеет вид панели и предназначен для группировки так называемых радиокнопок. Включенной может быть лишь одна такая радиокнопка. На рисунке 7.1 в правой части формы вы видите такую панель с установленными радиокнопками. Добавьте компонент RadioGroup на форму, в свойстве Caption установите текст "BorderStyle", не забывая про пробелы до и после текста. Устанавливать на этой панели радиокнопки значительно легче, чем кнопки CheckBox. Выделите эту панель и дважды щелкните по ее свойству Items. Откроется редактор текста, такой же, как у Memo. В этом редакторе нужно написать названия кнопок, каждую кнопку обязательно нужно писать на отдельной строке. Напишите следующие кнопки:
bsSizeable
bsDialog
bsNone
bsSingle
bsSizeToolWin
bsToolWindow
Как только вы нажмете "ОК" и закроете редактор, на панели RadioGroup появятся описанные кнопки. Ни одна из них не имеет включенного вида. Мы уже знаем, что можно включить только одну такую кнопку из списка. Компонент RadioGroup имеет свойствоItemIndex, которое указывает, какая кнопка в данный момент включена. По умолчанию, ItemIndex равен -1. Поскольку нумерация кнопок начинается с нуля, значение -1 означает, что ни одна кнопка не включена. Установите значение 0, включив тем самым первую кнопку (на форме одноименное свойство включено по умолчанию).
Ниже установите кнопку, написав на ней слово "Применить". Все, с дизайном окончено, переходим к программированию кнопки. Если вы еще не сохранили проект в новую папку, сделайте это сейчас. Свойству Name формы, как обычно, дайте имя fMain, модулю – просто Main, всему проекту в целом – FormViewer.
Вернемся к кнопке. Щелкните дважды по ней, создав процедуру обработки нажатия кнопки.
Процедура имеет следующий вид:
procedure TfMain.Button1Click(Sender: TObject);
begin
//обрабатываем компонент BorderIcons
if CheckBox1.Checked then fMain.BorderIcons := fMain.BorderIcons + [biSystemMenu]
else fMain.BorderIcons := fMain.BorderIcons - [biSystemMenu];
if CheckBox2.Checked then fMain.BorderIcons := fMain.BorderIcons + [biMinimize]
else fMain.BorderIcons := fMain.BorderIcons - [biMinimize];
if CheckBox3.Checked then fMain.BorderIcons := fMain.BorderIcons + [biMaximize]
else fMain.BorderIcons := fMain.BorderIcons - [biMaximize];
if CheckBox4.Checked then fMain.BorderIcons := fMain.BorderIcons + [biHelp]
else fMain.BorderIcons := fMain.BorderIcons - [biHelp];
//обрабатываем компонент BorderStyle
case RadioGroup1.ItemIndex of
0 : fMain.BorderStyle := bsSizeable;
1 : fMain.BorderStyle := bsDialog;
2 : fMain.BorderStyle := bsNone;
3 : fMain.BorderStyle := bsSingle;
4 : fMain.BorderStyle := bsSizeToolWin;
5 : fMain.BorderStyle := bsToolWindow;
end; //case
end;
Разберемся с кодом. Вначале мы обрабатываем первый флажок CheckBox:
if CheckBox1.Checked then fMain.BorderIcons := fMain.BorderIcons + [biSystemMenu]
else fMain.BorderIcons := fMain.BorderIcons - [biSystemMenu];
Если этот флажок включен, его свойство Checked вернет Истину, и тогда к свойству формы BorderIcons будет добавлена константа [biSystemMenu]. О константах, в том числе и встроенных, мы будем говорить позднее. Пока что важно одно – если мы прибавляем эту константу, то включаем это значение в свойство BorderIcons.
Пример взят из встроенного справочника Delphi. Поставьте мигающий курсор внутри слова BorderIcons и нажмите <Ctrl + F1>. Выйдет контекстный справочник с этой командой. Если вам будет предложено выбрать между CLX и VCL, выбирайте последнюю (Visual Components Library – Библиотека визуальных компонентов). Далее щелкните по ссылке "Delphi example" (Пример для Delphi). В показанном в справке примере отключается кнопка "Развернуть окно".
Таким же образом, мы обрабатываем остальные три компонента CheckBox.
Далее, идет обработка панели RadioGroup. Поскольку только одна кнопка может быть включена, то свойство ItemIndex этой панели может иметь только 6 значений, по количеству кнопок: от 0 до 5. Здесь удобней всего использовать конструкцию case. В зависимости от значения ItemIndex мы присваиваем одноименное включенной кнопке значение свойству BorderStyle формы. Вот и все.
Сохраните пример, скомпилируйте и посмотрите, как работает программа. В зависимости от выбранных значений после нажатия кнопки "Применить" меняется внешний вид формы. В некоторых случаях ее размеры можно менять, раздвигая мышью, в некоторых – нет. В случае, если BorderStyle равен значению bsNone, пропадает и оборка окна, и верхняя системная строка формы. Поэкспериментируйте. Эта утилита может оказаться полезной в дальнейшем, если вы желаете заранее посмотреть, какие настройки выбрать, чтобы окно вашей программы выглядело именно так. Например, чтобы нельзя было менять его размеры, чтобы отсутствовали кнопки "Свернуть" и "Развернуть" и т.п.
Лекция 8. Меню
Здесь вы познакомитесь с созданием главного и всплывающего (контекстного) меню, познакомитесь с очень полезными свойствами компонентов Enabled и Visible. В процессе изучения улучшите предыдущий проект редактора текстов.
Свойства Enabled и Visible
Эти свойства присутствуют практически у всех визуальных компонентов, и позволяют использовать интересные приемы программирования.
Откройте проект с редактором текста из прошлой лекции. У вас там есть три кнопки – "Сохранить", "Загрузить" и "Очистить". Давайте предположим, что пользователь набрал какой-то важный текст и сохранил его. На следующий день он снова загрузил ваш редактор, но по ошибке вместо кнопки "Загрузить" он нажал кнопку "Сохранить". Что произойдет? Никакого текста в данный момент компонент Memo не содержит. Если будет выполнена команда
Memo1.Lines.SaveToFile('MyFile.txt');
то наш файл перезапишется – важный текст будет стерт, а взамен ничего не запишется, так как текста нет. Пользователь, совершив небольшую ошибку, потеряет свою работу.
Конечно, виноват пользователь – он нажал не ту кнопку. Но в большей степени здесь виноват программист, что не предусмотрел такого развития событий, и не сделал для своей программы элементарной защиты от ошибок пользователя. Исправим ошибку.
Свойство Enabled отвечает за доступность компонентов. Это свойство имеет логический тип, и может быть либо True, либо False. Выделите кнопку с надписью "Сохранить", найдите ее свойство Enabled и вместо установленного по умолчанию значения True, выберите значение False. На форме не произошло видимых изменений, мы не сможем их увидеть в режиме разработки программы. Однако сохраните проект, скомпилируйте командой Run и посмотрите на результат – кнопка "Сохранить" видна на форме, но ее надпись выходит серым, неактивным цветом, а на кнопку невозможно нажать. Теперь у пользователя нет возможности нажать на эту кнопку, значит, он не совершит такой ошибки.
Но это только полдела, надо все-таки в процессе работы программы ему эту возможность вернуть, иначе как же он сможет сохранить текст?
В лекции 6 мы обсуждали событие OnChange, которое происходит всякий раз, когда компонент изменяется. Этим мы и воспользуемся. Выделите компонент Memo, в Инспекторе объектов перейдите на вкладку Events (События) и найдите там событие OnChange. Дважды щелкните по нему, чтобы сгенерировать процедуру – обработчик этого события. В этой процедуре запишем всего только одну строку:
Button1.Enabled := True;
Таким образом, при изменении компонента Memo (пользователь изменил текст), мы делаем доступной кнопку "Сохранить". Теперь пользователь может сохранить свои изменения.
Подумаем теперь вот о чем: когда пользователь сохранил текст, следует ли оставлять кнопку "Сохранить" доступной? Очевидно, нет, если у текста не произошли изменения. Поэтому щелкайте дважды по кнопке "Сохранить", и после строки, где текст сохраняется, добавьте строку
Button1.Enabled := False;
Сразу, как только текст будет сохранен, кнопка "Сохранить" снова станет недоступной, пока пользователь не произведет очередных изменений в тексте.
Также сделайте недоступной эту кнопку после того, как пользователь нажмет кнопку "Очистка", эта кнопка очищает набранный текст, что само по себе заставляет работать событие OnChange компонента Memo, однако сохранять пустоту смысла нет.
Свойство Visible компонентов работает практически также, как свойство Enabled, только вместо того, чтобы делать компонент недоступным, оно делает его невидимым. Visible также имеет логический тип, и может быть либо True (компонент видим), либо False(невидим). Самостоятельно измените все приведенные выше рекомендации, использовав вместо свойства Enabled свойство Visible. Посмотрите на результат. Скрывать или отключать можно не только кнопки, но и вообще все видимые компоненты – редактор Memo, поле Edit, надпись Label. Даже у формы есть эти свойства, поэтому при некоторой фантазии вы можете добиваться вполне профессиональных эффектов.
Главное меню
Любая более-менее серьезная программа имеет собственное меню. Пришла пора познакомиться с этим компонентом. Для примера снова загрузим наш редактор текстов. Выделите все кнопки на форме и удалите их. Также удалите и панель, на которой эти кнопки были. Затем нам потребуется удалить все процедуры обработки этих кнопок, но тут нужно проявить осторожность – нельзя просто взять, и удалить процедуру. Каждая сгенерированная процедура прописана в коде и выше. Чтобы без ошибок удалить все ненужные последние процедуры, следует просто удалить из них тот код, который мы писали сами, оставив "пустую" процедуру – имя процедуры и строчки begin.. end :
Увеличить изображение
Рис. 8.1. Удаление ненужных процедур
После того, как вы сохраните проект, все пустые процедуры будут удалены автоматически. Это касается последних процедур – если после такой пустой процедуры будет присутствовать действующая процедура или функция, они обе останутся в коде.
Таким образом, у вас должна получиться форма, на которой расположен только компонент Memo, и больше ничего. В редакторе кода не должно остаться ни одной процедуры. В общем, только заготовка программы.
Выделите компонент Memo, и убедитесь, что в его свойстве Align установлено значение alClient, то есть, Memo растянуто на всю форму.
На вкладке Standard найдите компонент MainMenu (главное меню), и установите его на любое место формы, прямо на компонент Memo. Компонент MainMenu не визуальный, то есть, пользователь все равно не будет его видеть.
Будем создавать меню. Дважды щелкните по MainMenu, чтобы вызвать редактор меню. Когда редактор откроется, вы увидите, что первый пункт меню выделен синим цветом. Пусть выделение остается, перейдите на свойство Caption и введите текст "Файл". Нажав <Enter>, вы сформируете в меню команду "Файл", а выделение переместится направо, к следующей команде. Другой пункт меню мы пока делать не будем, щелкните мышью немного ниже команды "Файл", чтобы выделить пункт ниже. Получается, что мы сделали пункт меню "Файл", и сейчас делаем подменю этого пункта. Нам потребуются следующие команды:
- "Сохранить"
- "Загрузить"
- "Очистить"
- "-"
- "Выход"
Рис. 8.2. Внешний вид редактора главного меню
Предпоследняя команда, знак "-" (минус), формирует в меню разделительную полосу. Как только вы закроете редактор меню, строка с главным меню сейчас же появится над компонентом Memo. Щелкните один раз по слову "Файл", и откроется подменю. Щелкните по команде "Сохранить", и будет создана процедура обработки этой команды. Команда "Сохранить" по-прежнему выглядит, как
Memo1.Lines.SaveToFile('MyFile.txt');
Все остальные команды введите аналогичным образом. Команда "Выход" выглядит так:
Close; //выход из программы
Всплывающее меню
Всплывающее меню вызывается, когда пользователь щелкает правой кнопкой мыши по объекту – форме или какому либо другому компоненту. Найдите на вкладке Standard компонент PopupMenu (всплывающее меню), и также установите его поверх компонента Memo. Редактор этого меню вызывается таким же образом, как и редактор главного меню. Во всплывающем меню, однако, только одна ветка меню, где команды указываются одна под другой. Другими словами, нет возможности делать пункты меню (Файл, Правка, Вид и т.д.) и подпункты (Файл -> Создать, Файл -> Загрузить и т.д.).
Создайте следующие команды:
- "Сохранить"
- "Загрузить"
- "Очистить"
- "-"
- "Выход"
Чтобы создать обработчик события для команды, нужно дважды щелкнуть по ней в редакторе всплывающего меню. Сами команды точно такие же, как и у главного меню. Напишите код для всех указанных пунктов всплывающего меню.
Примечание: в дальнейших лекциях мы будем изучать компонент ActionList, который позволяет использовать одну команду для одноименных пунктов главного и всплывающего меню, а также панели инструментов. Пока что нам придется дублировать команды главного и всплывающего меню.
Теперь всплывающее меню нужно привязать к форме, само по себе оно работать не будет. Для этого нам нужно выделить форму, что является непростой задачей – компонент Memo растянут на все окно, и нет возможности щелкнуть по свободному месту формы. Форму проще всего выделить в окне Дерева объектов (Object TreeView). Если у вас в данный момент это окно закрыто, открыть его можно командой меню View-> Object TreeView , или горячими клавишами <Shift+Alt+F11>. В этом окне легко можно выделить любой компонент, в том числе и форму.
Итак, выделите форму. В окне Инспектора объектов отразятся свойства формы. Нас интересует свойство PopupMenu. Оно имеет вид списка, в котором мы можем выбрать то или иное всплывающее меню. Поскольку такое меню у нас только одно, его и выбираем. Теперь можно сохранить проект, скомпилировать его и запустить на выполнение. Щелчок правой кнопкой на любом месте формы приведет к вызову всплывающего меню.
Всплывающее меню также называют контекстными – дело в том, что многие компоненты имеют свойство PopupMenu – редактор Memo, панели и многие другие компоненты. Можно установить несколько всплывающих меню с разными командами, и привязать к различным компонентам свои собственные PopupMenu. Тогда щелчок правой кнопкой над одним компонентом приведет к вызову одного всплывающего меню, над другим – другого.
Модальные окна
Модальным называется дочернее окно, которое не дает главной форме работать, пока не закончена работа этого модального окна.
До сих пор мы делали проекты только с одной формой. Настало время изучить многооконные проекты. Воспользуемся предыдущим примером – редактором текстов. Откройте этот проект, если он закрыт.
Чтобы создать новое окно, выберите команду "File – New – Form".
В свойстве Caption новой формы напишите "О программе", форму назовите fAbout и сохраните проект. Модуль новой формы, соответственно, назовите About.
На форму установите компонент Label, напишите в его свойстве Caption "Программа: MyNotebook v 1.0"
Ниже установите еще один Label. Свойство AutoSize (автоматическое изменение размера) поставьте в False, а свойство WordWrap (перенос слов на другую строку) – в True. Здесь напишите такой текст:
Программа предназначена для простого редактирования текстов. Программа позволяет сохранять текст в файл, и считывать его из файла. Файл создается там же, откуда запущена программа, и имеет имя MyFile.txt.
Ниже установим еще один Label. Пишем в нем: "Автор: такой-то", можете указать свои собственные фамилию, имя и отчество. Будет красиво, если текст этого компонента выйдет посередине. Чтобы добиться этого, свойство AutoSize (автоматическое изменение размера) установите в False, свойство Aligment (выравнивание текста) в taCenter.
Ниже устанавливаем кнопку. Пишем на ней "ОК" и создаем обработчик кнопки для выхода из формы.
Инструкция Close главной формы закрывает всю программу, а инструкция Close модального окна закрывает только это окно.
Рис. 8.3. Внешний вид формы "О программе"
Можете "поиграть" со свойствами Font и Color компонентов, чтобы форма выглядела красивей.
Подобные окна не имеют кнопок "Свернуть" и "Развернуть", поэтому в свойстве BorderStyle формы fAbout выберите значение bsDialog. А в свойстве Position (Позиция формы при ее открытии) выберите poMainFormCenter, чтобы форма появлялась по центру главного окна. Обратите внимание на последнее свойство. Обычно для главных окон программы это свойство устанавливают в poDesktopCenter, чтобы форма появлялась по центру рабочего стола, запомните это на будущее.
Теперь, чтобы можно было вызывать это окно модально, нужно "привязать" его к главной форме. Сейчас в редакторе кодов имеется две вкладки – Main и About, это модули главной формы и формы "О программе". Перейдите на вкладку главного окна и нажмите <F12>, чтобы вызвать это окно. Выберите команду "File – Use Unit". Откроется окно, где мы увидим нашу модальную форму. Выделите ее и нажмите OK. Теперь, если Вы посмотрите код главной формы, под разделом implementation Вы увидите такую картину:
implementation
uses About;
Delphi вставила инструкцию, при которой главная форма использует все, что описано в коде модального окна. Можно было набрать все это вручную, однако во избежание ошибок рекомендуется пользоваться командой "File – Use Unit". Тогда код точно будет введен без ошибок, и именно в то место, которое нужно.
uses About;
Теперь в главной форме снова откройте редактор главного меню, дважды щелкнув по компоненту MainMenu. Выделите пункт справа от "Файл", и в свойстве Caption напишите "Справка". А в пункте ниже напишите "О программе":
Рис. 8.4. Редактор главного меню
При разработке меню не забывайте о стандартах, принятых в Windows. Никто не запрещает Вам засунуть подраздел "О программе" в Пункт "Файл" или какой-нибудь другой. Однако пользователь будет искать его именно в разделе "Справка". Не заставляйте пользователя привыкать к другим стандартам, если хотите, чтобы ваши программы пользовались спросом!
Теперь нужно написать код вызова модального окна. Дважды щелкните по подразделу меню "О программе", чтобы создать процедуру обработки этого подраздела. Там введите инструкцию:
fAbout.ShowModal;
Помните, что мы вызываем форму модального окна (fAbout), поэтому нужно обращаться именно к ней.
Сохраните проект, скомпилируйте программу и посмотрите результат.