新生代的用户界面设计工具
目录表
介绍
nsWindows nsWindows 允许在安装程序中创建自定义窗口。居于内置的窗口之上,nsWindows
能够创建包含任何类型的以任意形式排列的控件的窗口。它能够创建简至仅一个控件的窗口,也能创建满足用户需求的版面。
nsWindows 是一个新的 NSIS 插件,自版本 NSIS 2.42 被引入。nsWindows 不使用 INI 文件,因此执行速度要比 InstallOptions
快得多。与脚本的整合度更紧密也更自然了棗创建控件是通过使用插件的功能实现的,而通告则是直接在脚本中调用一个函数来实现的。不象
InstallOptions 那样,它没有预先定义的可能用到的控件类型并实现较低层次的 Windows API
访问,每一种类型的控件均能被创建并且窗口的定制具有更高的自由度。
使用 nsWindows 越灵活的同时,没有 Win32 API
知识的用户就会觉得越复杂。这可通过创建预定义函数库解决。函数库在脚本中定义,可允许进行控件的创建和处理。这样,新手可以简易地体会其易用性,而高级用户仍可通过修改函数库来体会其核心功能的强大。
脚本指南,从零开始
基本脚本
在使用之初,让我们先创建一个基本的脚本作为我们的骨架。
Name nsWindows
OutFile nsWindows.exe
XPStyle on
Page instfiles
Section
DetailPrint "hello world"
SectionEnd
自定义窗口
现在轮廓已基本搞定,该让我们的 nsWindows 上场了!第一个调用必须总是
nsWindows::Create。它将在该窗口中创建一个对话框,并在堆栈中返回其 HWND
值。其结果必须从堆栈中被弹出以免堆栈出错。若结果为 error,对话框将不会被创建。
nsWindows::Create 接受5个参数。它有一个特殊的功能,但为了保持此教程的简易性,最后一个参数值一般规定为 1018。
HWND 是一个标识当前窗口唯一性的数字,可用于 SendMessage、SetCtlColors 和 Win32
API。
!include nsWindows.nsh
Name nsWindows
OutFile nsWindows.exe
XPStyle on
Var hWindow
Page custom nsWindowsPage
Page instfiles
Function nsWindowsPage
nsWindows::Create $hwndparent ${dwExStyle} ${dwStyle} "hello world" 1018
Pop $hWindow
${If} $hWindow == error
Abort
${EndIf}
FunctionEnd
Section
DetailPrint "hello world"
SectionEnd
显示窗口
现在窗口已经创建,该让她露脸了!这次使用的是
${NSW_Show}。此函数直至用户点击关闭按钮后才会返回。
!include nsWindows.nsh
Name nsWindows
OutFile nsWindows.exe
XPStyle on
Var hWindow
Page custom nsWindowsPage
Page instfiles
Function nsWindowsPage
nsWindows::Create $hwndparent ${dwExStyle} ${dwStyle} "hello world" 1018
Pop $hWindow
${If} $hWindow == error
Abort
${EndIf}
nsWindows::Show
FunctionEnd
Section
DetailPrint "hello world"
SectionEnd
添加控件
此时编译并运行最后修改的脚本得到的将只是一个没有用处的空白窗口。因此我们也应当在该窗口上添加一些控件。要实现此目的,我们可使用头文件
nsWindows.nsh 中的宏 ${NSW_Create*}。这些宏,每个都带有
5 个参数 - x, y, width, height 和 text. 每个宏也都会返回一个值到堆栈,那就是新控件的 HWND。如同对话框的
HWND,它必须从堆栈中被弹出并保存下来。
宏使用的所有尺寸单位均可使用以下三种单位类型中的任一种棗像素、对话框单位 或
对话框尺寸的百分比。你可以指定负值,这表示距离是从右端或底部算起。要使用对话框单位,数值后面必须加上后缀符
u。要使用百分比单位,数值后面必须加上百分符 - %。此外,有无其它的后缀符均表示像素。
使用对话框单位作为尺寸单位,能够保证在用户不同的字体或 DPI 设置下均能完美地显示对话框。
!include nsWindows.nsh
!include LogicLib.nsh
Name nsWindows
OutFile nsWindows.exe
XPStyle on
Var hWindow
Var Label
Var Text
Page custom nsWindowsPage
Page instfiles
Function nsWindowsPage
${NSW_CreateWindow} $hWindow "hello world" 1018
${If} $hWindow == error
Abort
${EndIf}
${NSW_CreateLabel} 0 0 100% 12u "Hello, welcome to nsWindows!"
Pop $Label
${NSW_CreateText} 0 13u 100% -13u "Type something here..."
Pop $Text
${NSW_Show}
FunctionEnd
Section
DetailPrint "hello world"
SectionEnd
有效的能用 ${NSW_Create*}
来创建的控件类型为:
- HLine
- VLine
- Label
- Icon
- Bitmap
- BrowseButton
- Link
- Button
- GroupBox
- CheckBox
- RadioButton
- Text
- Memo
- Password
- FileRequest
- DirRequest
- ComboBox
- DropList
- ListBox
控件状态
现在我们有了一些用户可以参与互动的控件,那么让我们看看用户到底对她们都干了些什么吧。要实现此目的,我们首先要添加一个离开回调
(leave callback) 函数到我们的窗口。在该函数中,我们需要知道我们所创建并显现在用户面前的 Text
控件的状态。要实现此目的,我们要使用宏 ${NSW_GetText}。对于
RadioButton 和 CheckBox 控件则要使用宏 ${NSW_GetState}。
注意并非所有的控件都支持 ${NSW_GetText},一些控件需要使用特定讯息(在
WinMessages.nsh 中定义)来进行特殊的处理。例如 ListBox 控件需要使用 LB_GETCURSEL 和
LB_GETTEXT。nsWindows.nsh 中的宏集将会及时地补充许许多多的宏来处理更多的此类事情。
!include nsWindows.nsh
!include LogicLib.nsh
Name nsWindows
OutFile nsWindows.exe
XPStyle on
Var hWindow
Var Label
Var Text
Page custom nsWindowsPage
Page instfiles
Function nsWindowsPage
${NSW_CreateWindow} $hWindow "hello world" 1018
${If} $hWindow == error
Abort
${EndIf}
${NSW_CreateLabel} 0 0 100% 12u "Hello, welcome to nsWindows!"
Pop $Label
${NSW_CreateText} 0 13u 100% -13u "Type something here..."
Pop $Text
GetFunctionAddress $0 nsWindowsPageLeave
nsWindows::OnBack $0
${NSW_Show}
FunctionEnd
Function nsWindowsPageLeave
${NSW_GetText} $Text $0
MessageBox MB_OK "You typed:$\n$\n$0"
FunctionEnd
Section
DetailPrint "hello world"
SectionEnd
实时通告
nsWindows 让人兴奋的新功能之一就是对话框状态改变时的回调函数通告。nsWindows
能够调用脚本中定义的一个函数以响应诸如文本区段的改变和某按钮的点击等用户行为。需求。要使得 nsWindows
通告我们事件的发生,我们可以使用 ${NSW_OnClick}
和 ${NSW_OnChange}。并非所有的控件都支持事件通告。例如
label 控件没有任何的通告。
当回调函数被调用时,将在堆栈中返回控件的 HWND
值,其结果必须从堆栈中被弹出以免堆栈出错。在这个简易的脚本中似乎看不出有多大用处。但是在一个大型的脚本中几个控件关联到相同的回调函数,HWND
值能够区分出哪个控件触发了该事件。
下面的例子将在用户输入 hello 到文本框中时通知用户。
!include nsWindows.nsh
!include LogicLib.nsh
Name nsWindows
OutFile nsWindows.exe
XPStyle on
Var hWindow
Var Label
Var Text
Page custom nsWindowsPage
Page instfiles
Function nsWindowsPage
${NSW_CreateWindow} $hWindow "hello world" 1018
${If} $hWindow == error
Abort
${EndIf}
${NSW_CreateLabel} 0 0 100% 12u "Hello, welcome to nsWindows!"
Pop $Label
${NSW_CreateText} 0 13u 100% -13u "Type something here..."
Pop $Text
${NSW_OnChange} $Text nsWindowsPageTextChange
GetFunctionAddress $0 nsWindowsPageLeave
nsWindows::OnBack $0
${NSW_Show}
FunctionEnd
Function nsWindowsPageLeave
${NSW_GetText} $Text $0
MessageBox MB_OK "You typed:$\n$\n$0"
FunctionEnd
Function nsWindowsPageTextChange
Pop $1 # $1 == $ Text
${NSW_GetText} $Text $0
${If} $0 == "hello"
MessageBox MB_OK "right back at ya!"
${EndIf}
FunctionEnd
Section
DetailPrint "hello world"
SectionEnd
储存数据
到目前为止,我们有了一个具备一些基本输入控件的窗口。但是,当用户关闭窗口再重建时会发生什么情况呢?按照现有的代码,用户的输入将不会被储存下来。要储存它们,我们可以使用已有的离开回调函数来储存用户对的选择到变量并在下一次创建该控件时传递这些变量。更好的一个例子,我们也可以添加一个
Checkbox 控件到窗口,并使用 ${NSW_GetState}
和 ${NSW_SetState}
来获取和设置其状态。
为了更直观一些,我们将要删除先前步骤中的一些通告。
!include nsWindows.nsh
!include LogicLib.nsh
Name nsWindows
OutFile nsWindows.exe
XPStyle on
Var hWindow
Var Label
Var Text
Var Text_State
Var Checkbox
Var Checkbox_State
Page custom nsWindowsPage
Page license
Page instfiles
Function .onInit
StrCpy $Text_State "Type something here..."
FunctionEnd
Function nsWindowsPage
${NSW_CreateWindow} $hWindow "hello world" 1018
${If} $hWindow == error
Abort
${EndIf}
${NSW_CreateLabel} 0 0 100% 12u "Hello, welcome to nsWindows!"
Pop $Label
${NSW_CreateText} 0 13u 100% 12u $Text_State
Pop $Text
${NSW_CreateCheckbox} 0 30u 100% 10u "&Something"
Pop $Checkbox
${If} $Checkbox_State == ${BST_CHECKED}
${NSW_Check} $Checkbox
${EndIf}
# alternative for the above ${If}:
#${NSW_SetState} $Checkbox_State
GetFunctionAddress $0 nsWindowsPageLeave
nsWindows::OnBack $0
${NSW_Show}
FunctionEnd
Function nsWindowsPageLeave
${NSW_GetText} $Text $Text_State
${NSW_GetState} $Checkbox $Checkbox_State
StrCpy $R9 $hWindow
Call nsWindowsPage
IsWindow $R9 0 +2
System::Call 'user32::DestroyWindow(i $R9)'
FunctionEnd
Section
DetailPrint "hello world"
SectionEnd
函数参考
Create
nsWindows::Create HWND dwExStyle dwStyle Title rect
${NSW_CreateWindow} $hWindow Title rect
${NSW_CreateWindowEx} $hWindow HWND dwExStyle dwStyle Title rect
新建一个窗口。
$hWindow 用于保存新建窗口句柄的变量 。
HWND 指定了新创建窗口的父窗口,通常是 $HWNDPARENT 。
dwExStyle 指定了新创建窗口的扩展风格 。
dwStyle 指定了新创建窗口的窗口风格 。
Title 指定了新创建窗口的窗口名称。
rect 指定了位置将被模仿的控件的标识符。此处通常使用 1018,用其模仿内建页面的创建。
返回新对话框的 HWND 值到堆栈或 error。
CreateControl
nsWindows::CreateControl class style
extended_style x y width height
text
${NSW_Create*} left top
width height
text
在当前对话框中新建一个控件。此函数正常工作的前提条件是对话框必须存在,故 nsWindows::Create
必须在此函数之前调用。
返回新控件的 HWND 值到堆栈或 error。
Show
nsWindows::SHow
${NSW_Show}
显示窗口。一旦调用它将结束 nsWindows::Create、nsWindows::CreateControl 及其它
nsWindows 函数。
无返回值。
SelectFileDialog
nsWindows::SelectFileDialog mode
initial_selection filter
显示一个文件选择对话框。若 mode 设置为 save,将显示一个保存文件对话框,若 mode
设置为 open,将显示一个打开文件对话框。filter 为有效的文件过滤器列表,用 |
分隔。如果没有指定,则使用默认的 所有文件|*.*。
返回所选中的文件到堆栈,或当用户取消操作时返回空字串。
SelectFolderDialog
nsWindows::SelectFolderDialog title
initial_selection
显示一个文件夹选择对话框。
返回所选中的文件夹到堆栈,或当用户取消操作时返回空字串。
SetRTL
nsWindows::SetRTL rtl_setting
打开/关闭 从右到左 模式。若 rtl_setting = 0,关闭。若 rtl_setting =
1,打开。此函数必须在任何的 nsWindows::CreateControl 之前调用。
无返回值。
GetUserData
nsWindows::GetUserData control_HWND
返回与控件相关联的用户数据到堆栈。使用 nsWindows::SetUserData 设置此数据。
SetUserData
nsWindows::SetUserData control_HWND
data
关联数据到控件。使用 nsWindows::GetUserData 获取此数据。
无返回值。
SetTransParent
nsWindows::SetTransparent control_HWND
Transparency
设置窗口的百分比透明度。注意:此函数仅能在 2K 或者以上系统中使用!
无返回值。
Transparency 为不透明度百分比,取值范围为0~100
OnBack
nsWindows::OnBack function_address
设置关闭按钮的回调函数。此函数在用户点击关闭按钮时调用。在此函数中调用
Abort 能阻止用户回关闭该窗口。
使用 GetFunctionAddress 获取期望的回调函数地址。
无返回值。
OnChange
nsWindows::OnChange control_HWND
function_address
设置一个更改通告回调函数到所指定的控件。当控件状态被更改时,该函数将被调用,并返回控件的 HWND 值到堆栈。
使用 GetFunctionAddress 获取期望的回调函数地址。
无返回值。
OnClick
nsWindows::OnClick control_HWND
function_address
设置一个点击通告回调函数到所指定的控件。当控件被点击时,该函数将被调用,并返回控件的 HWND 值到堆栈。
使用 GetFunctionAddress 获取期望的回调函数地址。
无返回值。
OnNotify
nsWindows::OnNotify control_HWND
function_address
设置一个通告回调函数到所指定的控件。当控件接收到 WM_NOTIFY 讯息时,该函数将被调用,并返回控件的 HWND 值、通告代码和
MNHDR 结构指针到堆栈。
使用 GetFunctionAddress 获取期望的回调函数地址。
无返回值。
宏参考
nsWindows.nsh 包含了一系列的宏,这将使得 nsWindows
的使用变得更简单一些。下面是有关这些宏的用途、语法、输入和输出的简要介绍。
NSW_Create*
${NSW_Create*} x y width height
text
在当前对话框中新建一个控件。此函数正常工作的前提条件是对话框必须存在,故 nsWindows::Create
必须在此函数之前调用。
有效的变量:
- ${NSW_CreateHLine}
- ${NSW_CreateVLine}
- ${NSW_CreateLabel}
- ${NSW_CreateIcon}
- ${NSW_CreateBitmap}
- ${NSW_CreateBrowseButton}
- ${NSW_CreateLink}
- ${NSW_CreateButton}
- ${NSW_CreateGroupBox}
- ${NSW_CreateCheckBox}
- ${NSW_CreateRadioButton}
- ${NSW_CreateText}
- ${NSW_CreateMemo}
- ${NSW_CreatePassword}
- ${NSW_CreateNumber}
- ${NSW_CreateFileRequest}
- ${NSW_CreateDirRequest}
- ${NSW_CreateComboBox}
- ${NSW_CreateDropList}
- ${NSW_CreateListBox}
返回新对话框的 HWND 值到堆栈或 error。
NSW_OnBack
${NSW_OnBack} control_HWND
function_address
参阅 OnBack
了解更多资料。
NSW_OnChange
${NSW_OnChange} control_HWND
function_address
参阅 OnChange
了解更多资料。
参阅 Real-time
Notification 了解使用实例。
NSW_OnClick
${NSW_OnClick} control_HWND
function_address
参阅 OnClick
了解更多资料。
NSW_OnNotify
${NSW_OnNotify} control_HWND
function_address
参阅 OnNotify
了解更多资料。
NSW_AddStyle
${NSW_AddStyle} control_HWND style
添加一个或多个窗口外观样式到控件。多个外观样式用分隔符 `|' 隔开。
请到 MSDN 获取样式资料。
NSW_AddExStyle
${NSW_AddExStyle} control_HWND style
添加一个或多个窗口外观样式到控件。多个外观样式用分隔符 `|' 隔开。
请到 MSDN 获取样式资料。
NSW_GetText
${NSW_GetText} control_HWND
output_variable
返回某个控件的 text 状态并储存到 output_variable。尤其适用于 Text 控件。
参阅 Control
State 了解使用实例。
NSW_SetText
${NSW_SetText} control_HWND text
设置某个控件的 text 状态。
NSW_SetTextLimit
${NSW_SetTextLimit} control_HWND limit
设置 Text 控件的输入长度限制。
NSW_GetState
${NSW_GetState} control_HWND
output_variable
返回 CheckBox 和 RadioButton 控件的状态。可能的输出值为 ${BST_CHECKED} 和
${BST_UNCHECKED}。
参阅 Memory
了解使用实例。
NSW_SetState
${NSW_SetState} control_HWND state
设置 CheckBox 和 RadioButton 控件的状态。可能的 state 参数数据为 ${BST_CHECKED}
和 ${BST_UNCHECKED}。
参阅 Memory
了解使用实例。
NSW_Check
${NSW_Check} control_HWND
勾选一个 CheckBox 和 RadioButton 控件。等同于带 ${BST_CHECKED} 参数调用
${NSW_SetState}。
NSW_Uncheck
${NSW_Uncheck} control_HWND
取消勾选一个 CheckBox 和 RadioButton 控件。等同于带 ${BST_UNCHECKED} 参数调用
${NSW_SetState}。
参阅 Memory
了解使用实例。
NSW_CB_AddString
${NSW_CB_AddString} combo_HWND string
添加一个字符串到组合框(ComboBox)。
NSW_CB_SelectString
${NSW_CB_SelectString} combo_HWND
string
选择组合框(ComboBox)中的一个字符串。
NSW_LB_AddString
${NSW_LB_AddString} combo_HWND string
添加一个字符串到列表框(ListBox)。
NSW_LB_SelectString
${NSW_LB_SelectString} combo_HWND
string
选择列表框(ListBox)中的一个字符串。
NSW_SetFocus
${NSW_SetFocus} control_HWND
将控件设置为焦点。
NSW_SetImage
${NSW_SetImage} control_HWND image_path
output_variable
自 image_path 载入一个图像并显示在已使用 ${NSW_CreateBitmap}
创建的 control_HWND 位置上。图像句柄储存在 output_variable 中,一旦不需要时可使用
${NSW_FreeImage}
释放。
必须在图像被释放到用户系统之后才能调用此宏。推荐释放图像到 $PLUGINSDIR 。
!include nsWindows.nsh
Name nsWindows
OutFile nsWindows.exe
XPStyle on
Page instfiles nsWindowsImage
Var hWindow
Var Image
Var ImageHandle
Function .onInit
InitPluginsDir
File /oname=$PLUGINSDIR\image.bmp "${NSISDIR}\Contrib\Graphics\Header\nsis-r.bmp"
FunctionEnd
Function nsWindowsImage
${NSW_CreateWindow} $hWindow "nsWindowsImage" 1018
${If} $hWindow == error
Abort
${EndIf}
${NSW_CreateBitmap} 0 0 100% 100% ""
Pop $Image
${NSW_SetImage} $Image $PLUGINSDIR\image.bmp $ImageHandle
${NSW_Show}
; ${NSW_FreeImage} $ImageHandle
FunctionEnd
Section
SectionEnd
NSW_SetStretchedImage
${NSW_SetStretchedImage} control_HWND image_path
output_variable
载入并显示一个图像,有点类似 ${NSW_SetImage},但它能拉伸图像以填充控件的位置范围。
NSW_ClearImage
${NSW_ClearImage} control_HWND
清除控件图像。
NSW_FreeImage
${NSW_FreeImage} image_handle
释放一个先前使用 ${NSW_SetImage}
或 ${NSW_SetStretchedImage}
加载的图像句柄。
常见问题
- Q: nsWindows 能否处理 InstallOptions INI 文件?
A: nsWindows.nsh 中包含的一个名为 CreateWindowFromINI 的函数能够根据
INI 文件创建 nsWindows 对话框。它能处理 InstallOptions 支持的各种控件类型,但暂不会处理 flags
标记或通告。Examples\nsWindows\InstallOptions.nsi 显现了此函数的使用方法。
未来将也会有一个函数来创建脚本自身。