Действует для версии: DIRECTUM 4.5 (IS-Builder 7.6.1) и выше.
Данный документ описывает алгоритм создания мастеров настройки на языке ISBL. Мастер - это программа, в определенной последовательности вызывающая диалоги, которые запрашивают у пользователя различные параметры, проверяют их корректность и предпринимают соответствующие действия по настройке чего-либо. Все строки, используемые в примерах в данном документе, не локализованы. Это сделано исключительно для того, чтобы упростить понимание кода.
Для разработки нового мастера создайте сценарий (функцию, расчет и т.д.) и следуйте инструкциям, приведенным ниже.
Для начала опишем все кнопки, используемые в диалогах мастера, например:
CancelButton
= "Отмена"
NextButton
= "Далее >>"
PreviousButton = "<<
Назад"
ReadyButton
= "Готово"
Каждой кнопке соответствует строковая переменная. В качестве значения переменной задается текст, который в дальнейшем будет отображаться на кнопке. Имя переменной должно оканчиваться на "Button".
Добавим код:
Delimiter = "|"
Если один и тот же набор кнопок предполагается использовать в различных диалогах, необходимо определить для него отдельную переменную, например:
// Кнопки первого диалога (отсутствует кнопка “<< Назад”)
FirstPageButtons = Join(ArrayOf(NextButton; ReadyButton; CancelButton); Delimiter)
// Кнопки промежуточного диалога (есть все кнопки)
InnerPageButtons = Join(ArrayOf(PreviousButton; NextButton; ReadyButton;
CancelButton); Delimiter)
// Кнопки последнего диалога (отсутствует кнопка “Далее >>”)
LastPageButtons = Join(ArrayOf(PreviousButton; ReadyButton; CancelButton);
Delimiter)
Имя переменной должно оканчиваться на "Buttons".
Определим все возможные типы параметров, которые запрашиваются диалогами.
В первую очередь задаются простые типы, например:
StringType = "Строка"
IntegerType = "Число"
DateType = "Дата"
FontNameType = “Строка:50”
Далее - перечислимые, например:
taLeft = "По левому краю"
taRight = "По правому краю"
TextAlignmentType = Format('Признак:%s,%s:К'; ArrayOf(taLeft; taRight))
Имя переменной, описывающей тип, должно оканчиваться на "Type".
Определим диалоги и параметры, используемые в мастере, и сопоставим с ними порядковые номера. Для диалога порядковый номер определяет, каким по счету он будет отображен пользователю. Для параметра - каким он окажется в списке параметров соответствующего диалога. Например:
//
Стиль текста документа
TextStyle = 0
// Имя штрифта
tsFontName = 0
// Размер шрифта
tsFontSize = tsFontName + 1
// Выравнивание
tsAlignment = tsFontSize + 1
// Параметры сохранения документа
Destination = TextStyle + 1
// Имя файла
dPath = 0
Индекс первого диалога должен быть равен 0. Для удобства добавления новых диалогов, индекс каждого последующего диалога должен вычисляться путем прибавления 1 к индексу предыдущего. Аналогично для параметров.
Добавим код:
EnvironmentValueVariableName = 'Value'
Опишем проверки корректности значений всех параметров. Каждая проверка - это ISBL-код, возвращающий результат проверки в переменной Result. Из кода доступна переменная окружения EnvironmentValueVariableName, содержащая значение проверяемого параметра. Например:
// Параметр пройдет проверку, если его значение не пустое
ValueIsNotEmptyCondition = Format(
'Value = Object.Environment.ValueByName("%s");
Result = Value <<>> ""';
ArrayOf(EnvironmentValueVariableName))
Имя переменной, описывающей проверку, должно оканчиваться на "Condition".
Добавим код:
EnvironmentDialogsVariableName = 'Dialogs'
Зададим условия отображения для каждого диалога. Условие представляет собой ISBL-код, возвращающий в переменной Result True, если диалог должен быть отображен, или False - в противном случае. Из кода доступна переменная окружения EnvironmentDialogsVariableName, содержащая полное описание всех диалогов (подробнее см. раздел "Диалоги"). Например:
// Шаблон условия для проверки поля произвольного диалога на определенное значение
// В шаблон должны быть подставлены следующие величины:
//
- EnvironmentDialogsVariableName;
//
- индекс диалога, содержащего проверяемый параметр;
//
- FieldValues;
//
- индекс проверяемого параметра;
//
- значение, с которым будет сравниваться проверяемый параметр;
CheckDialogFieldConditionTemplate =
'Dialogs = Object.Environment.ValueByName("%s")
Dialog = Dialogs[%s]
DialogFieldValues = Dialog[%s]
Result = DialogFieldValues[%s] == "%s"'
// Диалог будет отображен, если параметр
tsAlignment диалога
TextStyle будет
равен
taLeft
TextIsLeftAlignedCondition = Format(CheckDialogFieldConditionTemplate;
Arrayof(EnvironmentDialogsVariableName; TextStyle; FieldValues; tsAlignment; taLeft))
Имя переменной, описывающей условие, должно оканчиваться на "Condition".
Опишем диалоги мастера в массиве Dialogs, имеющем следующую структуру:
Dialogs =
ArrayOf(
// <Диалог1>
ArrayOf(
// Заголовки параметров
Join(ArrayOf(
<Заголовок_параметра1>;
<Заголовок_параметра2>;
...
);
Delimiter);
// Типы
параметров
Join(ArrayOf(
<Тип_параметра1>;
<Тип_параметра2>:
...
);
Delimiter);
// Текущие значения параметров
ArrayOf(
<Значение_параметра1>;
<Значение_параметра2>;
...
);
// Проверки корректности введенных значений параметров
ArrayOf(
<Проверка_параметра1>;
<Проверка_параметра2>;
...
);
// Сообщения о вводе некорректных значений параметров
ArrayOf(
<Сообщение_параметра1>;
<Сообщение_параметра2>;
...
);
// Группа кнопок или перечисление отдельных кнопок:
//
ArrayOf(
//
<Кнопка1>;
//
<Кнопка2>;
//
...
//
);
<Группа_кнопок>;
// Заголовок окна диалога
<Заголовок_окна>
// Условия отображения диалога
ArrayOf(
<Условие_отображения1>;
<Условие_отображения1>;
...);
// Способ объединения условий отображения диалога:
// -
mOr (логическое “Или”)
//
- mAnd (логическое “И”)
<Способ_объединения_условий_отображения>
);
// <Диалог2>
...
)
Для доступа к отдельным частям диалога (текущим значениям параметров, заголовку окна диалога и т.д.) объявим переменные:
// Заголовки параметров
FieldCaptions = 0
// Типы параметров
FieldTypes =
FieldCaptions + 1
// Текущие значения параметров
FieldValues
= FieldTypes + 1
// Проверки корректности введенных значений параметров
FieldChecks = FieldValues + 1
// Сообщения о вводе некорректных значений параметров
FieldCheckMessages = FieldChecks + 1
// Кнопки
Buttons = FieldCheckMessages + 1
// Заголовок
окна диалога
Title =
Buttons + 1
// Условия отображения диалога
ExecutionConditions =
Title + 1
// Способ объединения условий отображения диалога
ExecutionConditionMergeMode = ExecutionConditions + 1
Пример чтения/записи значения параметра:
// Считать значение параметра
dPath диалога
Destination
// Получить диалог
Dialog = Dialogs[Destination]
// Получить список значений параметров диалога
DialogFieldValues = Dialog[FieldValues]
// Прочитать
значение параметр
dPath
... = DialogFieldValues[dPath]
// Изменить значение параметра dPath диалога
Destination
DialogFieldValues[dPath] = ...
// Сохранить изменения
Dialog[FieldValues] = DialogFieldValues
Dialogs[Destination] = Dialog
Добавим код, реализующий логику работы мастера по введенным ранее настройкам:
// Код отмены работы мастера
ConfigurationFail = -1
// Код завершения работы мастера
ConfigurationComplete = -2
// Код рестарта текущего диалога
DialogRestarted = -3
// Индекс текущего диалога
CurrentDialog = 0
// Нажатая в последнем диалоге кнопка
ChosenButton = NextButton
// Индекс
первого диалога
FirstDialogIndex = ArrayLowBound(Dialogs)
//
Индекс последнего
диалога
LastDialogIndex = ArrayHighBound(Dialogs)
// Вызывть диалог с индексом CurrentDialog, пока этот индекс не выдет за
// диапазон FirstDialogIndex..LastDialogIndex или работа мастера не будет
//
отменена (ConfigurationFail)
или завершена (ConfigurationComplete)
while (CurrentDialog <> ConfigurationFail) and
(CurrentDialog <> ConfigurationComplete) and
(CurrentDialog >= FirstDialogIndex) and (CurrentDialog <= LastDialogIndex)
// Получить
текущий диалог
Dialog = Dialogs[CurrentDialog]
//
Проверить условия
отображения текущего
диалога
NeedToExecute = Dialog[ExecutionConditionMergeMode] = mAnd
Object.Environment.SetVar(EnvironmentDialogsVariableName; Dialogs)
foreach Condition in CArrayElement(Dialog[ExecutionConditions])
if Dialog[ConditionsMergeMode] = mAnd
NeedToExecute = NeedToExecute and Execute(Condition)
else
NeedToExecute = NeedToExecute or Execute(Condition)
endif
endforeach
// Если диалог должен быть отображен
if NeedToExecute
// Отобразить диалог
DialogResult = InputDialogEx(Dialog[FieldCaptions]; Join(Dialog[FieldValues];
Delimiter); Dialog[FieldTypes]; Dialog[Title]; ; ; ; Dialog[Buttons];
IfThen(CurrentDialog = LastDialogIndex; ReadyButton; NextButton);CancelButton)
// Считать значения параметров, заданных в ходе работы диалога
DialogFieldValues = Dialog[FieldValues]
FieldIndex = 0
FieldsCount = SubStringCount(DialogResult; Delimiter)
foreach FieldValue in CSubString(DialogResult; Delimiter)
if FieldIndex = FieldsCount - 1
//
Считать нажатую
кнопку
ChosenButton = FieldValue
else
// Считать новое значение параметра
DialogFieldValues[FieldIndex] = FieldValue
endif
FieldIndex = FieldIndex + 1
endforeach
Dialog[FieldValues] = DialogFieldValues
Dialogs[CurrentDialog] = Dialog
//
Проверить корректность
ввода параметров
DialogFieldChecks = Dialog[FieldChecks]
DialogFieldCheckMessages = Dialog[FieldCheckMessages]
FieldIndex = 0
foreach FieldValue in CArrayElement(DialogFieldValues)
Object.Environment.SetVar(EnvironmentValueVariableName; FieldValue)
if not Execute(DialogFieldChecks[FieldIndex])
ShowMessage(DialogFieldCheckMessages[FieldIndex])
CurrentDialog = DialogRestarted
exitfor
endif
FieldIndex = FieldIndex + 1
endforeach
endif
// Обработать
нажатия на
кнопки
if ChosenButton == NextButton
CurrentDialog = CurrentDialog + 1
endif
if ChosenButton == PreviousButton
CurrentDialog = CurrentDialog - 1
endif
if ChosenButton == CancelButton
CurrentDialog = ConfigurationFail
endif
if ChosenButton == ReadyButton
CurrentDialog = ConfigurationComplete
endif
endwhile
Если в диалогах присутствуют какие-либо нестандартные кнопки (отличные от "Далее >>", "<< Назад", "Отмена", "Готово"), необходимо написать для них собственные обработчики, например:
// Обработать нажатие на кнопку “Выбрать папку”
if ChosenButton == BrowseButton
// Создать внешний диалог выбора папки
FolderDialog = CreateFolderDialog()
// В качестве начальной папки означить текущее значение параметра
dPath
FolderDialog.InitialDir = DialogFieldValues[dPath]
// Если пользователь выбрал какую-либо папку
if FolderDialog.Execute
// Изменить значение параметра
dPath
DialogFieldValues[dPath] = FolderDialog.Result
Dialog[FieldValues] = DialogFieldValues
Dialogs[CurrentDialog] = Dialog
endif
endif
В самом конце необходимо написать код для настройки того, для чего собственно и предназначался создаваемый мастер. Пример чтения/записи значений параметров, которые ввел, приведен в разделе "Диалоги".
Авторизуйтесь, чтобы написать комментарий