InstallOptions 2

介紹

InstallOptions 是一個可以建立自定義安裝程式頁面的 NSIS 插件,它可以提供一些訊息的輸入輸出等高級功能。

InstallOptions 將會在 NSIS 視窗內建立一個對話。對話上的所有控件由 INI 檔案定義。

NSIS 2 有新的頁面系統,它使你把自定義的頁面新增到自己的安裝程式而不會導致上一步、下一步功能混亂。在新的插件系統裡,你也不用去管插件的釋放、刪除,這些 NSIS 都替你準備好了。如果你把 INI 檔案儲存在插件目錄,安裝結束時 NSIS 也會一樣幫你自動刪除。

這個新的 InstallOptions 是為 NSIS 2 設計的。它支援自定義用戶介面和自定義字型和 DPI 設定。

INI 檔案

這個 INI 檔案有一個必需的區段。這個區段包含了要建立的控件的數量和慣用的視窗屬性。INI 檔案也包含了一些帶變量的 Field x 區段用來定義要建立的控件及其屬性。

必須的區段名稱必須為 "Settings"。他可以包含下列值:

NumFields (必須的) 對話視窗上要顯示的控件數量。
Title (可選的) 如果指定,則設定標題欄文字,否則保持不變。
CancelEnabled (可選的) 如果指定,將會取代 NSIS 的設定並允許或禁止取消按鈕。如果設為 1,取消按鈕被允許。如果設為 0,取消按鈕被禁止。
CancelShow (可選的) 如果指定,將會取代 NSIS 的設定並顯示或隱藏取消按鈕。如果設為 1,取消按鈕被顯示。如果設為 0,取消按鈕被隱藏。
BackEnabled (可選的) 如果指定,將會取代 NSIS 的設定並允許或禁止上一步按鈕。如果設為 1,上一步按鈕被允許。如果設為 0,上一步按鈕被禁止。
CancelButtonText (可選的) 取代取消按鈕的文字,如果未指定取消按鈕的文字保持不變。
NextButtonText (可選的) 取代下一步按鈕的文字,如果未指定下一步按鈕的文字保持不變。
BackButtonText (可選的) 取代上一步按鈕的文字,如果未指定上一步按鈕的文字保持不變。
Rect (可選的) 取代預設的矩形 ID。這會使得 IO 重新調整它本身對話視窗的大小。
RTL (可選的) 如果指定為 1 則所有對話文字將顯示為從右至左文字。如果需要支援從右至左文字(比如阿拉伯文)你可以使用 NSIS 的 $(^RTL) 變量來填寫該值。
State (輸出) 這個值不是由你來提供而是由 InstallOptions 在調用你的自定義頁面確認函數之前來設定的,提供了一些控件的狀態訊息,比如按鈕按下等。

每個區段都為"Field #" 形式,這裡 # 是一個從 1 到 NumFields 的連續的數字。每一個區段可以包含下列值:

Type (必須的) 要建立的控件的類型。有效的值為 Label, Text, Password,Combobox, DropList, Listbox, CheckBox, RadioButton,FileRequest, DirRequest, Icon, Bitmap, GroupBox, LinkButton

Label 用來顯示靜態文字。
TextPassword 接受用戶的文字輸入。"Password" 把輸入顯示為 * 字元。
Combobox 使用戶可以直接輸入不在列表裡的文字,"Droplist" 只能從列表項裡選擇。
Listbox 顯示了多項並可以選擇多個項。
CheckBox 顯示了帶文字的單選框。
FileRequest 顯示文字框和瀏覽按鈕。按這裡瀏覽按鈕將顯示檔案開啟對話框使用戶可以從中選擇檔案。
DirRequest 顯示文字框和瀏覽按鈕。按這裡瀏覽按鈕將顯示目錄開啟對話框使用戶可以從中選擇目錄。
Icon 顯示圖檔。不帶文字可以顯示安裝程式圖檔。
Bitmap 顯示位圖。
GroupBox 顯示一組控件的框架。
Link 顯示一個靜態的連結。當用戶按這裡控件時,State 指定的內容將被執行(比如 http://)。作為選擇 State 也可以聯合 NOTIFY 標記來使用 NSIS 回調。
Button 顯示按鈕,可以執行像上面 "Link" 控件的功能。
Text (可選的) 指定 label, checkbox, 或 radio button 控件的標題。對於 DirRequest 控件則指定瀏覽對話的標題。對於 icon 和 bitmaps 控件則指定圖檔的路徑。

注意: 對於 label,\r\n 將被轉換為新行。要在文字裡使用反斜槓 \ 請使用 \\ 來轉義。下面 有一個函數可以進行這些文字的轉換。
State (可選的) 控件的狀態。當用戶關閉視窗時會更新,所以你可以從 NSIS 裡讀取該項內容。對於編輯框和目錄選擇框、檔案選擇框來說儲存的字串指示了內容。對於互斥按鈕或單選框,可能是 0 或 1 (對應於選擇或未選擇)。對於列表框,組合框或下拉列表框來說這是所選擇的內容,由 | 進行分隔。對於連結和按鈕來說這裡可以指定要被執行或被開啟的對象 (用 ShellExecute )。

注意: 對於帶 MULTILINE 標記的文字段,\r\n 將會被轉換為換行符。要使用 \ 你應該用 \\ 來進行轉義。
ListItems (可選的) 用來初始化列表框、組合框、下拉列表框的內容。使用單行字串並使用 | 來分隔每一項。
MaxLen (可選的) 使得選擇的控件限制最大的文字長度。如果用戶選擇的文字大於該限制,則當他們點確定的時候會出現一個消息框提示並且對話不會結束。
你不應該在組合框裡用來限制用戶的選擇。
應該用在 FileRequestDirRequest 裡用來限制最大的路徑長度為 260。
Label 控件會忽略這一項。
MinLen (可選的) 使得選擇的控件限制最小的文字長度。如果用戶選擇的文字小於該限制,則當他們點確定的時候會出現一個消息框提示並且對話不會結束。
不像 MaxLen,這在組合框中非常有用。如果把這一項設為 1 的話程式就會強制用戶至少選一項。
Label 控件會忽略這一項。
ValidateText (可選的) 如果某一個 Field 在測試上面的 MinLenMaxLen 時達到了限制的條件,那麼就會出現一個消息框顯示這個文字。

注意: \r\n 將會被轉換為換行符。要使用 \ 你應該用 \\ 來進行轉義。
Left
Right
Top
Bottom
(必須的) 各個控件出現在對話裡的位置。所有的容量單位均使用對話裡的單位。要取得你想知道的的控件的正確容量,你可以使用資源編輯器來設計你的對話並把容量複製到 INI 檔案。

注意: 你可以指定負值,這表示距離是從右端或底部算起。

注意 (2): 對於組合框或下拉列表框,bottom 值的意義稍微不同。
在這種情況下。底部的值表示下拉時所能顯示的視窗的最大容量。通常來說,組合框會自動地調整大小到一個元素高度。如果你碰到了組合框下拉時看不到列表的時候你應該檢查 bottom 值是否有足夠的大小。粗略的估計所需要的高度時列表項數目乘以 8 加 20。

注意 (3): FileRequest 和 DirRequest 控件會分配 15 個對話單位給瀏覽按鈕。請確認控件的寬度足夠顯示按鈕文字內容。
Filter (可選的) 指定 FileRequest 控件所用的過濾條件。
這是成對出現的,每一項由 | 分隔。
每一對的第一個值是過濾條件顯示的文字。
第二個值是用來匹配檔案的模式。
例如,你可以指定:
Filter=文字檔案|*.txt|程式|*.exe;*.com|所有檔案|*.*
如果沒有指定,則使用預設的 All Files|*.*

注意: 在 | 分隔符的旁邊不應該有多餘的空格。
Root (可選的) DirRequest 控件用來指定瀏覽時的根目錄。預設值是允許用戶瀏覽電腦裡的任何目錄。指定這個值可以限制只能在特定的目錄裡瀏覽。
Flags (可選的) 對於不同的控件顯示這個值指定了額外的標記。每一個標記需要用 | 來分隔,並且需要注意 | 旁邊不能有多餘的空格。
意義
REQ_SAVE 使得 FileRequest 控件顯示為儲存檔案對話。如果不指定則是開啟檔案對話。
FILE_MUST_EXIST 用於 FileRequest 來檢測選擇的檔案是否必須存在。
僅應用在開啟檔案對話時。
它通常不會強制檔案必須存在但除了使用瀏覽按鈕。
FILE_EXPLORER 用於 FileRequest 使用新的檔案請求外觀(推薦)。
FILE_HIDEREADONLY 用於 FileRequest,在開啟檔案對話裡隱藏「僅開啟只讀檔案」單選框。
WARN_IF_EXIST 用於 FileRequest ,當選擇的檔案不存在時顯示一個警告訊息。
這個警告訊息僅在通過瀏覽按鈕選擇檔案是顯示。
PATH_MUST_EXIST 用於 FileRequest 來強制路徑必須存在。這可以阻止用戶在瀏覽對話視窗裡輸入一個無效的路徑。
僅在通過瀏覽按鈕選擇時有效。
PROMPT_CREATE 用於 FileRequest ,當選這裡一個不存在的檔案時顯示一個警告。但是,它仍然允許用戶選擇檔案。
僅在通過瀏覽按鈕選擇時有效。
不能和 REQ_SAVE 一起使用。
RIGHT 用於 CheckboxRadiobutton 控件來指定選擇按鈕是左對齊還是右對齊。預設是左對齊。
MULTISELECT 用於 Listbox 控件。是否允許用戶按這裡或雙擊列表框裡的字串來選擇多項。如果指定了這個標記或 EXTENDEDSELCT 標記時用戶可以選擇多項,否則每次只能選擇一項。
EXTENDEDSELCT 用於 Listbox 控件。允許通過 SHIFT 健和鼠標或特殊的組合鍵來選擇多項。如果未指定這個標記和 MULTISELECT 的話每次只能選擇一項。
RESIZETOFIT 這個標記使得 Bitmap 控件重新調整圖像的大小來適合控件的大小。對於支援自定義 DPI 設定非常有用。不指定的話圖檔只能居中顯示。
TRANSPARENT 用於 Bitmap 控件。隱藏和左上方相同顏色的像素。這使得控件看上去就像在後面出現的一樣。這個標記和 RESIZETOFIT 組合使用且位圖多於 256 種顏色時不太好。
GROUP 新增該標記到需要成組控件的第一個控件上使他們成為一組控件。成組的控件使你可以建立多個互斥按鈕並可以方便的使用鍵盤上下鍵來選擇。
NOTABSTOP 當用戶按 Tab 鍵時不要停止在控件上。把這個標記新增到一組控件上除了第一個控件,這可以使按 Tab 鍵時一次性跳過該組。
DISABLED 禁用該控件。
ONLY_NUMBERS 用於 Text 控件。強制用戶只能在編輯框裡輸入數字。
MULTILINE 用於 Text 控件。使控件接受多行文字。
WANTRETURN 用於多行 Text 控件。指定當用戶按下Enter鍵時插入一個Enter符。
NOWORDWRAP 用於多行 Text 控件。禁止自動換行。
HSCROLL 顯示水平滾動條。當用於多行 Text 控件時也會禁止自動換行。
VSCROLL 顯示垂直滾動條。
READONLY 用於 Text 控件。不允許用戶從編輯框輸入內容但是可以讀取或複製。
NOTIFY 用於 Button, Link,CheckBox, RadioButton, ListBoxDropList 控件。當控件的選擇更改或按鈕被按這裡時使得 InstallOptions 調用 NSIS 自定義頁面的離開函數。你的離開函數可以從 Setting 區段裡讀取 State 值來檢測是哪一個控件產生了這個通知事件。你可以調用 Abort 來使得 NSIS 回到該頁面上。Examples\InstallOptions 檔案夾裡包含了如何使用這個標記的例子。
TxtColor (可選的) 用於 Link 控件來指定文字的前景色。格式為: 0xBBRRGG (十六進制)。

如何使用

Modern UI

關於在 Modern UI 裡使用 InstallOptions 的更多訊息請觀看 Modern UI 文件

釋放 INI 檔案

首先,你需要在 .onInit 函數里把對話的 INI 檔案釋放出來。

Function .onInit

  InitPluginsDir
  File /oname=$PLUGINSDIR\test.ini test.ini

FunctionEnd

調用 DLL

你可以在 page 函數里調用 InstallOptions,關於頁面系統的更多訊息請觀看 NSIS 文件。例如:

Page custom SetCustom ValidateCustom

InstallOptions DLL 有三個函數:

  • dialog - 立即建立對話
  • initDialog - 先在記憶體裡建立,但未顯示出來
  • show - 把在記憶體裡建立的對話顯示出來

通常,你只需要 dialog 函數就可以了:

Function SetCustom ;FunctionName defined with Page command

  ;Display the Install Options dialog

  Push $R0

  InstallOptions::dialog $PLUGINSDIR\test.ini
  Pop $R0

FunctionEnd

取得輸入

要取得用戶的輸入,可以用 ReadINIStr 來讀取某個 Field 的 State 值:

ReadINIStr $R0 "$PLUGINSDIR\test.ini" "Field 1" "State"

注意:

一些 InstallOptions 的值已被轉義(類似於 C 字串)來使得一些特定字元可以在 INI 檔案裡使用。受影響的值為:

  • ValidateText 字段
  • Label 字段的 Text 值
  • 帶有 MULTILINE 標記的 Text 字段的 State 值

轉義的字元如下:

"\\" 斜槓
"\r" Enter (ASCII 13)
"\n" 換行 (ASCII 10)
"\t" Tab (ASCII 9)

下面的函數可以用來轉換這些字元:

; 轉換 NSIS 字串到 InstallOptions 字串
; 使用:
;   Push <NSIS-字串>
;   Call Nsis2Io
;   Pop <IO-字串>
Function Nsis2Io
  Exch $0 ; The source
  Push $1 ; The output
  Push $2 ; Temporary char
  StrCpy $1 "" ; Initialise the output
loop:
  StrCpy $2 $0 1 ; Get the next source char
  StrCmp $2 "" done ; Abort when none left
    StrCpy $0 $0 "" 1 ; Remove it from the source
    StrCmp $2 "\" "" +3 ; Back-slash?
      StrCpy $1 "$1\\"
      Goto loop
    StrCmp $2 "$\r" "" +3 ; Carriage return?
      StrCpy $1 "$1\r"
      Goto loop
    StrCmp $2 "$\n" "" +3 ; Line feed?
      StrCpy $1 "$1\n"
      Goto loop
    StrCmp $2 "$\t" "" +3 ; Tab?
      StrCpy $1 "$1\t"
      Goto loop
    StrCpy $1 "$1$2" ; Anything else
    Goto loop
done:
  StrCpy $0 $1
  Pop $2
  Pop $1
  Exch $0
FunctionEnd

; 轉換 InstallOptions 字串到 NSIS 字串
; Usage:
;   Push <IO-字串>
;   Call Io2Nsis
;   Pop <NSIS-字串>
Function Io2Nsis
  Exch $0 ; The source
  Push $1 ; The output
  Push $2 ; Temporary char
  StrCpy $1 "" ; Initialise the output
loop:
  StrCpy $2 $0 1 ; Get the next source char
  StrCmp $2 "" done ; Abort when none left
    StrCpy $0 $0 "" 1 ; Remove it from the source
    StrCmp $2 "\" +3 ; Escape character?
      StrCpy $1 "$1$2" ; If not just output
      Goto loop
    StrCpy $2 $0 1 ; Get the next source char
    StrCpy $0 $0 "" 1 ; Remove it from the source
    StrCmp $2 "\" "" +3 ; Back-slash?
      StrCpy $1 "$1\"
      Goto loop
    StrCmp $2 "r" "" +3 ; Carriage return?
      StrCpy $1 "$1$\r"
      Goto loop
    StrCmp $2 "n" "" +3 ; Line feed?
      StrCpy $1 "$1$\n"
      Goto loop
    StrCmp $2 "t" "" +3 ; Tab?
      StrCpy $1 "$1$\t"
      Goto loop
    StrCpy $1 "$1$2" ; Anything else (should never get here)
    Goto loop
done:
  StrCpy $0 $1
  Pop $2
  Pop $1
  Exch $0
FunctionEnd

驗證輸入

如果你想驗證頁面的輸入,例如,你需要知道用戶是否填寫了文字框,當驗證失敗時可以使用頁面的 leave 函數並調用 Abort 來阻止用戶繼續:

Function ValidateCustom

  ReadINIStr $R0 "$PLUGINSDIR\test.ini" "Field 1" "State"
  StrCmp $R0 "" 0 +3
    MessageBox MB_ICONEXCLAMATION|MB_OK "請輸入一個名稱。"
    Abort

FunctionEnd

返回值

在你調用 InstallOptions 之後,InstallOptions 會新增一個字串到堆棧,新增的字串可能是下列之一:

  • success - 用戶按了下一步按鈕
  • back - 用戶按了上一步按鈕
  • cancel - 用戶按了取消按鈕
  • error - 發生了一個錯誤,對話無法顯示

通常,你不需要檢測這些值,但是你應該把它們從堆棧移除 (看上面的例子)。

僅當你需要的時候才回去檢測返回值,比如檢測用戶按了什麼按鈕。

保留檔案

如果你使用 BZIP2 或 LZMA (固實) 壓縮的話,那麼在頁面初始化階段或頁面函數里釋放檔案就變得很值得注意了,你應該把這些檔案保留在一個資料區塊裡,這會使你的安裝程式運行不會變慢。

如果在上面提到的階段裡使用了 File 命令的話,請在區段和函數之外新增 ReserveFile 命令:

ReserveFile "test.ini"
ReserveFile "${NSISDIR}\Plugins\InstallOptions.dll"

字型和顏色

如果你想在 InstallOptions 對話裡使用自定義的字型和顏色,你應該使用 initDialog 和 show 函數。initDialog 會在記憶體裡建立頁面但還沒有顯示。在調用了 initDialog 之後你可以設定字型和顏色,然後調用 show 來顯示對話。initDialog 會把 HWND 壓入堆棧。要取得控件的句柄請使用:

GetDlgItem (輸出變量) (自定義頁面的視窗句柄) (1200 + Field number - 1)

使用自定義顏色的例子:

Function FunctionName ;FunctionName defined with Page command

  ;Display the Install Options dialog

  Push $R0
  Push $R1
  Push $R2

    InstallOptions::initDialog /NOUNLOAD $PLUGINSDIR\test.ini
    Pop $R0

    GetDlgItem $R1 $R0 1200 ;1200 + Field number - 1

    ;$R1 contains the HWND of the first field
    CreateFont $R2 "Tahoma" 10 700
    SendMessage $R1 ${WM_SETFONT} $R2 0

    InstallOptions::show
    Pop $R0

  Pop $R2
  Pop $R1
  Pop $R0

FunctionEnd

版本歷史

  • DLL version 2.42 (January 21st, 2005)
    • Added TRANSPARENT flag for BITMAP fields (funded by Chris Morgan)

完整的版本歷史

開發團隊

Original version by Michael Bishop
DLL version by Nullsoft, Inc.
DLL version 2 by Amir Szekely, ORTIM, Joost Verburg
New documentation by Joost Verburg

許可協議

Original version Copyright © 2001 Michael Bishop
DLL version 1 Copyright © 2001-2002 Nullsoft, Inc., ORTIM
DLL version 2 Copyright © 2003-2005 Amir Szekely, Joost Verburg, Dave Laundon

This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.

Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute
it freely, subject to the following restrictions:

1. The origin of this software must not be misrepresented;
   you must not claim that you wrote the original software.
   If you use this software in a product, an acknowledgment in the
   product documentation would be appreciated but is not required.
2. Altered versions must be plainly marked as such,
   and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any distribution.