NSIS進階教程(一)
自定義介面之無邊框窗體移動貼圖
**前言**
在Windows下,有很多人想做一個完全自己把控的安裝程式,想過很多種途徑去實現,有人說MFC可以實現,有人說C#可以實現,有人說Delphi可以實現,有人說VB又未嘗不可呢。MFC,Delphi,VB,C#都需要自己去實現打包壓縮,釋放,釋放過程中的業務邏輯跟介面功能,是一項比較麻煩的工作,甚至於C#程式需要執行的話,還需要裝dotnet Framework的runtime。NSIS製作的安裝包可以執行在Win9x下,完全是WinAPI的呼叫,不需要額外裝任何的runtime,安裝包雙擊就能執行,本身封裝了很多Win的函式,方便呼叫與開放介面。功能部分也是實現了基本的安裝過程所需的操作,NSIS的很多Editor做到了嚮導模式的指令碼生成,很是方便。
這麼好的工具能否定製開發呢,答案是肯定的。
本篇主要講講以下幾點:
-
如何消除普通的NSIS指令碼生成的窗體的邊框
-
如何使得無邊框窗體能夠移動
-
如何給這個窗體貼上一張大小合適的背景圖
所用到的NSIS外掛:
-
nsDialogs
-
nsWindows
-
WinProc
-
System
**講義**:
首先貼出一個今天教程的完整的例子(附帶圖片)
猛擊這裡
題外話,本來想用新浪愛問做檔案分享平臺的,發現上傳後一直在稽核中……練葵花寶典能力誰也比過性浪呀,用CSDN也不好,還要登入,本人就因為積分太少而不得不去做無聊的工作贏得積分,用於CSDN下載,自從CSDN把我的密碼明碼儲存還被黑客給搞了之後,我不再上此網站。115雖然下載頁廣告多的一筆,但是後臺上傳頁相當的乾淨,還不用稽核以及無登陸下載,極致方便大家。(115被政府搞了,轉性浪愛問)
使用時:把外掛DLL跟標頭檔案分別放入到你的NSIS本地對應的安裝目錄中,然後編譯原始碼即可。
下文都用%NSIS_Install_DIR%來替代你本地安裝路徑
-
去除窗體Border
在去除窗體邊框之前有一項工作是必須做的,那就是更改預設窗體的大小,因為每個人想做的打包窗體不可能都一樣大,更改窗體大小有兩種方法,也可以兩種方法並用
-
修改NSIS內部的UI
NSIS的預設UI放在"%NSIS_Install_DIR%\Contrib\UIs"中,其中常常見到的建立自定義窗體的1018,1044都在此路徑的modern.exe中。我們只要修改modern.exe裡面的資原始檔即可,做過MFC的都知道,VC在建立程式的時候是有Resources的,只要找到一些能更改Resources裡面Dialog的工具即可,本文推薦
修改的時候寧可大點,也絕不小,因為開發過程中我遇到用nsWindows命令擴大窗體的時候,出現不起作用的情況,但是預設窗體比需要的窗體小的時候可以用nsWindows命令控制。
開啟ResHacker工具拖入modern.exe,操作前請備份modern.exe,拖動資源窗體或者直接修改你想要的大小。預設的1044跟1018窗體都在105分類下。
-
通過nsWindows命令
nsDialogs::Create 1044 Pop $0 ${If} $0 == error Abort ${EndIf} SetCtlColors $0 "" transparent ;背景設成透明 ${NSW_SetWindowSize} $HWNDPARENT 513 354 ;改變窗體大小
該指令碼新增在自定義窗體的建立Function中,建立的是1044型別視窗,修改命令是兩條,分別是對$HWNDPARENT的窗體跟建立的1044page的修改,確保預設的modern.exe的視窗大小比這個要大!
修改好窗體大小後,直接在初始化的Function中直接填入以下程式碼即可去除邊框
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 Function onGUIInit
;消除邊框
System::Call `user32::SetWindowLong(i$HWNDPARENT,i${GWL_STYLE},0x9480084C)i.R0`
;隱藏一些既有控制元件
GetDlgItem $0 $HWNDPARENT 1034
ShowWindow $0 ${SW_HIDE}
GetDlgItem $0 $HWNDPARENT 1035
ShowWindow $0 ${SW_HIDE}
GetDlgItem $0 $HWNDPARENT 1036
ShowWindow $0 ${SW_HIDE}
GetDlgItem $0 $HWNDPARENT 1037
ShowWindow $0 ${SW_HIDE}
GetDlgItem $0 $HWNDPARENT 1038
ShowWindow $0 ${SW_HIDE}
GetDlgItem $0 $HWNDPARENT 1039
ShowWindow $0 ${SW_HIDE}
GetDlgItem $0 $HWNDPARENT 1256
ShowWindow $0 ${SW_HIDE}
GetDlgItem $0 $HWNDPARENT 1028
ShowWindow $0 ${SW_HIDE}
FunctionEnd
用System::Call命令呼叫SetWindowLong的API函式改變GWL_STYLE的樣式即可,System是NSIS官方外掛用於幫助使用者呼叫系統函式,是相當重要的自動安裝程式的外掛!程式中其餘的程式碼是把建立的1004頁面上其餘的控制元件給隱藏掉,後面攜帶的ID都是可以通過ResHacker在105包中查詢到。
-
-
貼一張大小合適的背景圖
貼圖需要用到nsDialogs外掛的命令:
1 2 3 4 5 6 ;貼背景大圖
${NSD_CreateBitmap} 0 0 100% 100%
""
Pop $BGImage
${NSD_SetImage} $BGImage $PLUGINSDIR\bg.bmp $ImageHandle
${NSD_FreeImage} $ImageHandle
${NSD_CreateBitmap}命令建立一個跟窗體一樣大小的圖片區域,後面的五個引數分別是x,y,width,height,text,座標,寬高,文字。緊接著給這張圖貼上一張合適的圖片bg.bmp,貼圖片之前需要把這個圖片打包到安裝程式中,這個是基本的操作,原始碼包中有,這裡就不做說明了。最後還要通過${NSD_FreeImage}去釋放該圖片記憶體區。
-
無標題移動
做到無標題移動的潛臺詞是把原本傳遞給標題欄的Message通過你定義的元素回撥傳遞給標題欄,所以只要給你新增的資源加上傳遞資訊的回撥函式就可以了。這裡是通過WinProc這個外掛完成的,WinProc這個外掛在官方的外掛庫中沒有,Google一下就可以查詢到,這裡的原始碼包中也有。除了WinProc,第三方外掛SkinBtn也可以幫助實現。
1 2 3 4 5 Function onGUICallback
${If} $MSG = ${WM_LBUTTONDOWN}
SendMessage $HWNDPARENT ${WM_NCLBUTTONDOWN} ${HTCAPTION} $0
${EndIf}
FunctionEnd
以上是回撥函式,判斷滑鼠左鍵的Down事件,並且傳遞訊息給標題欄。
1 2 GetFunctionAddress $0 onGUICallback
WndProc::onCallback $BGImage $0 ;處理無邊框窗體移動
以上是把當前的$BGImage作為回撥主體,當用戶左鍵點選$BGImage的時候,訊息就傳遞給了窗體標題欄,實現了無邊框的移動。
**結束語**
看看結果是什麼樣子的……哦!kugou也被我山寨了一把,有人精益求精,說,你的程式滑鼠放在哪裡都能移動,人家kugou只能標題欄移動……是的呀,你把圖切成幾份,分別貼,有的給回撥函式,有的不給就實現了訊息部分傳遞的功能。
有一個注意點:貼圖的時候注意了!程式碼的執行是自上而下,如果要貼的圖需要在另一張上面的話,需要把程式碼寫在前面。
比如:
1 2 3 4 5 6 7 8 9 |
;貼小圖
${NSD_CreateBitmap} 0 34 100% 100% ""
Pop $MiddleImage
${NSD_SetImage} $MiddleImage $PLUGINSDIR\middle.bmp $ImageHandle
;貼背景大圖
${NSD_CreateBitmap} 0 0 100% 100% ""
Pop $BGImage
${NSD_SetImage} $BGImage $PLUGINSDIR\bg.bmp $ImageHandle
|
That's all
下回繼續探討
***************************
特別感謝石頭(石頭的qq群號97208217),夢想吧論壇(雖然我還不是個會員,但是學到了很多)