Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

DiVM / OOP / 12_116608_1_51491

.pdf
Скачиваний:
26
Добавлен:
11.05.2015
Размер:
6.45 Mб
Скачать

Рисунок 8.85. При запуске программы команда Open оказалась недоступна

Странно: и кнопка Open… на панели инструментов, и пункт Open… в главном меню недоступны. Это объясняется отсутствием у компонента OpenAction обработчика события OnExecute. Им сейчас и займемся.

8.6.4. Реакция на команды

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

Шаг 80. Определим в компоненте OpenAction обработчик события OnExecute. Обратитесь к контекстному меню компонента ActionList и вызовите окно команд. В этом окне выберите команду OpenAction, после чего в окне свойств выберите вкладку Events. Теперь сделайте двойной щелчок мыши на значении события OnExecute. Среда Delphi создаст заготовку для будущего обработчика:

procedure TPictureForm.OpenActionExecute(Sender: TObject); begin

end;

Обработчик у нас уже есть в виде метода OpenMenuItemClick, поэтому мы просто перенесем код этого метода (слегка подправив его) в только что созданный метод, удалив код метода OpenMenuItemClick.

331

procedure TPictureForm.OpenMenuItemClick(Sender: TObject); begin

end;

...

procedure TPictureForm.OpenActionExecute(Sender: TObject); begin

if OpenDialog.Execute then begin

Image.Picture.LoadFromFile(OpenDialog.FileName);

EnableCommands(True);

NormalSizeAction.Execute; // Вместо NormalSizeMenuItem.Click; end;

UpdateStatusBar; end;

Сохраните проект; пустой метод OpenMenuItemClick будет автоматически удален из исходного текста.

Обратите внимание, что компонент Action автоматически подменяет обработчики OnClick в связанных с ним компонентах. Поэтому если вы перейдете к окну свойств и посмотрите на событие OnClick в компоненте OpenMenuItem, то обнаружите там метод

OpenActionExecute (обработчик события OnExecute компонента OpenAction).

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

Рисунок 8.86. Команда Open опять доступна пользователю (компонент OpenAction обрабатывает событие OnExecute)

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

Шаг 81. Обойдите все пункты меню (не забудьте про контекстное меню) и кнопки панели инструментов и установите в каждом из них свойство Action в соответствующее значение. Попутно значения некоторых других свойств тоже изменятся, например свойство Enabled получит значение True. Пусть вас это не беспокоит, так и должно быть (рисунок 8.87).

332

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

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

Шаг 82. Сделайте недоступной команду SaveAsAction, установив ее свойство Enabled в значение False. Одновременно кнопка и пункт меню Save As... станут недоступными

(рисунок 8.88).

Рисунок 8.88. Команда Save As отключена до тех пор, пока пользователь не откроет какойнибудь графический файл

Шаг 83. Создайте для компонента SaveAsAction обработчик события OnExecute и перенесите код метода SaveAsMenuItemClick в только что созданный метод

SaveAsActionExecute:

333

procedure TPictureForm.SaveAsMenuItemClick(Sender: TObject); begin

end;

procedure TPictureForm.SaveAsActionExecute(Sender: TObject); begin

if SaveDialog.Execute then Image.Picture.SaveToFile(SaveDialog.FileName);

end;

Шаг 84. Доработку команды SaveAsAction мы закончили и теперь по аналогии доработаем команды ExitAction и CloseAction:

procedure TPictureForm.ExitMenuItemClick(Sender: TObject); begin

end;

procedure TPictureForm.CloseMenuItemClick(Sender: TObject); begin

end;

procedure TPictureForm.ExitActionExecute(Sender: TObject); begin

Close; end;

procedure TPictureForm.CloseActionExecute(Sender: TObject); begin

with Image do begin

Picture := nil; Width := 0; Height := 0;

end;

NormalSizeAction.Execute; // Вместо NormalSizeMenuItem.Click; EnableCommands(False);

UpdateStatusBar; end;

Шаг 85. Теперь настало время команд ToolBarAction и StatusBarAction:

procedure TPictureForm.ToolBarMenuItemClick(Sender: TObject); begin

end;

procedure TPictureForm.StatusBarMenuItemClick(Sender: TObject); begin

end;

procedure TPictureForm.ToolBarActionExecute(Sender: TObject); begin

ToolBarAction.Checked := not ToolBarAction.Checked; ToolBar.Visible := not ToolBar.Visible;

end;

procedure TPictureForm.StatusBarActionExecute(Sender: TObject); begin

StatusBarAction.Checked := not StatusBarAction.Checked; StatusBar.Visible := not StatusBar.Visible;

end;

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

Шаг 86. Вернитесь к окну редактирования списка команд и выделите команду HalfSizeAction. После этого нажмите клавишу Ctrl и, удерживая ее, выделите команды NormalSizeAction и DoubleSizeAction. Перейдите к окну свойств и установите свойство GroupIndex в значение 1 (рисунок 8.89).

334

Рисунок 8.89. Группировка команд с помощью свойства GroupIndex

Шаг 87. Свойство Checked компонента NormalSizeAction установите в значение True — при запуске программы рисунок не масштабируется (рисунок 8.90).

Рисунок 8.90. Начальное значение для переключателя масштаба — Normal Size

Шаг 88. Установите свойство Enabled команд HalfSizeAction, NormalSizeAction и DoubleSizeAction в значение False — при запуске программы рисунок еще не загружен, поэтому команды переключения масштаба должны быть недоступны (рисунок 8.91).

335

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

Шаг 89. Теперь создадим обработчики команд HalfSizeAction, NormalSizeAction и DoubleSizeAction. Для каждой команды определите обработчик события OnExecute и перенесите код из уже имеющихся методов:

336

procedure TPictureForm.HalfSizeMenuItemClick(Sender: TObject); begin

end;

procedure TPictureForm.NormalSizeMenuItemClick(Sender: TObject); begin

end;

procedure TPictureForm.DoubleSizeMenuItemClick(Sender: TObject); begin

end;

...

procedure TPictureForm.HalfSizeActionExecute(Sender: TObject); begin

HalfSizeToolButton.Down := True;

HalfSizeMenuItem.Checked := True;

HalfSizePopupItem.Checked := True; with Image do

begin

AutoSize := False;

Width := Picture.Width div 2; Height := Picture.Height div 2; Stretch := True;

end; end;

procedure TPictureForm.NormalSizeActionExecute(Sender: TObject); begin

NormalSizeToolButton.Down := True;

NormalSizeMenuItem.Checked := True;

NormalSizePopupItem.Checked := True; Image.AutoSize := True;

end;

procedure TPictureForm.DoubleSizeActionExecute(Sender: TObject); begin

DoubleSizeToolButton.Down := True;

DoubleSizeMenuItem.Checked := True;

DoubleSizePopupItem.Checked := True; with Image do

begin

AutoSize := False;

Width := Picture.Width * 2; Height := Picture.Height * 2; Stretch := True;

end; end;

Шаг 90. Обработчики можно упростить за счет управления состоянием пунктов меню и кнопок через компоненты Action, т.е. первые три оператора каждого обработчика заменяются на один оператор:

337

procedure TPictureForm.HalfSizeActionExecute(Sender: TObject); begin

HalfSizeAction.Checked := True; with Image do

begin

AutoSize := False;

Width := Picture.Width div 2; Height := Picture.Height div 2; Stretch := True;

end; end;

procedure TPictureForm.NormalSizeActionExecute(Sender: TObject); begin

NormalSizeAction.Checked := True; Image.AutoSize := True;

end;

procedure TPictureForm.DoubleSizeActionExecute(Sender: TObject); begin

DoubleSizeAction.Checked := True; with Image do

begin

AutoSize := False;

Width := Picture.Width * 2; Height := Picture.Height * 2; Stretch := True;

end; end;

А теперь воспользуемся свойством AutoCheck компонентов Action, чтобы избавиться от необходимости программно переключать метку в пунктах Toolbar и Status bar главного меню. Когда свойство AutoCheck равно True, то при выполнении команды свойство Checked автоматически меняет свое значение на противоположное. Это отражается на связанных с командой пунктах меню и кнопках-переключателях.

Шаг 91. У команд ToolBarAction и StatusBarAction установите свойства AutoCheck и Checked в значение True.

Шаг 92. Подправьте методы ToolBarActionExecute и StatusBarActionExecute:

procedure TPictureForm.ToolBarActionExecute(Sender: TObject); begin

ToolBar.Visible := ToolBarAction.Checked; end;

procedure TPictureForm.StatusBarActionExecute(Sender: TObject); begin

StatusBar.Visible := StatusBarAction.Checked; end;

8.6.5. Управление состоянием команд

Компонент ActionList имеет удобный механизм управления состоянием команд (например, доступна/недоступна). После выполнения очередной команды и во время простоя программы в компоненте возникает событие OnUpdate. Реакцией на это событие может быть изменение состояния отдельных команд, например переключение в них свойства Enabled. Напомним, что сейчас для этих целей используется метод EnableCommand, вызываемый при открытии и закрытии файла. Избавимся от него.

Шаг 93. Выделите на форме компонент ActionList, и в окне свойств на вкладке Events отыщите событие OnExecute. Двойным щелчком мыши создайте обработчик:

338

procedure TPictureForm.ActionListUpdate(Action: TBasicAction; var Handled: Boolean);

var

NonEmpty: Boolean; begin

NonEmpty := Image.Picture.Graphic <> nil; SaveAsAction.Enabled := NonEmpty; CloseMenuItem.Enabled := NonEmpty; HalfSizeAction.Enabled := NonEmpty; NormalSizeAction.Enabled := NonEmpty; DoubleSizeAction.Enabled := NonEmpty; Handled := True;

end;

Шаг 94. Удалите метод EnableCommands и обращения к нему из методов

OpenActionExecute и CloseActionExecute. Вот, что должно получиться:

procedure TPictureForm.OpenActionExecute(Sender: TObject); begin

if OpenDialog.Execute then begin

Image.Picture.LoadFromFile(OpenDialog.FileName);

NormalSizeAction.Execute; end;

UpdateStatusBar; end;

procedure TPictureForm.CloseActionExecute(Sender: TObject); begin

with Image do begin

Picture.Graphic := nil; Width := 0;

Height := 0; end;

NormalSizeAction.Execute;

UpdateStatusBar; end;

Шаг 95. Программа полностью готова, выполните компиляцию и запустите ее. Наслаждайтесь результатами своего труда, просматривая рисунки на жестком диске

(рисунок 8.92).

339

Рисунок 8.92. Окончательный вариант программы для просмотра графических файлов

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

8.7. Итоги

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

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

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

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

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

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

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

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

9.2. Окно "About"

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

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

340