Последнее обновление: 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.