史萊姆論壇

史萊姆論壇 (http://forum.slime.com.tw/)
-   多媒體影音轉檔燒錄技術文件 (http://forum.slime.com.tw/f129.html)
-   -   取得winamp的NSIS教本的教學 (http://forum.slime.com.tw/thread136509.html)

psac 2004-12-13 01:51 PM

取得winamp的NSIS教本的教學
 
新增 NSIS 指令碼的習慣: 新增一個 include 目錄,用來儲存安裝用的文件, .nsi 文件放在 include 的上級目錄,再在 include 目錄裡新增一個 resource,用來儲存一些資源文件比如圖示、界面圖形、自己修改的 UI 等等。

然後分析一下官方的安裝程序,嗯嗯,先清空臨時資料夾,這是為了為了找東西方便,然後啟動安裝程序,再到臨時目錄裡找一個 nxxx.tmp 這樣的目錄,裡面有一些解壓縮出來的資源 gaydata.ini、modern-header.bmp、classic256.bmp、modern256.bmp、opt2page.ini、 opt3page.ini。那幾個圖形一看就明白,不用解釋,gaydata.ini 呢,裡面有從 sec0 到 sec47 的定義,所以我們可以確定一共有 47 個區段,而且區段的名稱是根據 gaydata.ini 來確定的,如何知道是根據 gaydata.ini 來確定的 的呢,你在安裝程序剛啟動的時候(剛顯示許可頁面的時候)找到臨時的那個目錄(也就是 NSIS 裡的 $PLUGINSDIR 目錄),把一個區段名稱改一下,比如把「Winamp (required)」改為 aaa,等進入元件選項頁面的時候第一個就是 aaa 了,而如果把「Winamp (required)」清空的話,第一個區段就不見了。 opt2page.ini、opt3page.ini 分別是最後兩個頁面用來選項連接方式和外觀的。分析後就可以動手了……

1.建立基本的結構

首先在指令碼頭部定義一些版本號等值,比如

!define VERSION "5.05"
!define VERSION_NUM "505"

這樣版本號變的時候在指令碼頭部改一下就行了,不用在指令碼的每個地方都改
然後定義輸出檔案名,為了方便 full、pro、lite 三個版本切換方便。

!define FILE_NAME "Winamp${VERSION_NUM}_full"

有關定義的說明可以看這裡

再下來就是安裝程序內容的設定了,必須的設定有
Name "Winamp"
OutFile "${FILE_NAME}.exe"

當然

SetCompressor lzma

應該也是必須的,LZMA 不止壓縮率大很多,而且不太準確的一個內容是啟動快不少,然後再設定一個區段就構成了主體部分,已經能夠編譯了

Section "主程序"
SectionEnd

2. 插入頁面

首先要

!include "MUI.nsh"

這樣才能使用 NSIS 提供的一些巨集來插入頁面,要插入的頁面是

!insertmacro MUI_PAGE_LICENSE ".\resource\License.txt"
!insertmacro MUI_PAGE_COMPONENTS
!insertmacro MUI_PAGE_DIRECTORY
!insertmacro MUI_PAGE_COMPONENTS
!insertmacro MUI_PAGE_INSTFILES
!insertmacro MUI_UNPAGE_CONFIRM
!insertmacro MUI_UNPAGE_INSTFILES

最後還要插入語言

!insertmacro MUI_LANGUAGE English



3. 完善安裝程序內容設定
當然安裝程序的內容還要增加一些設定

BrandingText "Nullsoft Install System -- built on ${__DATE__} at ${__TIME__}"

這是設定安裝程序個人標誌的

InstallDir "$PROGRAMFILES\Winamp"

設定一個預設的安裝路徑

InstallDirRegKey HKCU "Software\Winamp" ""

優先讀取註冊表裡儲存的路徑,如果存在就是用註冊表儲存的路徑

4. 設定頁面
圖示的定義

!define MUI_ICON ".\resource\inst.ico"
!define MUI_UNICON ".\resource\uninst.ico"

定義了安裝程序圖示和卸載程序圖示

!define MUI_HEADERIMAGE

定義在安裝程序頂端顯示一個圖形

!define MUI_HEADERIMAGE_BITMAP ".\resource\modern-header.bmp"

定義要顯示的圖形,必須是本機電腦上的

!define MUI_COMPONENTSPAGE_NODESC

指定元件選項頁面不使用描述區域

5. 設定頁面文本

!define MUI_LICENSEPAGE_TEXT_TOP "Please read and agree to the license terms below before installing."

指定許可頁面上頂端顯示的文本

!define MUI_COMPONENTSPAGE_TEXT_TOP "This will install Winamp ${VERSION}. This installer contains the full install."

指定元件選項頁面頂端的文本

!define MUI_DIRECTORYPAGE_TEXT_TOP "Setup has determined the optimal location to install. If you would like to change the folder, do so now."

指定目錄選項頁面的文本

!define MUI_ABORTWARNING

定義按取消按鈕時,提示是否真的結束

6. 設定安裝檔案類型,並把補全所有的區段

InstType "Full"
InstType "Standard"
InstType "Lite"
InstType "Minimal"

一共四個安裝檔案類型,還有一個 Custom 檔案類型系統會自動增加,不必干預

然後在新增 46 個區段,一共有 47 個,名稱可以隨便起,因為區段的名稱到後面會由 gaydata.ini 來從命名,比如

Section " "
SectionEnd

7. .onInit 函數

這個函數是在安裝程序 GUI 啟動完畢的時候開始執行裡面的程式碼,應該把那些資源文件在這個階段解壓縮到用戶電腦以供使用

InitPluginsDir

啟始化 $PLUGINSDIR 也就是插件目錄

File "/oname=$PLUGINSDIR\gaydata.ini" ".\resource\gaydata.ini"
File "/oname=$PLUGINSDIR\opt2page.ini" ".\resource\opt2page.ini"
File "/oname=$PLUGINSDIR\opt3page.ini" ".\resource\opt3page.ini"
File "/oname=$PLUGINSDIR\classic256.bmp" ".\resource\classic256.bmp"
File "/oname=$PLUGINSDIR\modern256.bmp" ".\resource\modern256.bmp"

因為在 .onInit 裡使用 File 會使程序啟動時要搜尋很久,所以還應該使用 ReserveFile,ReserveFile 的說明看這裡。
在 !include "MUI.nsh" 上面增加

ReserveFile ".\resource\gaydata.ini"
ReserveFile ".\resource\opt2page.ini"
ReserveFile ".\resource\opt3page.ini"
ReserveFile ".\resource\classic256.bmp"
ReserveFile ".\resource\modern256.bmp"
ReserveFile "${NSISDIR}\Plugins\InstallOptions.dll"

因為 InstallOptions.dll 在自訂界面要使用,所以也要加入
8. 元件的隱藏和顯示
細心的朋友都看到了指令碼裡面有兩個 !insertmacro MUI_PAGE_COMPONENTS,那麼元件選項頁面就會出現兩次,察看 gaydata.ini 就知道第一次顯示的是 sec0 到 sec36,第二次顯示的是 sec37 到 sec 47。
關於頁面的說明請看這裡
每個頁面都有三個函數: Pre、Show、Leave,分別是預載入、顯示、離開,在 MUI 界面可以用定義的方法來插入函數,比如在 !insertmacro MUI_PAGE_COMPONENTS 前(插入上一個頁面之後) 定義一個 MUI_PAGE_CUSTOMFUNCTION_PRE 函數就可以插入一個預載入函數。在本次指令碼中在第一個元件選項頁面作如下定義

!define MUI_PAGE_CUSTOMFUNCTION_PRE ComponentPre
!define MUI_PAGE_CUSTOMFUNCTION_SHOW ComponentShow

上面定義了 ComponentPre、ComponentShow 函數,當然定義的函數名可以隨便起,但一般來說名字都要表達它的含義,便於閱讀。

在開始新增這兩個函數之前還要定義一些內容

!define SECTION_COMPONENT_END 36
!define SECTION_ASSCOIATION_START 37
!define SECTION_TOTAL 47

上面定義了 36 是要安裝的元件最後的區段索引好,37 是文件關聯等的開始區段索引號,47 是總共的區段數。ComponentPre 函數的內容如下

Function ComponentPre
Push $0
Push $1

Call SectionTextReset

StrCpy $1 0
loop:
ReadINIStr $0 "$PLUGINSDIR\gaydata.ini" "secnames" "sec$1"
StrCmp $0 "" 0 +2
SectionSetText $1 ""
StrCmp $1 ${SECTION_COMPONENT_END} loop_quit
IntOp $1 $1 + 1
Goto loop
loop_quit:

StrCpy $1 ${SECTION_ASSCOIATION_START}
SectionSetText $1 ""
StrCmp $1 ${SECTION_TOTAL} +3
IntOp $1 $1 + 1
Goto -3

Pop $1
Pop $0
FunctionEnd

這個函數使用了 SectionTextReset 函數,SectionTextReset 函數如下

Function SectionTextReset
Push $R0

StrCpy $R0 0
SectionSetText $R0 " "
StrCmp $R0 ${SECTION_TOTAL} +3
IntOp $R0 $R0 + 1
Goto -3

Pop $R0
FunctionEnd

SectionTextReset 函數構成一個循環,$R0 從 0 開始遞增,直到等於 ${SECTION_TOTAL} 後跳出循環,這個循環把所有區段的名稱都重置為空格,在兩個 MUI_PAGE_COMPONENTS 頁面的預載入函數都使用一次。這是因為 Show 函數會把一些區段隱藏,即把區段名稱設為空值,在下一個 MUI_PAGE_COMPONENTS 頁面的 Pre 階段必須給它一個名稱,否則它將一直隱藏。
使用了 SectionTextReset 函數之後是一個循環,這個循環讀取 "$PLUGINSDIR\gaydata.ini" 的 sec0 到 ${SECTION_COMPONENT_END} ,如果某個 sec 讀到的值為空,則把該區段隱藏,也就是把區段名設為空值。你可以試試英文原版,剛啟動時把 "$PLUGINSDIR\gaydata.ini" 的 sec0 設為空值,到了元件選項頁面 Winamp (required) 區段就被隱藏了。

再下來也是一個循環,把 ${SECTION_ASSCOIATION_START} 到 ${SECTION_TOTAL} 的區段隱藏,因為第一個 MUI_PAGE_COMPONENTS 只需要顯示 0 到 ${SECTION_COMPONENT_END} 的區段。ComponentShow 函數如下

Function ComponentShow
Push $0
Push $1

StrCpy $1 0
loop:
ReadINIStr $0 "$PLUGINSDIR\gaydata.ini" "secnames" "sec$1"
SectionSetText $1 $0
StrCmp $1 ${SECTION_COMPONENT_END} loop_quit
IntOp $1 $1 + 1
Goto loop
loop_quit:

Pop $1
Pop $0
FunctionEnd

也是一個循環,$1 的值從 0 到 ${SECTION_COMPONENT_END} 遞增,則是依次從 sec0 到 sec36 讀取 gaydata.ini 相應的值,並根據讀取道的值來從命名區段名稱。

第二個元件頁面對應的 AsscoiationPre、AsscoiationShow 與上面的基本一致,只是要隱藏的區段索引不同而已。

9. 隱藏控件
元件頁面第二次顯示的時候,有幾個控件是隱藏的,用 Resource Hacker 開啟 ${NSISDIR}\Contrib\UIs\modern.exe 裡面的 104 對話視窗就是元件顯示頁面,要隱藏的空間 ID 為 1017 (顯示安裝檔案類型) 和 1021 (它左邊顯示的文本) 還有 1023 (磁牒空間顯示的控件)。顯示和隱藏控件的指令為 ShowWindow ,說明請看這裡。
隱藏控件的程式碼需要加在 AsscoiationShow 函數里。

FindWindow $0 "#32770" "" $HWNDPARENT

獲取一個視窗關鍵句儲存在 $0 裡

GetDlgItem $1 $0 1017

獲取 1017 控件的關鍵句

ShowWindow $1 ${SW_HIDE}

隱藏 1017 控件,其他幾個控件的隱藏指令依次為

GetDlgItem $1 $0 1021
ShowWindow $1 ${SW_HIDE}
GetDlgItem $1 $0 1023
ShowWindow $1 ${SW_HIDE}

除了控件隱藏之外,還有兩處文本需要更改,由於使用 !define 只能對第一次顯示的元件頁面更改,所以第二次顯示的文本只能自己用 SendMessage 來改了

GetDlgItem $1 $0 1006
SendMessage $1 ${WM_SETTEXT} 0 "STR:Select which icons you want installed, and whether you want files and CDs associated with"
GetDlgItem $1 $0 1022
SendMessage $1 ${WM_SETTEXT} 0 "STR:Select icons to install and media associations:"

jasoncute 2004-12-16 07:35 AM

哇@@"您好厲害啊..佩服佩服


所有時間均為台北時間。現在的時間是 09:40 AM

Powered by vBulletin® 版本 3.6.8
版權所有 ©2000 - 2024, Jelsoft Enterprises Ltd.

『服務條款』

* 有問題不知道該怎麼解決嗎?請聯絡本站的系統管理員 *


SEO by vBSEO 3.6.1