内置页面的定制
”现代用户界面“中提供了一些页面,您可以通过插入宏的指令(如:!insertmacro MUI_PAGE_COMPONENTS)来把相应的页面加入到安装脚本,在安装过程中,插入的页面将按照先后顺序出现,这些提供的安装页面如下:
MUI_PAGE_WELCOME
MUI_PAGE_LICENSE textfile
MUI_PAGE_COMPONENTS
MUI_PAGE_DIRECTORY
MUI_PAGE_STARTMENU pageid variable
MUI_PAGE_INSTFILES
MUI_PAGE_FINISH
通过NSIS用户手册我们知道每个内建的页面都有三个回调函数。一个预置函数、一个显示创建函数和一个离开函数。预置函数在页面被创建之前被直接的调用,显示函数在页面被创建后且在显示之前被直接调用,离开函数在用户按下下一页按钮之后并且在页面离开之前被直接调用。
类似的“现代用户界面”,查看NSIS Modern User Interface的页面自定义函数有以下三种类型,它们在插入页面宏之前设置(!insertmacro MUI_PAGE_***):
MUI_PAGE_CUSTOMFUNCTION_PRE function ; 在其间你可以初始化变量或者决定下面插入的页面是否要跳过
MUI_PAGE_CUSTOMFUNCTION_SHOW function ;在其间界面上所有控件的句柄都可以获得,你可以自定义界面的任何部分
MUI_PAGE_CUSTOMFUNCTION_LEAVE function ;在其间可以校验用户的输入
下面是一个例子,对区段变量进行设置(包括对区段组展开,区段设置成只读、选中或不选),体现在组件界面中就是组件的只读、选中或不选:
!define MUI_PAGE_CUSTOMFUNCTION_PRE ComponentsPre
!insertmacro MUI_PAGE_COMPONENTS
; 组件页面函数开始----------------------
Function ComponentsPre
; 设置区段选中并且只读
IntOp $0 ${SF_SELECTED} | ${SF_RO}
SectionSetFlags ${SEC01} $0
SectionSetFlags ${SEC02} $0
SectionSetFlags ${SEC03} $0
SectionSetFlags ${SEC04} $0
; 如果选择启用Exchange功能则选中,否则不选
${If} $IsEnableExchange == ${BST_CHECKED}
SectionSetFlags ${SEC05} $0
${Else}
SectionSetFlags ${SEC05} ${SF_RO}
${EndIf}
; 如果选择启用Lync功能则选中,否则不选
${If} $IsEnableLync == ${BST_CHECKED}
SectionSetFlags ${SEC06} $0
${Else}
SectionSetFlags ${SEC06} ${SF_RO}
${EndIf}
SectionSetFlags ${SEC07} $0
; 设置区段组展开
IntOp $1 ${SF_SECGRP} | ${SF_EXPAND}
IntOp $2 $1 | ${SF_RO}
SectionSetFlags ${SECG01} $2
FunctionEnd
; 组件页面函数结束----------------------
值得提一下的是指令(SectionSetFlags ${SEC01} $0)中变量${SEC01}是区段索引,定义了区段索引的新的区段如下所示:
Section "数据库配置" SEC01
; coding
SectionEnd
自定义页面
如果提供的这些内置页面不能满足您的需求,就需要您完全自定义页面了,您的自定义页面想出现在安装过程中,和内置页面一样,需要按照安装页面的的顺序插入页面。插入自定义页面的指令(参考NSIS用户手册,如:Page custom [创建函数] [离开函数] [标题] ),像我们这个实际应用中包含了10个页面,我们按照安装过程中页面出现的顺序插入页面指令,如下代码所示:
; 安装程序页面开始----------------------
; 欢迎页面
!insertmacro MUI_PAGE_WELCOME
; 许可页面
!insertmacro MUI_PAGE_LICENSE "Licence.Txt"
; 系统环境检查页面
Page custom SystemEnvironmentCheckInit SystemEnvironmentCheckLeave
; 数据库服务器配置页面
; Page custom DBServiceSettingsInit DBServiceSettingsLeave
; AD服务器配置页面
Page custom ADServiceSettingsInit ADServiceSettingsLeave
; Exchange服务器配置页面
Page custom ExchangeServiceSettingsInit ExchangeServiceSettingsLeave
; Lync服务器配置页面
Page custom LyncServiceSettingsInit LyncServiceSettingsLeave
; 目录选择页面
!insertmacro MUI_PAGE_DIRECTORY
; 组件页面
!define MUI_PAGE_CUSTOMFUNCTION_PRE ComponentsPre
!insertmacro MUI_PAGE_COMPONENTS
; 安装记录页面
!insertmacro MUI_PAGE_INSTFILES
; 完成页面
!insertmacro MUI_PAGE_FINISH
; 安装程序页面结束----------------------
下面我们以自定义页面”Exchange服务器配置页面“为例来说明怎么创建页面(包含了一系列控件和相关布局),设置控件初始状态、获取控件的数据、校验控件数据来控制下一步动作等。
这个页面中有”是否启用邮箱功能“选项,如果启用邮箱,需要填写Exchange版本、Exchange服务器地址、管理员账户和账户密码等信息,默认是启用邮箱状态,Exchange版本默认是2013,切换”是否启用邮箱功能“选项的状态,会相应的改变邮箱设置的相关信息的可用/不可用状态,如果启用邮箱,信息输入不全则点击下一步时需要有类似”请输入信息再进行下一步安装“的提示,信息输入校验没问题才进行下一步安装。
根据插入的自定义页面指令(Page custom ExchangeServiceSettingsInit ExchangeServiceSettingsLeave),我们知道这里有两个基本的函数,一个是创建函数(ExchangeServiceSettingsInit),一个是离开函数(ExchangeServiceSettingsLeave)。结合需求在创建函数中我们可以创建页面、创建并布局页面上的控件、设置控件初始状态、设置控件动作等,在离开函数中我们可以获取控件数据、校验数据、控制流程走向(是继续下一步还是停止执行脚本)、保存数据等。
在这里我们创建页面使用的是nsDialogs插件(可以参考nsDialogs和nsDialogs FAQ),需要包含插件头文件指令(!include nsDialogs.nsh),对应的NSIS安装目录的Plugins文件夹(如:C:\Program Files (x86)\NSIS\Plugins)会有nsDialogs.dll文件。INI文件也可以用来创建自定义页面,但因为INI既不灵活又不高效已经被nsDialogs取代啦。具体的创建页面和控件的指令参考手册说的很清楚了,不再累述。
现在重点说一下创建控件的布局,创建控件的一般指令:${NSD_Create*} x y width height text, 这里面关于控件的定位和大小有四个参数控制,X坐标、Y坐标、宽度和高度,取值可以有三种类型,一种是像素(就是我们通常的px)、一种是对话框单位(必须在数据后加后缀u)、再就是对话框大小的百分比(必须在数据后加后缀%),我这里的建议是使用百分比,这样更好控制布局。
另外一个重点要说的是创建完控件后,会返回一个值放入堆栈中,这个值就是控件的句柄(即HWND),我们以后要设置或获取控件的值等一切针对新创建控件的操作都需要句柄,所以我们需要从堆栈里弹出这个值保存在用户变量中(如指令:Pop $TxtExchangeServerIP),设置控件初始值指令如:${NSD_SetText} $TxtExchangeServerIP “10.0.1.4”,获取控件值如:${NSD_GetText} $TxtExchangeServerIP $ExchangeServerIP等。
针对控件的事件这里我们定义了一个单击事件,如:${NSD_OnClick} $ChxEnableExchange EnableExchangeClick,单击事件处理函数EnableExchangeClick中会根据“是否启用邮箱功能”选项的值来设置其他控件的启用/禁用状态。涉及到选项(如:单选框、复选框)的状态属于两个值中(选中${BST_CHECKED},未选中${BST_UNCHECKED})之一,设置控件的启用/禁用状态使用指令:SendMessage $TxtExchangeServerIP ${EM_SETREADONLY} 0 0/SendMessage $TxtExchangeServerIP ${EM_SETREADONLY} 1 0。
获取文本框控件输入的数据值时我们需要过去掉输入字符串的前后空格和回车换行符等,我们可以自己写一个处理字符串的方法并且宏定义后保存为Trim.nsh文件后使用,当然我们需要先引入头文件(指令:!include Trim.nsh),使用例如:${Trim} $4 $0 第一个参数是处理后的字符串,第二个参数是源字符串。校验输入后我们可以把获取的控件值保存在一个有意义的变量中供其他地方调用,如:StrCpy $ExchangeServerIP $4
下面是完整的创建”Exchange服务器配置页面“的代码,以供参考:
; Exchange服务器配置页面函数开始----------------------
/*设置项:是否启用邮箱功能、Exchange版本默认Exchange 2013、
Exchange服务器地址、管理员账户、账户密码
*/
Var ChxEnableExchange
Var LabExchangeServerIP
Var LabExchangeVersion
Var LabExchangeUser
Var LabExchangeUserPwd
Var TxtExchangeServerIP
Var TxtExchangeVersion
Var TxtExchangeUser
Var TxtExchangeUserPwd
Function ExchangeServiceSettingsInit
StrCpy $PAGE_TITLE "Exchange服务器配置"
StrCpy $PAGE_SUBTITLE "当选择启用邮箱功能时,需要输入以下内容(都为必填项):\
Exchange服务器地址、Exchange版本、管理员账户、账户密码"
!insertmacro MUI_HEADER_TEXT $PAGE_TITLE $PAGE_SUBTITLE
nsDialogs::Create 1018
Pop $Dialog
${If} $Dialog == error
Abort
${EndIf}
${NSD_CreateGroupBox} 0 0 100% 100% "设置项"
Pop $GBox
${NSD_CreateCheckbox} 35% 5% 40% 20% "启用Exchange相关功能"
Pop $ChxEnableExchange
${NSD_CreateLabel} 10% 27% 20% 20% "服务器地址:"
Pop $LabExchangeServerIP
${NSD_CreateLabel} 10% 42% 20% 20% "版本:"
Pop $LabExchangeVersion
${NSD_CreateLabel} 10% 57% 20% 20% "管理员账户:"
Pop $LabExchangeUser
${NSD_CreateLabel} 10% 72% 20% 20% "账户密码:"
Pop $LabExchangeUserPwd
${NSD_CreateText} 35% 27% 60% 10% ""
Pop $TxtExchangeServerIP
${NSD_CreateText} 35% 42% 60% 10% "2013"
Pop $TxtExchangeVersion
${NSD_CreateText} 35% 57% 60% 10% ""
Pop $TxtExchangeUser
${NSD_CreatePassword} 35% 72% 60% 10% ""
Pop $TxtExchangeUserPwd
SendMessage $TxtExchangeVersion ${EM_SETREADONLY} 1 0
${NSD_SetState} $ChxEnableExchange ${BST_CHECKED}
${NSD_GetState} $ChxEnableExchange $IsEnableExchange
${NSD_OnClick} $ChxEnableExchange EnableExchangeClick
nsDialogs::Show
FunctionEnd
Function EnableExchangeClick
${NSD_GetState} $ChxEnableExchange $IsEnableExchange
${If} $IsEnableExchange == ${BST_CHECKED}
SendMessage $TxtExchangeServerIP ${EM_SETREADONLY} 0 0
SendMessage $TxtExchangeUser ${EM_SETREADONLY} 0 0
SendMessage $TxtExchangeUserPwd ${EM_SETREADONLY} 0 0
${Else}
SendMessage $TxtExchangeServerIP ${EM_SETREADONLY} 1 0
SendMessage $TxtExchangeUser ${EM_SETREADONLY} 1 0
SendMessage $TxtExchangeUserPwd ${EM_SETREADONLY} 1 0
${EndIf}
FunctionEnd
Function ExchangeServiceSettingsLeave
${If} $IsEnableExchange == ${BST_UNCHECKED}
Return
${EndIf}
${NSD_GetText} $TxtExchangeServerIP $0
${NSD_GetText} $TxtExchangeVersion $1
${NSD_GetText} $TxtExchangeUser $2
${NSD_GetText} $TxtExchangeUserPwd $3
; ${Trim} $trimmedString $originalString
${Trim} $4 $0
${Trim} $5 $1
${Trim} $6 $2
${Trim} $7 $3
${If} $4 == ""
${OrIf} $5 == ""
${OrIf} $6 == ""
${OrIf} $7 == ""
MessageBox MB_OK "请输入信息再进行下一步安装!"
Abort
${EndIf}
StrCpy $ExchangeServerIP $4
StrCpy $ExchangeVersion $5
StrCpy $ExchangeUser $6
StrCpy $ExchangeUserPwd $7
FunctionEnd
; Exchange服务器配置页面函数结束----------------------
该自定义页面执行效果截图如下: