Первый раздел урока: Стандартный интерфейс пользователя, или Приложение и меню — навсегда!

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

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

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

Задачи урока

  • Дать общие представления о стандартном интерфейсе пользователя.
  • Работа с компонентами MainMenu и PopupMenu.

Выполнение упражнения

В этом упражнении вы создадите стандартный интерфейс пользователя для уже написанного вами приложения в уроке № 4  — Текстовый редактор (рисунок 1). Он будет состоять из главного меню приложения и контекстного меню для многострочного редактора.

Рисунок 1. Окно приложения

1. Что же придумал Microsoft?

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

 а)  б)

Рисунок 2

1. Заголовок окна — элемент любого окна (хотя может и отсутствовать). Там находятся кнопки управления окном и его текстовый заголовок.

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

(вкладка Standart).

3. Контекстное меню — элемент интерфейса, в котором отображаются пункты меню, связанные с компонентом. Вызывается щелчком правой кнопки мыши на связанном компоненте. В Delphi компонент, отвечающий за контекстное меню, носит название PopupMenu  (вкладка Standart).

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

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

6. Всплывающая подсказка (Hint) выглядит следующим образом:

За всплывающюу подсказку в Delphi отвечает свойство компонентов — Hint типа String. Подсказка показывается в том случае, если значение логического свойства ShowHint=True.

Отметим, что главное меню, контекстное меню и панель инструментов кроме текста могут отображать и иконки, соответствующие выполняемой операции (рисунок 2б). Все иконки удобно хранить в специальном контейнере — ImageList  (вкладка Win32).

Ниже мы рассмотрим работу каждого элемента интерфейса более подробно (кроме панели статуса).

2. Дизайн приложения

1. Откройте созданное нами ранее приложение в уроке № 4  — Текстовый редактор.

2. Поместите на форму компоненты MainMenu и PopupMenu согласно рисунку 3.

Рисунок 3

3. Измените имена компонентов следующим образом:

Имя, которое было Имя, на которое

необходимо изменить

FontDialog1 FontDialog
OpenDialog1 OpenDialog
MainMenu1 MainMenu
PopupMenu1 PMenuMemo

 

Обратите внимание, что у многих интерфейсных компонентов мы просто убрали порядковый номер, т. к. они находятся на форме в единственном экземпляре и выполняют свои «штатные» функции. Исключением является только компонент PopupMenu, у которого в названии есть добавка Memo. Она говорит о том, что контекстное меню будет привязано к компоненту Memo.

3. Создание главного и контекстного меню

1. Приступим к созданию главного меню. Щёлкните два раза по компоненту MainMenu. В результате откроется окно специального редактора главного меню (рисунок 4).

Рисунок 4

Как правило, главное меню состоит из нескольких категорий, таких как «Файл», «Вид», «Опции», «Помощь» и т. д. (например, посмотрите на главное меню приложения Microsoft Word). Нам необходимы всего две категории: «Файл» с пунктами «Новый», «Открыть», «Выход» и «Опции» с пунктами «Шрифт» и «Жирный».

2. Для того чтобы создать новую категорию «Файл», введите в свойстве Caption — «Файл» и нажмите клавишу  Enter. В результате появятся два новых пустых места — для новой категории и для пункта меню, как показано на рисунке 5а.

 а)  б)  в)

Рисунок 5

3. Создайте пункт «Новый» в категории «Файл«. Делается это точно так же — введите в свойство Caption слово «Новый» и нажмите Enter. Появилось место для следующего пункта. В нём свойству Captionприсвойте значение «Открыть файл» и далее в последнем пункте свойству Caption присвойте значение «Выход». В результате должна получиться заготовка меню, как показано на рисунке 5б.

4. Аналогично предыдущему пункту, создайте следующую категорию «Опции», в которой будут пункты: «Шрифт» и «Жирный». Результат этой работы показан на рисунке 5в. Закройте окно главного меню.

В итоге в верхней части формы появится меню (рисунок 6а). Вы сможете выбирать пункты этого меню (рисунок 6б). Правда, пока они ничего не будут делать. Пункты меню — это аналог кнопок Button, только в более компактном виде.

 а)  б)

Рисунок 6

5. Для раздела меню «Жирный» поставьте свойство AutoCheck = True (рисунок 7). Это означает, что данный раздел будет работать как компонент CheckBox.

Рисунок 7

Предупреждение! Для того чтобы изменить свойства пункта в меню или назначить ему событие, необходимо выбрать его в окне редактора главного меню. Например, как показано на рисунке 5б для пункта «Выход». Но событие OnClick можно создать и непосредственно из конструктора формы, просто щёлкнув по необходимому пункту меню.

6. Приступим к изготовлению контекстного меню для компонента Memo. Сначала нужно сообщить Memo о том, что у него будет такое меню. Для этого напротив свойства PopupMenu, компонента Memo (имя MemoOut), в раскрывающемся списке выберите пункт PMenuMemo (рисунок 8). Теперь многострочный редактор будет «знать», что если на него кликнут правой кнопкой мыши, то появится соответствующее контекстное меню.

Рисунок 8

7. Щёлкните два раза по компоненту PopupMenu. В результате откроется окно редактора контекстного меню. Внешне оно выглядит точно так же, как и редактор главного меню, только без возможности создания категорий. Создайте в нём пункты «Открыть файл» и «Шрифт» (рисунок 9). После закройте редактор контекстного меню.

Рисунок 9

8. Запустите приложение. Пощёлкайте по пунктам главного меню. Нажмите на пункт «Жирный» и посмотрите, как меняется его вид. Вызовите контекстное меню правой кнопкой мыши на многострочном редакторе. Закройте приложение.

9. Дайте осмысленные имена разделам главного меню согласно таблице:

Функциональная нагрузка раздела меню Имя, на которое

необходимо изменить

Новый nNew
Открыть файл nOpen
Выход nExit
Шрифт nFont
Жирный nBold

 

4. Перенос программного кода

Теперь интерфейс главного и контекстного меню работает, но, к сожалению, ничего не делает. Надо ведь обработчики событий писать! Одно только радует, что весь программный код, написанный ранее для упражнения «Текстовый редактор», практически остаётся прежним, так как мы меняем преимущественно интерфейс.

1. Перенесите содержимое событий OnClick кнопок Button в обработчики событий OnClick соответствующих пунктов главного меню. Например, из кнопки «Новый» — в пункт меню «Файл» → «Новый» и т. д.

2. Удалите панель (Panel1) вместе со всем её содержимым. Она нам больше не нужна, весь программный код находится в обработчиках событий OnClick главного меню.

3. Запустите приложение. И… Сразу синтаксическая ошибка. Компилятор не знает такого компонента как CheckBold в обработчиках событий nFontClick и nBoldClick. Это и логично, ведь мы только что его удалили. Теперь вместо него у нас раздел главного меню — компонент NBold.

4. Замените во всём коде имя компонента CheckBold на NBold.

5. Свяжите обработчики событий OnClick контекстного меню с соответствующими обработчиками главного меню.

6. Запустите приложение. Убедитесь, что всё работает, пощёлкав на пункты главного и контекстного меню.

5. Коротко о главном

За главное меню отвечает компонент MainMenu  (вкладка Standart). На форме оно может быть только в единственном экземпляре.

За контекстное меню отвечает компонент PopupMenu  (вкладка Standart). Оно привязывается к конкретному компоненту (компонентам) через специальное свойство PopupMenu этого компонента (компонентов). Для компонента может быть только одно контекстное меню.

Второй раздел урока: Стандартный интерфейс пользователя, или Инструменты на панели

В предыдущей части урока № 11 — Интерфейс пользователя, или Приложение и меню — навсегда! мы создали стандартный интерфейс пользователя для уже написанного вами приложения в уроке № 4 — Текстовый редактор. Он включал в себя главное меню приложения и контекстное меню для многострочного редактора. Но это только малая часть компонентов интерфейса, предлагаемых средой Delphi. Рассмотрим ещё несколько из них.

Задачи урока

  • Работа с компонентом ToolBar.
  • Работа с компонентом ImageList.
  • Использование всплывающих подсказок (Hint).

Выполнение упражнения

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

Рисунок 1. Окно приложения

1. Работа с панелью инструментов

1. Откройте проект, созданный в предыдущем разделе урока № 11 — Интерфейс пользователя, или Приложение и меню — навсегда!

2. Поместите на форму компоненты ToolBar  (категория Win32) и ImageList  (категория Win32) согласно рисунку 2.

Рисунок 2

Обратите внимание, что компонент ToolBar (панель инструментов) сразу же отображается прижатым к верхней части окна (Align = alTop). Он пока пустой (т. е. без инструментальных кнопок).

3. Переименуйте помещенные на форму компоненты следующим образом: ImageList1 — ImageList, ToolBar1 — ToolBar.

4. Создайте инструментальные кнопки на панели инструментов. Для этого щёлкните на панели инструментов (ToolBar) правой кнопкой мыши. В результате откроется контекстное меню (рисунок 3а). В верхней части меню будут два важных пункта «New Button» («Новая кнопка») и «New Separator» («Новый разделитель»). Первый пункт добавляет функциональную кнопку на панель инструментов (аналог кнопки SpeedButton), как показано на рисунке 3а, а второй добавляет разделитель групп между кнопками.

 а)  б)

Рисунок 3

Добавьте на панель пять кнопок и два разделителя согласно рисунку 3б. Кнопки и разделители можно перемещать по панели с помощью метода Drag and Drop (перетащи и оставь).

Первые пары кнопок будут дублировать пункты главного меню «Новый» и «Открыть файл», вторые — «Шрифт» и «Жирный», а последняя кнопка — «Выход».

5. Обратите внимание, что кнопки на рисунке 3б менее рельефные, чем получились у нас. При запуске приложения их вообще не будет видно (как в приложении MS Word), а когда вы наведёте на них мышью, они будут «приподниматься». Этот эффект сейчас «модный». Выделите панель инструментов (не кнопки!) и поменяйте значение свойства Flat (плоский) с False на True.

Но как же пользователь узнает, какая кнопка что делает… Можно, конечно, отобразить заголовок кнопки (для этого необходимо свойство ShowCaption для инструментальной панели поставить в True), но лучше поместить на неё маленькую картинку — пиктограмму (обычно размером 16х16 либо 32х32 пикселей), которая наглядно отображает функциональное действие кнопки. Иногда одновременно размещают и текст, и картинку.

Картинками мы займёмся в следующем разделе.

2. А картинки — лучше!

1. Чтобы «прилепить» к каждой инструментальной кнопке картинку, необходимо связать панель инструментов со специальным контейнером картинок —  ImageList . Для этого напротив свойства Imagesкомпонента ToolBar в раскрывающемся списке выберите пункт ImageList (рисунок 4).

Рисунок 4

После таких действий картинки на инструментальных кнопках не появятся, ведь в контейнере картинок (ImageList) пусто, но зато установится связь между этими компонентами.

2. Наполним контейнер картинок набором пиктограмм. Щёлкните два раза мышью на компоненте ImageList. В результате откроется окно редактора набора картинок (рисунок 5).

Рисунок 5

3. Нажмите кнопку «Add» («Добавить») для выбора картинок через диалог открытия файлов. Выберите файл Icons.bmp в каталоге «Обеспечение». В результате появится сообщение (рисунок 6). Нажмите на кнопку Yes.

Рисунок 6

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

Рисунок 7

4. После сообщения редактор набора картинок отобразит список добавленных пиктограмм (рисунок 8). Нажмите кнопку «ОК».

Рисунок 8

Сразу же после закрытия редактора на панель инструментов «высыпятся» пиктограммы (рисунок 9). Но их функциональное значение не совпадает с нашей задумкой (см. пункт 4).

Рисунок 9

5. Назначьте каждой кнопке свою пиктограмму согласно рисунку 10. Кнопка [Abc] будет вызывать диалог шрифта, а кнопка [B] — будет переключать жирность шрифта.

Рисунок 10

Чтобы назначить кнопке конкретную пиктограмму, необходимо её выбрать в свойстве ImageIndex у каждой инструментальной кнопки (рисунок 11).

Рисунок 11

6. У кнопки [B] свойство Style установите в tbsCheck (рисунок 12). Это означает, что эта кнопка будет работать как компонент CheckBox.

Рисунок 12

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

 а)  б)  в)

Рисунок 13

8. Свяжите обработчики событий OnClick инструментальных кнопок меню с соответствующими обработчиками главного меню.

9. Запустите программу. Пощёлкайте по кнопкам инструментальных панелей и убедитесь в их работоспособности. Точнее, в работоспособности всех кнопок, кроме кнопки B. Она не работает! Ещё бы… В её обработчике событий onClick стоит проверка только на состояние (вкл/выкл) пункта главного меню «Жирный».

10. Дополните код события nBoldClick следующими строками:

procedure TForm1.nBoldClick(Sender: TObject);
begin

  if Sender is TToolButton Then nBold.Checked    := ToolButton4.Down
                           Else ToolButton4.Down := nBold.Checked;
  If nBold.Checked Then MemoOut.Font.Style := MemoOut.Font.Style+[fsBold]
                   Else MemoOut.Font.Style := MemoOut.Font.Style-[fsBold];

end;
Листинг 1

Это означает, что мы проверяем условие: если тип компонента (Sender) является (is) инструментальной кнопкой (TToolButton), то «нажимаем» раздел главного меню «Жирный», в противном случае —«нажимаем» кнопку [B]. Состояние инструментальной кнопки отслеживает свойство Down.

11. Дополните обработчик события ButtonFontClick (событие OnClick для элемента меню «Шрифт») следующей строкой:

procedure TForm1.ButtonFontClick(Sender: TObject);
begin

  // Передаём компоненту FontDialog параметры шрифта из компонента Memo
  FontDialog1.Font := MemoOut.Font;
  // Открываем диалог шрифта
  If FontDialog1.Execute then begin
    // Если была нажата кнопка OК, то:
    // Передаём компоненту Memo параметры шрифта из компонента FontDialog
    MemoOut.Font := FontDialog1.Font;
    // Изменяем, если необходимо, состояние переключателя 
    NBold.Checked    := fsbold in FontDialog.Font.Style;
    ToolButton4.Down := fsbold in FontDialog.Font.Style;
  end;

end;
Листинг 2

Здесь мы дополнительно меняем состояние кнопки [B], если произошли изменения жирности шрифта в диалоге «Шрифт».

12. Запустите программу. Теперь всё работает правильно!

3. Главное — вовремя «всплыть» подсказке!

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

Рисунок 14

1. Выделите панель инструментов (ToolBar) и значение свойства ShowHint установите в True. Это означает, что разрешается использование всплывающих подсказок у инструментальных кнопок панели (по умолчанию у всех компонентов использование всплывающих подсказок запрещено).

2. Выделите первую кнопку инструментальной панели . В свойстве Hint напишите «Новый».

3. Поочерёдно выделяя остальные инструментальные кнопки, записывайте соответствующий текст в свойство Hint. Этот текст должен кратко отражать назначение кнопки. Например: «Открыть файл», «Выбор шрифта», «Жирный», «Выход».

4. Запустите программу и наведите курсором на каждую из инструментальных кнопок. Убедитесь, что подсказки всплывают у каждой из кнопок.

Теперь ваши приложения станут намного привлекательнее!

4. Коротко о главном

Пункты меню компонентов MainMenu  и PopupMenu  могут содержать пиктограммы.

За панель инструментов отвечает компонент ToolBar  (вкладка Win32). Он состоит из набора кнопок (инструментальных), которые дублируют наиболее часто используемые элементы главного меню. Кнопки содержат пиктограммы, поясняющие текст.

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

Компонент ImageList  (вкладка Win32) — это контейнер для картинок (пиктограмм) одинакового размера. Его можно связать с различными меню и инструментальными панелями для передачи в их распоряжение набора картинок, хранящихся этом компоненте.

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

Кнопки инструментальной панели и разделы главного и контекстного меню могут работать как переключатели (аналог компонента CheckBox).

Зарезервированное слово As служит для определения типа компонента, от которого произошло событие, следующим образом: 
Sender As <тип компонента>. Результатом является значение True либо False.

Всплывающие подсказки можно назначать любому видимому компоненту через свойство Hint. Чтобы подсказка «всплывала», необходимо, чтобы свойство ShowHint у компонента имело значение True

5. Выполнение заданий

Особенности задания

Во всех заданиях в качестве базового приложения следует использовать текстовый редактор, созданный в упражнении № 12. 
Примечание: набор дополнительных пиктограмм для инструментальных кнопок находится в папке «Обеспечение».

Задания I уровня сложности

1. Дополните текстовый редактор функцией сохранения текстового файла через компонент SaveDialog. Для этого расположите новую кнопку «Сохранить» рядом с кнопкой «Открыть». А также добавьте в интерфейс приложения функцию «Сохранить как…», которая должна быть в главном и контекстном меню и в инструментальной панели.


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


3. Дополните текстовый редактор функцией выбора цвета фона у компонента Memo через компонент ColorDialog. Цвет фона выбирается через нажатие на соответствующую инструментальную кнопку либо пункт меню.


4. Дополните текстовый редактор функцией выбора цвета шрифта у компонента Memo через компонент ColorDialog. Выбор цвета шрифта должен быть доступен из главного меню и из инструментальной панели. Цвет текста выбирается нажатием на соответствующую инструментальную кнопку (либо пункт меню).


5. Дополните текстовый редактор функцией задания размера шрифта. Добавьте в интерфейс приложения функции «Увеличить шрифт на 1 пт» и «Уменьшить шрифт на 1 пт». Они должны быть в главном меню и в инструментальной панели.


6. Создайте приложение, которое должно уметь открывать текстовые файлы и отображать их в многострочном редакторе. Добавьте в интерфейс приложения функции «Открыть», «Выход» и «Cохранить». Они располагаются в главном и контекстном меню и в инструментальной панели. При нажатии на кнопки «Открыть» и «Cохранить» выводятся диалоги открытия и сохранения файла соответственно.


7. Дополните текстовый редактор функцией помещения выбранного фрагмента текста в буфер обмена и вставления содержимого буфера в многострочный редактор. Эти операции реализуются через функции «Вырезать», «Копировать», «Вставить» и «Выделить всё». Они должны быть в главном меню и в инструментальной панели. В контекстном меню должны быть только функции «Копировать» и «Вставить».


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

Задания II уровня сложности

1. Добавьте в интерфейс текстового редактора функцию «Заменить». Она должна быть в главном меню (как пункт) и в инструментальной панели (как кнопка). Диалог происходит с помощью дополнительной формы. На ней должны быть расположены: два однострочных редактора (что заменить и на что заменить), кнопки «Заменить» и «Закрыть».


2. Добавьте в интерфейс текстового редактора функцию «Найти». Она должна быть в главном меню (как пункт) и в инструментальной панели (как кнопка). Диалог происходит с помощью дополнительной формы. На ней расположены: однострочный редактор (что найти), кнопки «Найти» и «Закрыть». Если строка найдена, то она выделяется. При повторном нажатии на кнопку будет происходить дальнейший поиск фрагмента в тесте. Когда поиск дойдёт до конца документа, то он продолжается с его начала.