![]() |
![]() ![]() ![]() ![]() |
|
Создаем диалог-мастерDelphi , Программа и Интерфейс , Диалоги и Фреймы
Оформил: DeeCo Автор: Николай Мазуркин В данной статье рассматривается способ создания мастера (Wizard) с использованием средств Delphi и стандартной библиотеки VCL, без установки и использования каких-либо дополнительных компонентов или средств. ВведениеВ палитре современных средств для строительства программных интерфейсов особое место занимают интерфейсные диалоги типа "мастер" (в оригинале, на английском, Wizard - "фокусник, волшебник"). Данные элементы широко применяются как самой операционной системой Windows (особенно последние версии Windows 2000, Windows XP), так и многими программами различных производителей программного обеспечения. Во многих случаях использование мастера стало стандартом, например, в программах установки программного обеспечения. Что же такое мастер? Можно определить мастер, как самоконфигурирующийся диалог управления определенным процессом, который разбивает настройку процесса на несколько этапов с возможностью ветвления, проводит пользователя через эти этапы, указывая только необходимые параметры и избавляя от необходимости тратить внимание на элементы управления, не участвующие в текущем этапе. Достоинствами мастера перед альтернативными решениями, вроде многостраничного диалога настройки являются следующие факторы.
Пример мастера приведен на следующем рисунке. Это тестовый мастер, который мы будем разрабатывать в рамках данной статьи.
Практически любой мастер состоит из следующих элементов.
Представим себе, что мы разрабатываем финансовую программу, результатом которой является таблица с большим количествов записей. Нам необходимо сохранить эту таблицу в формате, указанном пользователем. Формат может быть выбран из множества HTML, XML или TXT. Также у каждого формата существуют свои, специфические настройки. Решим эту задачу с помощью разработки специального мастера, который позволит пользователю выбрать необходимый формат, указать настройки, и выбрать файл для сохранения отчета. Схема мастераПрежде чем приступать к кодированию, необходимо продумать структуру будующего мастера: количество и назначение страниц, порядок перехода и конфигурации. Это облегчит работу на последующих этапах, в том числе и на этапе кодирования.
Еще лучше нарисовать всю структуру на бумаге или в графическом редакторе типа Visio. А те кто знаком с графическим языком UML, наверняка предпочтут проработать структуру мастера в виде полноценной Statechart диаграммы в редакторе типа Rational Rose. Подобная визуальная проработка структуры позволит продумать и учесть множество нюансов. Структура нашего мастера показана на следующем рисунке. Блоками обозначены странички, реализующие этапы настройки. В блоках указано программное имя странички (имя компонента), а цифрой в квадратных скобках показан индекс странички среди всех страничек мастера (подробнее о программной реализации мастера мы поговорим далее). Стрелками показаны переходы между страничками по нажатию кнопок "Назад" и "Вперед". Для тех же, кто понимает язык моделирования UML, можно предложить более детальную схему.
Видно, что мастер состоит из семи страничек. Назначение каждой из страничек следующее.
Будем считать, что мы уже разработали содержание, дизайн и текстовое наполнение каждой из страничек. Устройство мастераИтак, схема мастера уже полностью разработана и нам нужно приступить к непосредственному кодированию. Прежде чем приступить к рассмотрению вопросов, связанных с кодированием мастера, скачайте и откройте тестовый проект, содержащий полную реализацию проектируемого нами мастера. <<< Исходный код проекта диалога-мастера В режиме редактирования наш мастер выглядит следующим образом.
Настройка основных элементов мастера показана зеленым цветом. С остальными настройками и расположением элементов вы можете ознакомится сами, используя Object Inspector. В качестве контейнера для страниц мы будем использовать элемент TPageControl. Для того чтобы убрать выпуклую рамку вокруг элемента переведем его в режим tsButtons. Заголовки страничек позволят нам быстро выбирать нужную страничку для редактирования, однако они будут лишними в рабочем режиме. Чтобы убрать эти заголовки, при создании формы установим у всех элементов TTabSheet свойство TabVisible равным False. Для того чтобы дизайн мастера в рабочем режиме не сильно отличался от дизайна в режиме редактирования, установим минимальную высоту закладок. В "рекламной" области установим два текстовых элемента, один из которых будет отображать название текущей странички, а другой - краткое пояснение к ней. Чтобы не умножать сущности, название странички будем хранить прямо в ней, в свойстве TTabSheet.Caption, а краткое пояснение в свойстве TTabSheet.Hint (но при этом TTabSheet.ShowHint = False). Код мастераПо сути, любой мастер - это конечный автомат или state machine, в чистом виде. У него есть внутренние состояние, которое может быть в одном из нескольких положений (один из этапов или страничек). Также есть два события - OnForward и OnBackward, которые переводят этот автомат из одного состояния в другое, в зависимости от дополнительных внутренних настроек или опций. При этом переход определяется исключительно текущим положением и текущими настройками. Такой подход позволяет прекрасно и понятно описать работу мастера с помощью средств UML, а также анализировать и реализовывать работу мастера с помощью уже готового математического аппарата. Однако, мы не будем залезать в теоретические дебри и реализуем мастер простым способом. Основной код мастера состоит из трех процедур, являющихся обязательными для каждого мастера. Процедура ShowPageПроцедура ShowPage активизирует указанную страницу, настраивает кнопки и внешний вид диалога в соответствии с указанной страницей. Эта процедура также копирует текст названия страницы и комментарий к ней из свойств TTabSheet.Caption и TTabSheet.Hint в текстовые поля "рекламной" области. Можно дополнять и расширять эту процедуру. Например, настраивать дополнительные кнопки, выводить каждый раз новый логотип или информационную картинку в соответствии с выбранной страничкой, проигрывать звуковые файлы и т.д.
////////////////////////////////////////////////////////////////////////////////
// Показываем требуемую страничку
////////////////////////////////////////////////////////////////////////////////
procedure TDialogWizard.ShowPage(PageIndex: Integer);
begin
// Проверка индекса на допустимость
if (PageIndex < 0) or (pcWizard.PageCount < = PageIndex) then
Exit;
// Установка странички
pcWizard.ActivePageIndex := PageIndex;
// Установка параметров заголовка
lblCaption.Caption := pcWizard.ActivePage.Caption;
lblHint.Caption := pcWizard.ActivePage.Hint;
// Настраиваем кнопку "Назад"
btnBackward.Visible := PageIndex <
>
tsWelcome.PageIndex;
// Настраиваем кнопку "Вперед"
if PageIndex = tsFinish.PageIndex then
btnForward.Caption := 'Готово'
else
btnForward.Caption := 'Вперед >';
// Настраиваем кнопку "Отмена"
btnCancel.Enabled := PageIndex <
>
tsFinish.PageIndex;
end;
Обработчик OnForward
Обработчик события OnForward срабатывает каждый раз при нажатии кнопки "Вперед". И, если процедура ShowPage определяет, как выглядит мастер на каждой страничке, то обработчик события OnForward определяетю, что происходит при переходе от одной странички вперед к другой. По умолчанию, обработчик заменяет текущую страничку следующей, не производя при этом никаких других действий. Однако, для того чтобы реализовать логику нашего мастера, мы должны каждый раз проверять какая страничка находится в данный момент на экране, и какую страничку мы должны выставить следующей. Обратите внимание, что при уходе с определенных страничек происходит проверка их содержимого на корректность. И, если введенные пользователем данные на страничке некорректны, перехода не происходит.
////////////////////////////////////////////////////////////////////////////////
// Передвигаемся вперед
////////////////////////////////////////////////////////////////////////////////
procedure TDialogWizard.OnForward(Sender: TObject);
begin
// Это страница выбора формата?
if pcWizard.ActivePage = tsFormat then
begin
// Показываем соответствующую страницу
if rbtnChooseHTML.Checked then
ShowPage(tsFormatHTML.PageIndex);
if rbtnChooseXML.Checked then
ShowPage(tsFormatXML.PageIndex);
if rbtnChooseTXT.Checked then
ShowPage(tsFormatTXT.PageIndex);
Exit;
end;
// Это формат HTML?
if pcWizard.ActivePage = tsFormatHTML then
begin
// Проверка имени файла
if Trim(edtExportHTML.Text) = '' then
begin
edtExportHTML.SetFocus;
Application.MessageBox('Укажите имя файла', PChar(Caption), MB_OK or
MB_ICONWARNING);
Exit;
end;
// Очищаем лог
memLog.Clear;
ShowPage(tsProgress.PageIndex);
Exit;
end;
// Это формат XML?
if pcWizard.ActivePage = tsFormatXML then
begin
// Проверка имени файла
if Trim(edtExportXML.Text) = '' then
begin
edtExportXML.SetFocus;
Application.MessageBox('Укажите имя файла', PChar(Caption), MB_OK or
MB_ICONWARNING);
Exit;
end;
// Очищаем лог
memLog.Clear;
ShowPage(tsProgress.PageIndex);
Exit;
end;
// Это формат TXT?
if pcWizard.ActivePage = tsFormatTXT then
begin
// Проверка имени файла
if Trim(edtExportTXT.Text) = '' then
begin
edtExportTXT.SetFocus;
Application.MessageBox('Укажите имя файла', PChar(Caption), MB_OK or
MB_ICONWARNING);
Exit;
end;
// Очищаем лог
memLog.Clear;
ShowPage(tsProgress.PageIndex);
Exit;
end;
// Это страница экспорта?
if pcWizard.ActivePage = tsProgress then
begin
// Выполняем экспортирование
if rbtnChooseHTML.Checked then
if not ExportHTML then
Exit;
if rbtnChooseXML.Checked then
if not ExportXML then
Exit;
if rbtnChooseTXT.Checked then
if not ExportTXT then
Exit;
// Переходи на финальную страницу
ShowPage(tsFinish.PageIndex);
Exit;
end;
// Это финальная страница?
if pcWizard.ActivePage = tsFinish then
begin
ModalResult := mrOK;
Exit;
end;
// Действие по умолчанию - следующая страница
ShowPage(pcWizard.ActivePageIndex + 1);
end;
Обработчик OnBackward
Обработчик события OnBackward срабатывает каждый раз при нажатии на кнопку "Назад" и, по назначению, аналогичен обработчику OnForward. Данный обработчик определяет, что происходит при уходе со странички в обратном направлении.
////////////////////////////////////////////////////////////////////////////////
// Передвигаемся назад
////////////////////////////////////////////////////////////////////////////////
procedure TDialogWizard.OnBackward(Sender: TObject);
begin
// Это страница экспорта?
if pcWizard.ActivePage = tsProgress then
begin
// Показываем соответствующую страницу
if rbtnChooseHTML.Checked then
ShowPage(tsFormatHTML.PageIndex);
if rbtnChooseXML.Checked then
ShowPage(tsFormatXML.PageIndex);
if rbtnChooseTXT.Checked then
ShowPage(tsFormatTXT.PageIndex);
Exit;
end;
// Это финальная страница?
if pcWizard.ActivePage = tsFinish then
begin
ShowPage(tsFormat.PageIndex);
Exit;
end;
// Это формат HTML?
if pcWizard.ActivePage = tsFormatHTML then
begin
ShowPage(tsFormat.PageIndex);
Exit;
end;
// Это формат XML?
if pcWizard.ActivePage = tsFormatXML then
begin
ShowPage(tsFormat.PageIndex);
Exit;
end;
// Это формат TXT?
if pcWizard.ActivePage = tsFormatTXT then
begin
ShowPage(tsFormat.PageIndex);
Exit;
end;
// Действие по умолчанию - предыдущая страница
ShowPage(pcWizard.ActivePageIndex - 1);
end;
Дополнительные советы
Мастер является мощным инструментом реализации настроек сложных процессов и процедур, однако само по себе создание мастера не приводит автоматически к успеху - любой мастер должен быть продуманным, а его использование - оправданным. Вот несколько дополнительных советов.
Создаем диалог-мастер с использованием средств Delphi и стандартной библиотеки VCL без установки дополнительных компонентов или средств. Комментарии и вопросыПолучайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш :: Главная :: Диалоги и Фреймы ::
|
||||
©KANSoftWare (разработка программного обеспечения, создание программ, создание интерактивных сайтов), 2007 | ||||