Создаем диалог-мастер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 и FreePascal. Комментарии и вопросыМатериалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта. :: Главная :: Диалоги и Фреймы ::
|
||||
©KANSoftWare (разработка программного обеспечения, создание программ, создание интерактивных сайтов), 2007 |