» nsDialogs: Создаем собственные страницы инсталлятора

K.A.V.
www.oszone.net
22.02.2010
Автор: hb860
Последнее обновление: 22.02.2010


Рано или поздно стандартных страниц, которые предоставляет система NSIS и её ModernUI, становится мало.

Ответ прост — использовать команду page и модуль nsDialogs, входящий в стандартную поставку NSIS. Рассмотрим поподробней, как с ними работать.

Создаем страницу
Для начала создадим простой скриптик, на примере которого будем производить изучать nsDialogs. Вот такой:

!include "MUI.nsh"
SetCompress off

!insertmacro MUI_PAGE_WELCOME
!insertmacro MUI_PAGE_INSTFILES
!insertmacro MUI_PAGE_FINISH
!insertmacro MUI_LANGUAGE "Russian"

Name "Winreview.ru"
OutFile "winreview.exe"
ShowInstDetails show

Section
DetailPrint "Hello from winreview.ru"
SetAutoClose false
SectionEnd


Теперь дополним этот код своей собственной страницей. Для этого воспользуемся командой Page, вот так:

!insertmacro MUI_PAGE_WELCOME
Page custom fnCustomInit fnCustomDestroy
!insertmacro MUI_PAGE_INSTFILES


Команда Page custom fnCustomInit fnCustomDestroy буквально означает — создать пользовательскую страницу, выполнить функцию fnCustomInit при создании, при закрытии страницы выполнить функцию fnCustomDestroy. Ничего сложного, не так ли ? Страница будет отображаться между стартовой страницей инсталлятора и страницей процесса выполнения. Добавим в код скрипта эти самые функции,код fnCustomDestroy оставим пока пустым, а в fnCustomInit внесем код создания и отображения страницы при помощи модуля nsDialogs:
!include "MUI.nsh"
SetCompress off

!insertmacro MUI_PAGE_WELCOME
Page custom fnCustomInit fnCustomDestroy
!insertmacro MUI_PAGE_INSTFILES
!insertmacro MUI_PAGE_FINISH
!insertmacro MUI_LANGUAGE "Russian"

Name "Winreview.ru"
OutFile "winreview.exe"
ShowInstDetails show

Var Dialog

Function fnCustomInit
nsDialogs::Create 1018
Pop $Dialog
nsDialogs::Show
FunctionEnd

Function fnCustomDestroy
FunctionEnd

Section
DetailPrint "Hello from winreview.ru"
SetAutoClose false
SectionEnd


Итак, вызов nsDialogs::Create 1018 непосредственно создает новую страницу в нашем инсталляторе. Про цифру 1018 официальная документация гласит вот что:
nsDialogs::Create принимает только один параметр. Это очень специфическая функция, для простоты понимания скажем, что её параметр всегда должен быть равен 1018.

Функция возвращает дескриптор созданной страницы в переменную $Dialog, заранее нами объявленную. После того как страница создана, её надо отобразить на экране — вызываем nsDialogs::Show.


Добавляем элементы управления

Для добавления элементов управления на нашу страницу нам придется подключить заголовочный файл sDialogs.nsh:
!include "nsDialogs.nsh"


Добавление контролов производится вызовом макросов вида  ${NSD_Create*}, например:
 ${NSD_CreateLabel} 0 0 100% 12u "Hello, welcome to nsDialogs!"

Макросы возвращают дескриптор созданного элемента управления, по которому к нему можно обращаться далее в коде скрипта. Параметры вызова в общем случае таковы:
 ${NSD_CreateLabel} <координатаХ> <координатаУ> <Ширина> <Высота> <”Текст”>


Координаты, ширина и высота могут быть заданы в трех единицах измерения: пиксели, единицы измерения диалога(dialog units) или проценты от пространства окна страницы. Они могут иметь и отрицательные значения, что указывает, что отсчёт величины будет в обратную сторону, т.е. снизу или справа.

Указание размеров контролов в dialog units особенно полезны, так как отлично масштабируют размеры элементов управления под разные DPI.

Итак, можно создать следующие элементы управления при помощи макросов ${NSD_Create*}:
Hline — горизонтальная линия
Vline — вертикальная линия
Label - надпись
Icon - значок(ICO)
Bitmap – картинка BMP
BrowseButton – кнопка «...»
Link - ссылка
Button - кнопка
GroupBox — контейнер группы
CheckBox - флажок
RadioButton — зависимый флажок-точка
Text — текстовое поле
Password — поле ввода пароля
Number - цифра
FileRequest — поле ввода имени файла
DirRequest — поле ввода папки
ComboBox — выпадающий список с возможностью ввода текста
DropList — выпадающий список с фиксированными значениями
ListBox — список значений
ProgressBar — индикатор выполнения

Добавим в наш скрипт пару-тройку элементов управления. Заведем три переменные:
Var Label
Var Text
Var CheckBox

И код создания контролов в функцию fnCustomInit

Function fnCustomInit
nsDialogs::Create 1018
Pop $Dialog

${NSD_CreateLabel} 0 5u 100u 10u "Это надпись"
Pop $Label

${NSD_CreateText} 0 20u 100% 15u "Здесь можно печатать..."
Pop $Text

${NSD_CreateCheckBox} 0 45u 100u 10u "Можно отметить флажком"
Pop $CheckBox

nsDialogs::Show
FunctionEnd


Обработка состояния элементов управления

Элементы управления мы добавили, замечательно. Теперь мы хотим узнать, внес ли пользователь в них какую-либо информацию. Сделаем мы это, изменив доселе пустую функцию fnCustomDestroy. Что же туда написать ?
Модуль nsDialogs предоставляет следующие макросы для работы с состояниями контролов:
 ${NSD_GetText} - считывает текст контрола
 ${NSD_GetState} - считывает состояние «флажка» - Radiobutton или Checkbox.

Мы объявили переменные для каждого контрола, которые хранят дескриптор контрола. Сейчас мы будет их использовать.

Синтаксис макросов:

${NSD_GetText} <имя_переменной_с_дескриптором_контрола> <имя_переменной_для_хранения_значения>${NSD_GetState} <имя_переменной_с_дескриптором_контрола> <имя_переменной_для_хранения_значения>

Для того, чтобы прочитать текст из поля ввода в нашем примере, следует написать такой код:
${NSD_GetText} $Text $R0

Текст из поля будет считан в переменную $R0

По аналогии обработаем оставшиеся контролы, не забывая использовать  ${NSD_GetState} для Checkbox

Function fnCustomDestroy
${NSD_GetText} $Label $R0
StrCpy $R1 "Текст надписи:$R0$\n"
${NSD_GetText} $Text $R0
StrCpy $R1 "$R1Текст в поле ввода:$R0$\n"
${NSD_GetState} $CheckBox $R0
StrCpy $R1 "$R1Состояние флажка:$R0$\n"
MessageBox MB_OK $R1
FunctionEnd


Обработка событий элементов управления
Вы можете обработать события, возникающие при взаимодействии пользователя с контролами. Модуль nsDialog позволяет для этих целей использовать макросы ${NSD_OnClick} и ${NSD_OnChange}. Синтаксис таков:
${NSD_OnChange} <имя_переменной_с_дескриптором_контрола> <имя_функции>Подобный вызов макроса приведет к выполнению указанной функции при изменении состояния контрола.
Например:
Function fnCustomInit
nsDialogs::Create 1018
Pop $Dialog

${NSD_CreateLabel} 0 5u 100u 10u "Это надпись"
Pop $Label

${NSD_CreateText} 0 20u 100% 15u "Здесь можно печатать..."
Pop $Text
${NSD_OnChange} $Text fnTextChange

${NSD_CreateCheckBox} 0 45u 100u 10u "Можно отметить флажком"
Pop $CheckBox

nsDialogs::Show
FunctionEnd

Function fnTextChange
Pop $1 
${NSD_GetText} $Text $R0
${NSD_SetText} $Label "Текст в поле ввода: $R0"
FunctionEnd


При помощи макроса ${NSD_SetText} в данном примере текст надписи меняется на то, что ввел пользователь в поле ввода.

Обратите внимание на строку Pop $1. Документация гласит, что дескриптор контрола должен быть прочитан из стэка во избежание его(стэка) повреждения. При изменении состояния контрола он "вынимается" командой Pop $1 из стека в переменную $1 в функции, определенной на событии OnChange.

Резюме
Мы рассмотрели базовый принцип работы с модулем nsDialogs. Естественно, его возможности не ограничиваются приведенными здесь простейшими примерами кода. Полное описание модуля вы найдете по адресу http://nsis.sourceforge.net/Docs/nsDialogs/Readme.html, правда, на английском языке. Тем не менее, документация содержит много полезных примеров, которые позволят даже без знания английского разобраться с nsDialogs.