介紹
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
-
- HLine
- VLine
- Label
- Icon
- Bitmap
- BrowseButton
- Link
- Button
- GroupBox
- CheckBox
- RadioButton
- Text
- Password
- FileRequest
- DirRequest
- ComboBox
- DropList
- ListBox
此時編譯並運行最后修改的腳本得到的將只是一個沒有用處的空白頁面。因此我們也應當在該頁面上添加一些控件。要實現此目的,我們可使用頭文件 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*} 來創建的控件類型為:
現在我們有了一些用戶可以參與互動的控件,那么讓我們看看用戶到底對她們都干了些什么吧。要實現此目的,我們首先要添加一個離開回調 (leave callback) 函數到我們的頁面。在該函數中,我們需要知道我們所創建並顯現在用戶面前的 Text 控件的狀態。要實現此目的,我們要使用宏 ${NSD_GetText}。對於 RadioButton 和 CheckBox 控件則要使用宏 ${NSD_GetState}。
注意並非所有的控件都支持 ${NSD_GetText},一些控件需要使用特定訊息(在 WinMessages.nsh 中定義)來進行特殊的處理。例如 ListBox 控件需要使用 LB_GETCURSEL 和 LB_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 獲取期望的回調函數地址。
無返回值。
宏參考
-
- ${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}
nsDialogs.nsh 包含了一系列的宏,這將使得 nsDialogs 的使用變得更簡單一些。下面是有關這些宏的用途、語法、輸入和輸出的簡要介紹。
NSD_Create*
${NSD_Create*} x y width height text
在當前對話框中新建一個控件。此函數正常工作的前提條件是對話框必須存在,故 nsDialogs::Create 必須在此函數之前調用。
有效的變量:
返回新對話框的 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 顯現了此函數的使用方法。
未來將也會有一個函數來創建腳本自身。