NSIS nsDialogs 插件

介绍

    nsDialogs nsDialogs 允许在安装程序中创建自定义页面。居于内置的页面之上,nsDialogs 能够创建包含任何类型的以任意形式排列的控件的页面。它能够创建简至仅一个控件的页面,也能创建满足用户需求的版面。例如,Modern UI 2 使用 nsDialogs 来创建欢迎完成页面。

    nsDialogs 是一个新的 NSIS 插件,自版本 NSIS 2.29 作为 InstallOptions 的替代品被引入。nsDialogs 不使用 INI 文件,因此执行速度要比 InstallOptions 快得多。与脚本的整合度更紧密也更自然了棗创建控件是通过使用插件的功能实现的,而通告则是直接在脚本中调用一个函数来实现的。不象 InstallOptions 那样,它没有预先定义的可能用到的控件类型并实现较低层次的 Windows API 访问,每一种类型的控件均能被创建并且页面的定制具有更高的自由度。

    使用 nsDialogs 越灵活的同时,没有 Win32 API 知识的用户就会觉得越复杂。这可通过创建预定义函数库解决。函数库在脚本中定义,可允许进行控件的创建和处理。这样,新手可以简易地体会其易用性,而高级用户仍可通过修改函数库来体会其核心功能的强大。

脚本指南,从零开始

    基本脚本

      在使用之初,让我们先创建一个基本的脚本作为我们的骨架。

      Name nsDialogs
              OutFile nsDialogs.exe
              XPStyle on
              Page instfiles
              Section
              DetailPrint "hello world"
              SectionEnd

    自定义页面

      其次,我们将要添加一个自定义页面,在此我们可以使用 nsDialogs。nsDialogs 不能用于区段或自定义页面函数之外的任何函数中。

      Name nsDialogs
                  OutFile nsDialogs.exe
                  XPStyle on
                  Page custom nsDialogsPage
                  Page instfiles
                  Function nsDialogsPage
                  FunctionEnd
                  Section
                  DetailPrint "hello world"
                  SectionEnd

    创建页面

      现在轮廓已基本搞定,该让我们的 nsDialogs 上场了!第一个调用必须总是 nsDialogs::Create。它将在该页面中创建一个对话框,并在堆栈中返回其 HWND 值。其结果必须从堆栈中被弹出以免堆栈出错。若结果为 error,对话框将不会被创建。

      nsDialogs::Create 类似 nsDialogs::Show 之外的其它函数,必须带 /NOUNLOAD 调用。

      nsDialogs::Create 接受一个参数。它有一个特殊的功能,但为了保持此教程的简易性,参数值总是规定为 1018。

      HWND 是一个标识当前对话框唯一性的数字,可用于 SendMessage、SetCtlColors 和 Win32 API。

      !include LogicLib.nsh
                      Name nsDialogs
                      OutFile nsDialogs.exe
                      XPStyle on
                      Var Dialog
                      Page custom nsDialogsPage
                      Page instfiles
                      Function nsDialogsPage
                      
                      nsDialogs::Create /NOUNLOAD 1018
                      Pop $Dialog
                      ${If} $Dialog == error
                      Abort
                      ${EndIf}
                      
                      FunctionEnd
                      Section
                      DetailPrint "hello world"
                      SectionEnd

    显示页面

      现在页面已经创建,该让她露脸了!这次使用的是 nsDialogs::Show。此函数直至用户点击下一步上一步取消按钮后才会返回。

      !include LogicLib.nsh
                          Name nsDialogs
                          OutFile nsDialogs.exe
                          XPStyle on
                          Var Dialog
                          Page custom nsDialogsPage
                          Page instfiles
                          Function nsDialogsPage
                          nsDialogs::Create /NOUNLOAD 1018
                          Pop $Dialog
                          ${If} $Dialog == error
                          Abort
                          ${EndIf}
                          
                          nsDialogs::Show
                          
                          FunctionEnd
                          Section
                          DetailPrint "hello world"
                          SectionEnd

    添加控件

      此时编译并运行最后修改的脚本得到的将只是一个没有用处的空白页面。因此我们也应当在该页面上添加一些控件。要实现此目的,我们可使用头文件 nsDialogs.nsh 中的宏 ${NSD_Create*}。这些宏,每个都带有 5 个参数 - x, y, width, height 和 text. 每个宏也都会返回一个值到堆栈,那就是新控件的 HWND。如同对话框的 HWND,它必须从堆栈中被弹出并保存下来。

      宏使用的所有尺寸单位均可使用以下三种单位类型中的任一种棗像素、对话框单位 或 对话框尺寸的百分比。你可以指定负值,这表示距离是从右端或底部算起。要使用对话框单位,数值后面必须加上后缀符 u。要使用百分比单位,数值后面必须加上百分符 - %。此外,有无其它的后缀符均表示像素。

      使用对话框单位作为尺寸单位,能够保证在用户不同的字体或 DPI 设置下均能完美地显示对话框。

      !include nsDialogs.nsh
                              !include LogicLib.nsh
                              Name nsDialogs
                              OutFile nsDialogs.exe
                              XPStyle on
                              Var Dialog
                              Var Label
                              Var Text
                              Page custom nsDialogsPage
                              Page instfiles
                              Function nsDialogsPage
                              nsDialogs::Create /NOUNLOAD 1018
                              Pop $Dialog
                              ${If} $Dialog == error
                              Abort
                              ${EndIf}
                              
                              ${NSD_CreateLabel} 0 0 100% 12u "Hello, welcome to nsDialogs!"
                              Pop $Label
                              ${NSD_CreateText} 0 13u 100% -13u "Type something here..."
                              Pop $Text
                              
                              nsDialogs::Show
                              FunctionEnd
                              Section
                              DetailPrint "hello world"
                              SectionEnd

      有效的能用 ${NSD_Create*} 来创建的控件类型为:

      • HLine
      • VLine
      • Label
      • Icon
      • Bitmap
      • BrowseButton
      • Link
      • Button
      • GroupBox
      • CheckBox
      • RadioButton
      • Text
      • Password
      • FileRequest
      • DirRequest
      • ComboBox
      • DropList
      • ListBox

    控件状态

      现在我们有了一些用户可以参与互动的控件,那么让我们看看用户到底对她们都干了些什么吧。要实现此目的,我们首先要添加一个离开回调 (leave callback) 函数到我们的页面。在该函数中,我们需要知道我们所创建并显现在用户面前的 Text 控件的状态。要实现此目的,我们要使用宏 ${NSD_GetText}。对于 RadioButton 和 CheckBox 控件则要使用宏 ${NSD_GetState}

      注意并非所有的控件都支持 ${NSD_GetText},一些控件需要使用特定讯息(在 WinMessages.nsh 中定义)来进行特殊的处理。例如 ListBox 控件需要使用 LB_GETCURSELLB_GETTEXT。nsDialogs.nsh 中的宏集将会及时地补充许许多多的宏来处理更多的此类事情。

      !include nsDialogs.nsh
                              !include LogicLib.nsh
                              Name nsDialogs
                              OutFile nsDialogs.exe
                              XPStyle on
                              Var Dialog
                              Var Label
                              Var Text
                              Page custom nsDialogsPage nsDialogsPageLeave
                              Page instfiles
                              Function nsDialogsPage
                              nsDialogs::Create /NOUNLOAD 1018
                              Pop $Dialog
                              ${If} $Dialog == error
                              Abort
                              ${EndIf}
                              ${NSD_CreateLabel} 0 0 100% 12u "Hello, welcome to nsDialogs!"
                              Pop $Label
                              ${NSD_CreateText} 0 13u 100% -13u "Type something here..."
                              Pop $Text
                              nsDialogs::Show
                              FunctionEnd
                              Function nsDialogsPageLeave
                              ${NSD_GetText} $Text $0
                              MessageBox MB_OK "You typed:$\n$\n$0"
                              FunctionEnd
                              Section
                              DetailPrint "hello world"
                              SectionEnd

    实时通告

      nsDialogs 让人兴奋的新功能之一就是对话框状态改变时的回调函数通告。nsDialogs 能够调用脚本中定义的一个函数以响应诸如文本区段的改变和某按钮的点击等用户行为。需求。要使得 nsDialogs 通告我们事件的发生,我们可以使用 ${NSD_OnClick}${NSD_OnChange}。并非所有的控件都支持事件通告。例如 label 控件没有任何的通告。

      当回调函数被调用时,将在堆栈中返回控件的 HWND 值,其结果必须从堆栈中被弹出以免堆栈出错。在这个简易的脚本中似乎看不出有多大用处。但是在一个大型的脚本中几个控件关联到相同的回调函数,HWND 值能够区分出哪个控件触发了该事件。

      下面的例子将在用户输入 hello 到文本框中时通知用户。

      !include nsDialogs.nsh
                                  !include LogicLib.nsh
                                  Name nsDialogs
                                  OutFile nsDialogs.exe
                                  XPStyle on
                                  Var Dialog
                                  Var Label
                                  Var Text
                                  Page custom nsDialogsPage nsDialogsPageLeave
                                  Page instfiles
                                  Function nsDialogsPage
                                  nsDialogs::Create /NOUNLOAD 1018
                                  Pop $Dialog
                                  ${If} $Dialog == error
                                  Abort
                                  ${EndIf}
                                  ${NSD_CreateLabel} 0 0 100% 12u "Hello, welcome to nsDialogs!"
                                  Pop $Label
                                  ${NSD_CreateText} 0 13u 100% -13u "Type something here..."
                                  Pop $Text
                                  ${NSD_OnChange} $Text nsDialogsPageTextChange
                                  nsDialogs::Show
                                  FunctionEnd
                                  Function nsDialogsPageLeave
                                  ${NSD_GetText} $Text $0
                                  MessageBox MB_OK "You typed:$\n$\n$0"
                                  FunctionEnd
                                  Function nsDialogsPageTextChange
                                  Pop $1 # $1 == $ Text
                                  ${NSD_GetText} $Text $0
                                  ${If} $0 == "hello"
                                  MessageBox MB_OK "right back at ya!"
                                  ${EndIf}
                                  FunctionEnd
                                  Section
                                  DetailPrint "hello world"
                                  SectionEnd

    储存数据

      到目前为止,我们有了一个具备一些基本输入控件的页面。但是,当用户进入下一个页面后而又返回到前一页面时会发生什么情况呢?按照现有的代码,用户的输入将不会被储存下来。要储存它们,我们可以使用已有的离开回调函数来储存用户对的选择到变量并在下一次创建该控件时传递这些变量。更好的一个例子,我们也可以添加一个 Checkbox 控件到页面,并使用 ${NSD_GetState}${NSD_SetState} 来获取和设置其状态。

      为了更直观一些,我们将要删除先前步骤中的一些通告。

      !include nsDialogs.nsh
                                      !include LogicLib.nsh
                                      Name nsDialogs
                                      OutFile nsDialogs.exe
                                      XPStyle on
                                      Var Dialog
                                      Var Label
                                      Var Text
                                      Var Text_State
                                      Var Checkbox
                                      Var Checkbox_State
                                      Page custom nsDialogsPage nsDialogsPageLeave
                                      Page license
                                      Page instfiles
                                      Function .onInit
                                      StrCpy $Text_State "Type something here..."
                                      FunctionEnd
                                      Function nsDialogsPage
                                      nsDialogs::Create /NOUNLOAD 1018
                                      Pop $Dialog
                                      ${If} $Dialog == error
                                      Abort
                                      ${EndIf}
                                      ${NSD_CreateLabel} 0 0 100% 12u "Hello, welcome to nsDialogs!"
                                      Pop $Label
                                      ${NSD_CreateText} 0 13u 100% 12u $Text_State
                                      Pop $Text
                                      ${NSD_CreateCheckbox} 0 30u 100% 10u "&Something"
                                      Pop $Checkbox
                                      ${If} $Checkbox_State == ${BST_CHECKED}
                                      ${NSD_Check} $Checkbox
                                      ${EndIf}
                                      # alternative for the above ${If}:
                                      #${NSD_SetState} $Checkbox_State
                                      nsDialogs::Show
                                      FunctionEnd
                                      Function nsDialogsPageLeave
                                      ${NSD_GetText} $Text $Text_State
                                      ${NSD_GetState} $Checkbox $Checkbox_State
                                      FunctionEnd
                                      Section
                                      DetailPrint "hello world"
                                      SectionEnd

函数参考

    Create

    nsDialogs::Create /NOUNLOAD rect

    新建一个对话框。rect 指定了位置将被模仿的控件的标识符。此处通常使用 1018,用其模仿内建页面的创建。Modern UI 也用 1040 来控制欢迎完成页面。

    返回新对话框的 HWND 值到堆栈或 error

    CreateControl

    nsDialogs::CreateControl /NOUNLOAD class style extended_style x y width height text

    在当前对话框中新建一个控件。此函数正常工作的前提条件是对话框必须存在,故 nsDialogs::Create 必须在此函数之前调用。

    返回新控件的 HWND 值到堆栈或 error

    Show

    nsDialogs::Show

    显示页面。一旦调用它将结束 nsDialogs::Create、nsDialogs::CreateControl 及其它 nsDialogs 函数。

    无返回值。

    SelectFileDialog

    nsDialogs::SelectFileDialog /NOUNLOAD mode initial_selection filter

    显示一个文件选择对话框。若 mode 设置为 save,将显示一个保存文件对话框,若 mode 设置为 open,将显示一个打开文件对话框。filter 为有效的文件过滤器列表,用 | 分隔。如果没有指定,则使用默认的 所有文件|*.*

    返回所选中的文件到堆栈,或当用户取消操作时返回空字串。

    SelectFolderDialog

    nsDialogs::SelectFolderDialog /NOUNLOAD title initial_selection

    显示一个文件夹选择对话框。

    返回所选中的文件夹到堆栈,或当用户取消操作时返回空字串。

    SetRTL

    nsDialogs::SetRTL /NOUNLOAD rtl_setting

    打开/关闭 从右到左 模式。若 rtl_setting = 0,关闭。若 rtl_setting = 1,打开。此函数必须在任何的 nsDialogs::CreateControl 之前调用。

    无返回值。

    GetUserData

    nsDialogs::GetUserData /NOUNLOAD control_HWND

    返回与控件相关联的用户数据到堆栈。使用 nsDialogs::SetUserData 设置此数据。

    SetUserData

    nsDialogs::SetUserData /NOUNLOAD control_HWND data

    关联数据到控件。使用 nsDialogs::GetUserData 获取此数据。

    无返回值。

    OnBack

    nsDialogs::OnBack /NOUNLOAD function_address

    设置上一步按钮的回调函数。此函数在用户点击上一步按钮时调用。在此函数中调用 Abort 能阻止用户回到前一个页面。

    使用 GetFunctionAddress 获取期望的回调函数地址。

    无返回值。

    OnChange

    nsDialogs::OnChange /NOUNLOAD control_HWND function_address

    设置一个更改通告回调函数到所指定的控件。当控件状态被更改时,该函数将被调用,并返回控件的 HWND 值到堆栈。

    使用 GetFunctionAddress 获取期望的回调函数地址。

    无返回值。

    OnClick

    nsDialogs::OnClick /NOUNLOAD control_HWND function_address

    设置一个点击通告回调函数到所指定的控件。当控件被点击时,该函数将被调用,并返回控件的 HWND 值到堆栈。

    使用 GetFunctionAddress 获取期望的回调函数地址。

    无返回值。

    OnNotify

    nsDialogs::OnNotify /NOUNLOAD control_HWND function_address

    设置一个通告回调函数到所指定的控件。当控件接收到 WM_NOTIFY 讯息时,该函数将被调用,并返回控件的 HWND 值、通告代码和 MNHDR 结构指针到堆栈。

    使用 GetFunctionAddress 获取期望的回调函数地址。

    无返回值。

宏参考

    nsDialogs.nsh 包含了一系列的宏,这将使得 nsDialogs 的使用变得更简单一些。下面是有关这些宏的用途、语法、输入和输出的简要介绍。

    NSD_Create*

    ${NSD_Create*} x y width height text

    在当前对话框中新建一个控件。此函数正常工作的前提条件是对话框必须存在,故 nsDialogs::Create 必须在此函数之前调用。

    有效的变量:

    • ${NSD_CreateHLine}
    • ${NSD_CreateVLine}
    • ${NSD_CreateLabel}
    • ${NSD_CreateIcon}
    • ${NSD_CreateBitmap}
    • ${NSD_CreateBrowseButton}
    • ${NSD_CreateLink}
    • ${NSD_CreateButton}
    • ${NSD_CreateGroupBox}
    • ${NSD_CreateCheckBox}
    • ${NSD_CreateRadioButton}
    • ${NSD_CreateText}
    • ${NSD_CreatePassword}
    • ${NSD_CreateNumber}
    • ${NSD_CreateFileRequest}
    • ${NSD_CreateDirRequest}
    • ${NSD_CreateComboBox}
    • ${NSD_CreateDropList}
    • ${NSD_CreateListBox}

    返回新对话框的 HWND 值到堆栈或 error。

    NSD_OnBack

    ${NSD_OnBack} control_HWND function_address

    参阅 OnBack 了解更多资料。

     

    NSD_OnChange

    ${NSD_OnChange} control_HWND function_address

    参阅 OnChange 了解更多资料。

    参阅 Real-time Notification 了解使用实例。

    NSD_OnClick

    ${NSD_OnClick} control_HWND function_address

    参阅 OnClick 了解更多资料。

    NSD_OnNotify

    ${NSD_OnNotify} control_HWND function_address

    参阅 OnNotify 了解更多资料。

    NSD_AddStyle

    ${NSD_AddStyle} control_HWND style

    添加一个或多个窗口外观样式到控件。多个外观样式用分隔符 `|' 隔开。

    请到 MSDN 获取样式资料。

    NSD_AddExStyle

    ${NSD_AddExStyle} control_HWND style

    添加一个或多个窗口外观样式到控件。多个外观样式用分隔符 `|' 隔开。

    请到 MSDN 获取样式资料。

    NSD_GetText

    ${NSD_GetText} control_HWND output_variable

    返回某个控件的 text 状态并储存到 output_variable。尤其适用于 Text 控件。

    参阅 Control State 了解使用实例。

    NSD_SetText

    ${NSD_SetText} control_HWND text

    设置某个控件的 text 状态。

    NSD_SetTextLimit

    ${NSD_SetTextLimit} control_HWND limit

    设置 Text 控件的输入长度限制。

    NSD_GetState

    ${NSD_GetState} control_HWND output_variable

    返回 CheckBox 和 RadioButton 控件的状态。可能的输出值为 ${BST_CHECKED} 和 ${BST_UNCHECKED}。

    参阅 Memory 了解使用实例。

    NSD_SetState

    ${NSD_SetState} control_HWND state

    设置 CheckBox 和 RadioButton 控件的状态。可能的 state 参数数据为 ${BST_CHECKED} 和 ${BST_UNCHECKED}。

    参阅 Memory 了解使用实例。

    NSD_Check

    ${NSD_Check} control_HWND

    勾选一个 CheckBox 和 RadioButton 控件。等同于带 ${BST_CHECKED} 参数调用 ${NSD_SetState}。

    NSD_Uncheck

    ${NSD_Uncheck} control_HWND

    取消勾选一个 CheckBox 和 RadioButton 控件。等同于带 ${BST_UNCHECKED} 参数调用 ${NSD_SetState}。

    参阅 Memory 了解使用实例。

    NSD_CB_AddString

    ${NSD_CB_AddString} combo_HWND string

    添加一个字符串到组合框。

    NSD_CB_SelectString

    ${NSD_CB_SelectString} combo_HWND string

    选择组合框中的一个字符串。

    NSD_LB_AddString

    ${NSD_LB_AddString} combo_HWND string

    添加一个字符串到列表框。

    NSD_LB_SelectString

    ${NSD_LB_SelectString} combo_HWND string

    选择列表框中的一个字符串。

    NSD_SetFocus

    ${NSD_SetFocus} control_HWND

    将控件设置为焦点。

    NSD_SetImage

    ${NSD_SetImage} control_HWND image_path output_variable

    image_path 载入一个图像并显示在已使用 ${NSD_CreateBitmap} 创建的 control_HWND 位置上。图像句柄储存在 output_variable 中,一旦不需要时可使用 ${NSD_FreeImage} 释放。

    必须在图像被释放到用户系统之后才能调用此宏。推荐释放图像到 $PLUGINSDIR 。

    !include nsDialogs.nsh
                                    Name nsDialogs
                                    OutFile nsDialogs.exe
                                    XPStyle on
                                    Page custom nsDialogsImage
                                    Page instfiles
                                    Var Dialog
                                    Var Image
                                    Var ImageHandle
                                    Function .onInit
                                    InitPluginsDir
                                    File /oname=$PLUGINSDIR\image.bmp "${NSISDIR}\Contrib\Graphics\Header\nsis-r.bmp"
                                    FunctionEnd
                                    Function nsDialogsImage
                                    nsDialogs::Create /NOUNLOAD 1018
                                    Pop $Dialog
                                    ${If} $Dialog == error
                                    Abort
                                    ${EndIf}
                                    ${NSD_CreateBitmap} 0 0 100% 100% ""
                                    Pop $Image
                                    ${NSD_SetImage} $Image $PLUGINSDIR\image.bmp $ImageHandle
                                    nsDialogs::Show
                                    ${NSD_FreeImage} $ImageHandle
                                    FunctionEnd
                                    Section
                                    SectionEnd

    NSD_SetStretchedImage

    ${NSD_SetStretchedImage} control_HWND image_path output_variable

    载入并显示一个图像,有点类似 ${NSD_SetImage},但它能拉伸图像以填充控件的位置范围。

    NSD_ClearImage

    ${NSD_ClearImage} control_HWND

    清除控件图像。

    NSD_FreeImage

    ${NSD_FreeImage} image_handle

    释放一个先前使用 ${NSD_SetImage}${NSD_SetStretchedImage} 加载的图像句柄。

常见问题

  • Q: nsDialogs 能否处理 InstallOptions INI 文件?

    A: nsDialogs.nsh 中包含的一个名为 CreateDialogFromINI 的函数能够根据 INI 文件创建 nsDialogs 对话框。它能处理 InstallOptions 支持的各种控件类型,但暂不会处理 flags 标记或通告。Examples\nsDialogs\InstallOptions.nsi 显现了此函数的使用方法。

    未来将也会有一个函数来创建脚本自身。

posted @ 2008-09-24 18:26  kin2321  阅读(3914)  评论(1编辑  收藏  举报