1. 程式人生 > >NSIS進階教程(一)

NSIS進階教程(一)

自定義介面之無邊框窗體移動貼圖

**前言**

在Windows下,有很多人想做一個完全自己把控的安裝程式,想過很多種途徑去實現,有人說MFC可以實現,有人說C#可以實現,有人說Delphi可以實現,有人說VB又未嘗不可呢。MFC,Delphi,VB,C#都需要自己去實現打包壓縮,釋放,釋放過程中的業務邏輯跟介面功能,是一項比較麻煩的工作,甚至於C#程式需要執行的話,還需要裝dotnet Framework的runtime。NSIS製作的安裝包可以執行在Win9x下,完全是WinAPI的呼叫,不需要額外裝任何的runtime,安裝包雙擊就能執行,本身封裝了很多Win的函式,方便呼叫與開放介面。功能部分也是實現了基本的安裝過程所需的操作,NSIS的很多Editor做到了嚮導模式的指令碼生成,很是方便。

這麼好的工具能否定製開發呢,答案是肯定的。

本篇主要講講以下幾點:

  1. 如何消除普通的NSIS指令碼生成的窗體的邊框

  2. 如何使得無邊框窗體能夠移動

  3. 如何給這個窗體貼上一張大小合適的背景圖

所用到的NSIS外掛:

  • nsDialogs

  • nsWindows

  • WinProc

  • System

**講義**:

首先貼出一個今天教程的完整的例子(附帶圖片) 猛擊這裡

題外話,本來想用新浪愛問做檔案分享平臺的,發現上傳後一直在稽核中……練葵花寶典能力誰也比過性浪呀,用CSDN也不好,還要登入,本人就因為積分太少而不得不去做無聊的工作贏得積分,用於CSDN下載,自從CSDN把我的密碼明碼儲存還被黑客給搞了之後,我不再上此網站。115雖然下載頁廣告多的一筆,但是後臺上傳頁相當的乾淨,還不用稽核以及無登陸下載,極致方便大家。(115被政府搞了,轉性浪愛問)

使用時:把外掛DLL跟標頭檔案分別放入到你的NSIS本地對應的安裝目錄中,然後編譯原始碼即可。

下文都用%NSIS_Install_DIR%來替代你本地安裝路徑

  1. 去除窗體Border

    在去除窗體邊框之前有一項工作是必須做的,那就是更改預設窗體的大小,因為每個人想做的打包窗體不可能都一樣大,更改窗體大小有兩種方法,也可以兩種方法並用

    1. 修改NSIS內部的UI

      NSIS的預設UI放在"%NSIS_Install_DIR%\Contrib\UIs"中,其中常常見到的建立自定義窗體的1018,1044都在此路徑的modern.exe中。我們只要修改modern.exe裡面的資原始檔即可,做過MFC的都知道,VC在建立程式的時候是有Resources的,只要找到一些能更改Resources裡面Dialog的工具即可,本文推薦

      ResHacker

      修改的時候寧可大點,也絕不小,因為開發過程中我遇到用nsWindows命令擴大窗體的時候,出現不起作用的情況,但是預設窗體比需要的窗體小的時候可以用nsWindows命令控制。

      開啟ResHacker工具拖入modern.exe,操作前請備份modern.exe,拖動資源窗體或者直接修改你想要的大小。預設的1044跟1018窗體都在105分類下。

    2. 通過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包中查詢到。

  2. 貼一張大小合適的背景圖

    貼圖需要用到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}去釋放該圖片記憶體區。

  3. 無標題移動

    做到無標題移動的潛臺詞是把原本傳遞給標題欄的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),夢想吧論壇(雖然我還不是個會員,但是學到了很多)