innosetup教程【2】如何通過[code]欄位自定義安裝介面
目標要求:
1、 介面border去掉原本windows自帶的對話方塊格式,採取扁平化設計;
2、 簡化安裝流程,不要彈出那麼多安裝嚮導頁,不要讓使用者一直點“下一步”,簡潔人性化;
3、 安裝介面可載入漂亮的背景圖片;
4、 優化安裝包安裝時間。
原型設計:
介面1
介面2
介面3
開發工具:
因為之前採用Inno setup設計,而且它擁有Pascal指令碼引擎,功能算強大,故採用Inno setup。
主要流程:
流程圖
由圖中可以清晰地看出,所有嚮導頁之間都是通過“下一步”或者“上一步”進行驅動更換的。
概要分析:
這裡需要呼叫兩個美化外掛動態庫:botva2.dll和InnoCallback.dll,用於介面的美化和功能完善。這裡就不全部把程式碼貼出來了,只針對其中的要點進行分析概括。
在開始之前,先了解一下inno setup基本的過程和函式。
//該過程在開始的時候改變嚮導或者嚮導頁,不要指望使用InitializeSetup函式實現改變嚮導頁的功能,因為InitializeSetup函式觸發時嚮導視窗並不存在。 procedure InitializeWizard(); //該函式在安裝程式初始化時呼叫,返回False 將中斷安裝,True則繼續安裝. function InitializeSetup(): Boolean; //該過程提供使用者完成預安裝和安裝之後的任務,更多的是提供了安裝過程中的狀態。引數CurStep=ssInstall是在程式實際安裝前,CurStep=ssPostInstall是實際安裝完成後,而CurStep=ssDone是在一次成功的安裝完成後、安裝程式終止前(即點選finish按鈕後執行)。 procedure CurStepChanged(CurStep: TSetupStep); //當用戶單擊下一步按鈕時呼叫。如果返回True,嚮導將移到下一頁;如果返回False,它仍保留在當前頁。 function NextButtonClick(CurPageID: Integer): Boolean; //嚮導呼叫這個事件函式確定是否在所有頁或不在一個特殊頁 (用PageID 指定) 顯示。如果返回True,將跳過該頁;如果你返回False,該頁被顯示。注意: 這個事件函式不被wpWelcome、wpPreparing 和wpInstalling 頁呼叫,還有安裝程式已經確定要跳過的頁也不會呼叫 (例如,沒有包含元件安裝程式的wpSelectComponents)。 function ShouldSkipPage(PageID: Integer): Boolean; //在新嚮導頁 (由CurPageID 指定) 顯示後呼叫。 procedure CurPageChanged(CurPageID: Integer);
1、 介面border去掉原本windows自帶的對話方塊格式,採取扁平化設計
//設定歡迎向導頁的尺寸大小:
WizardForm.Center WizardForm.BorderStyle:=bsNone; //去掉對話方塊border WizardForm.ClientWidth:=601;
WizardForm.ClientHeight:=341;
WizardForm.InnerNotebook.Hide;
WizardForm.OuterNotebook.Hide;
wizardform.Color:=TransparentColor;
WizardForm.Bevel.Hide;
WizardForm.NextButton.Width:=0;
WizardForm.BackButton.Width:=0;
WizardForm.CancelButton.Width:=0;
WizardForm.OnMouseDown: [email protected]; //可拉動
2、 簡化安裝包安裝流程,不要使用者一直點“下一步”,簡潔人性化
這裡只有兩個嚮導頁,一個是選擇安裝目錄和許可協議的介面,一個是正在安裝的介面。使用者只需點選“開始安裝”即可安裝,並有進度條和百分比顯示,不用經常性地點選“下一步”。
3、 安裝介面可載入漂亮的圖片和動畫效果
// 建立描述點陣圖
Bmp:= TBitmapImage.Create(WizardForm);
Bmp.Top:=ScaleX(0);
Bmp.Left:=ScaleX(0);
Bmp.Width:=WizardForm.ClientWidth;
Bmp.Height:=ScaleY(371);
Bmp.BackColor:= WizardForm.Color;
Bmp.Parent:=WizardForm;
Bmp.Bitmap.LoadFromFile(ExpandConstant('{tmp}\bg.bmp'));
Bmp.OnMouseDown := @WizardFormMouseDown; //可拉動
//動畫效果
AnimateWindow(StrToInt(ExpandConstant('{wizardhwnd}')), 400, AW_Center or AW_Activate);
SetWindowLong(StrToInt(ExpandConstant('{wizardhwnd}')),GWL_Exstyle, WS_Ex_Layered);
SetLayeredWindowAttributes(StrToInt(ExpandConstant('{wizardhwnd}')), 0, 240, LWA_Alpha);
4、 優化安裝包安裝時間。
把不用的安裝檔案重新梳理了一遍,減少打包時的體積,不用多次呼叫讀寫登錄檔。
難點分析:
1、 如何跳過嚮導頁?
//主要是程式呼叫“下一步”,然後在ShouldSkipPage函式中進行跳過。
function ShouldSkipPage(PageID: Integer): Boolean;
begin
if PageID=wpWelcome then
result := true;
if PageID=wpSelectDir then
result := true;
end;
2、 “下一步”如何呼叫?
WizardForm.NextButton.OnClick(WizardForm);
3、 如何用滑鼠拉動對話方塊?
過載WizardFormMouseDown過程,然後呼叫SendMessage(WizardForm.Handle, WM_SYSCOMMAND, $F012, 0);
4、 如何自定義瀏覽資料夾按鈕?
//記住,獲得的路徑要賦給WizardForm.DirEdit.Text,這是瀏覽資料夾嚮導頁wpSelectDir的路徑編輯框。
procedure DirOnClick(hBtn:HWND);
var
res: Boolean;
UserSelectDir,str: string;
begin
UserSelectDir := Edit.Text;
res := BrowseForFolder('瀏覽資料夾', UserSelectDir, True);
if res then
begin
str:=Copy(UserSelectDir,Length(UserSelectDir),1);//取最後一個字元
if '\'=str then
Edit.Text := UserSelectDir
else
Edit.Text := UserSelectDir;
end;
//瀏覽資料夾嚮導頁的資料夾路徑
WizardForm.DirEdit.Text := Edit.Text;
end;
5、 如何點選按鈕顯示“許可協議”?
ShellExec('', ExpandConstant('{tmp}\license.txt'),'', '', SW_SHOW, ewNoWait, ErrorCode)。
6、 如何安裝程式完成後自動執行程式?
Exec(ExpandConstant('{app}\MySoftware.exe'), '', '', SW_SHOW, ewNoWait, RCode);
7、 如何刪除資料夾?
DelTree(ExpandConstant('{app}\資料夾名稱'), True, True, False);
8、 如何關閉嚮導頁?
WizardForm.Close;
9、 如何自定義完成嚮導頁的完成按鈕?
通過程式自行呼叫WizardForm.NextButton.OnClick(WizardForm);達到“下一步”的功能;
然後通過函式ShouldSkipPage一直調到最後完成頁wpFinished;
最後呼叫WizardForm.NextButton.OnClick(WizardForm);完成。
10、 如何在安裝頁面換背景圖片?
procedure CurPageChanged(CurPageID: Integer);
begin
if CurPageID = wpInstalling then
begin
Bmp:= TBitmapImage.Create(WizardForm);
Bmp.Top:=ScaleX(0);
Bmp.Left:=ScaleX(0);
Bmp.Width:=WizardForm.ClientWidth;
Bmp.Height:=ScaleY(371);
Bmp.BackColor:= WizardForm.Color;
Bmp.Parent:= WizardForm;
Bmp.Bitmap.LoadFromFile(ExpandConstant('{tmp}\bg2.bmp'));
Bmp.OnMouseDown := @WizardFormMouseDown;
WizardForm.OnMouseDown:[email protected];
end;
end;
11、 如何讀寫登錄檔?
//讀取資訊
RegQueryStringValue(HKLM, 'Software\***\***','Version',svValue)
//寫入資訊
RegWriteStringValue(HKLM, 'Software\***\***','Version', '4.0');
12、 安裝前如何判斷是否有程序正在進行?
//安裝前判斷是否有程序正在執行
function IsModuleLoaded(modulename: String ): Boolean;
external '[email protected]:psvince.dll stdcall setuponly';
IsModuleLoaded('Mysoftware.exe');
13、 如何使用botva2.dll外掛建立自定義按鈕?
//呼叫動態庫函式
function BtnCreate(hParent :HWND; Left, Top, Width, Height :integer; FileName :PAnsiChar; ShadowWidth :integer; IsCheckBtn :boolean) :HWND;
external '[email protected]:botva2.dll stdcall';
FinishBtnH := BtnCreate(WizardForm.Handle,ProgressBar.Left+ProgressBar.Width-83, ProgressBar.Top+ProgressBar.Height+ScaleX(10), ScaleX(83), ScaleY(28),ExpandConstant('{tmp}\Finish.png'),1,False);
BtnSetEvent(FinishBtnH,BtnClickEventID,WrapBtnCallback(@FinishButtonClick,1));
BtnSetVisibility(FinishBtnH,False);
14、 百分比如何確定?
//百分比
function PBProc(h:hWnd;Msg,wParam,lParam:Longint):Longint;
var
pr,i1,i2 : Extended;
w : integer;
begin
Result:=CallWindowProc(PBOldProc,h,Msg,wParam,lParam);
if (Msg=$402) and (WizardForm.ProgressGauge.Position>WizardForm.ProgressGauge.Min) then
begin
i1:=WizardForm.ProgressGauge.Position-WizardForm.ProgressGauge.Min;
i2:=WizardForm.ProgressGauge.Max-WizardForm.ProgressGauge.Min;
pr:=i1*100/i2;
PrLabel.Caption:=IntToStr(Round(pr))+'%';
w:=Round(110*pr/100); //改變數值,達到百分比和進度條的同步
ProgressBar.Position := w;
end;
end;
錯誤解決:
對於某些電腦環境,安裝時只要點選“退出”按鈕或者安裝完後總會遇到這個錯誤,彈出以下提示圖片:
錯誤問題
解決辦法:
因為呼叫WizardForm.Close或者WizardForm.NextButton.OnClick(WizardForm)退出時沒有進行WizardForm的資源釋放,所以導致了該錯誤。只要在退出或者完成前加上WizardForm.Release即可解決。
相關推薦
innosetup教程【2】如何通過[code]欄位自定義安裝介面
目標要求: 1、 介面border去掉原本windows自帶的對話方塊格式,採取扁平化設計; 2、 簡化安裝流程,不要彈出那麼多安裝嚮導頁,不要讓使用者一直點“下一步”,簡潔人性化; 3、 安裝介面可載入漂亮的背景圖片;
【PHP】通過header發送自定義數據
example color 發送 uil ade field urn server font 發送header: 我們定義了三個參數,token、language、region,放入header發送過去 <?php $url = ‘http://www.exam
Microsoft Azure Web Sites應用與實踐【2】—— 通過本地IIS 遠端管理Microsoft Azure Web Site
Microsoft Azure Web Sites應用與實踐 系列: 通過本地IIS 遠端管理Microsoft Azure Web Site 在上一篇博文中,我們介紹了Microsoft Azure Web Site的快速生成。假如您之前有接觸或使用過IIS ,相信您會記得它簡潔方便的管
TI—CC3200【2】通過UDP傳輸音訊
手上有一套TICC3200+TLV320AIC3254開發板,這個是TI官方出的一款評估板。 在官方給出的例程裡面只有一個是關於音訊的“wifi_audio_app”,這個例子使用兩塊開發板相互連線後相互傳輸音訊並且播放的。 現在我手上只有一塊開發板
【轉載】SAP OO ALV 在自定義螢幕上新增ALV控制元件 一個螢幕上使用2個ALV
終於完成了 OO ALV的學習,第一個作品。 一個螢幕上放了2個ALV控制元件,上面用來顯示錶頭,下面用來顯示詳細的行專案。 業務背景: 在汽車的售後服務環節,汽車零件在質保期內損壞,維修產生的費用,整車廠會追溯到零件供應商索取。 資料模型簡介: 三包索賠單資料從銷售系統中傳入ERP系統。
【MyBatis】解決資料庫欄位名稱與Java實體類屬性名稱不一致問題
問題描述: 有時候在專案中會遇到資料庫欄位名稱與實體類屬性名稱取得不一樣的情況,如下: 資料庫裡的資料為: 此時,如果我們查詢該表的某條資料,Proj
【mysql】MySQL新增欄位和修改欄位
MySQL新增欄位的方法並不複雜,下面將為您詳細介紹MYSQL新增欄位和修改欄位等操作的實現方法,希望對您學習MySQL新增欄位方面會有所幫助。 1新增表字段 alter table table1 add transactor varchar(10) not Null
【Django】orm指定欄位名,表名
1.指定欄位名: 在定義欄位的時候,增加引數db_column=’real_field’; 2.指定表名: 在model的class中,新增Meta類,在Meta類中指定表名db_table 例如在某個
【TP5】根據資料庫欄位註釋使用同一模板進行增刪查
author:咔咔 wechat:fangkangfk 有沒有在新增跟修改的時候很煩,需要寫很多頁面,修改還需要追加資料,很煩,很煩 下來就解決這樣的問題,所有模組的新增,修改,檢視,都使用同一個模板 首先從資料庫設計開始 註釋解釋:
【原創】user.id欄位
odoo中User.ID 欄位是使用者登入表 res_users 中的欄位,所以要關聯某個使用者或是判斷某個使用者,可以利用該欄位。 例如:在某個 介面中的domain中,要求顯示的是關聯某使用者的單子,則如下寫: &nbs
【ios學習記錄】- 通過nib檔案實現自定義表檢視單元
新增自定義表檢視單元有兩種方法:一種方法是建立單元時在程式中新增子檢視,第二種方法是從分鏡或者nib檔案中載入它們,在這裡我們簡單採用第二種方法 一般來說,ios資料列表包含了兩部分:表檢視(分組表和無格式表)和表檢視單元。每個表檢視都是UITable
【jmeter】通過Cookie跳過驗證碼登入介面
目錄 一、基本配置 二、HTTP請求預設值 (1)jmeter的設定: (2)設定HTTP請求預設值的優點: 1.該預設請求值下的所有介面,都不用填以下截圖這幾個選項。 2.而且可以通過修改預設值的域名和埠,來統一修改同介面名不同域名的請
【MYSQL】判斷某個欄位值是否包含於某個字串中
SQL函式:INSTR(str1,str2); //mysql中的語法似乎只支援2個引數 引數說明:str1:在這個字串中查詢、str2:欄位值 舉個例子:查詢出名字在字串“張三王五朱六”出現的記錄 表資料:
【Oracle】觸發器更新欄位後自動更新某欄位
CREATE OR REPLACE TRIGGER tig_d22_face BEFORE UPDATE ON HRM_ECARD.HRM_CARD_CD_D22_FACE FOR EACH ROWBEGIN IF UPDATING ('HCI_COMPUTE
【UE4】 第07講 實現自定義的行走控制元件
在圖形業,只有技術是不行的,你要明白我們從事的工作,我們可是在作詩,我們是詩人 - Nvidia創始人黃仁勳(圖形皇帝) (版權宣告,禁止轉載) U
【javascript】DOM模擬事件 和 自定義事件
事件,就是網頁中某一個特別值得關注的瞬間。 事件經常由使用者操作或通過其他瀏覽器功能來觸發。 但是也可以使用Javascript在任意時刻觸發特定的事件,這個時候的事件和瀏覽器建立的事件一樣。 也就是說這些事件還是有冒泡等屬性,而且瀏覽器也會響應該事件去執行相應的事件處理程式。 我們來跑一
【轉】手把手教你實現自定義的應用層協議
原文: https://my.oschina.net/u/2245781/blog/1622414 報錯了, 在Linux系統中,/usr/include/ 是C/C++等的標頭檔案放置處, -----------------------
【Jmeter】Jmeter使用AbstractJavaSamplerClient編寫自定義流程測試
一、前言 在上一篇部落格中,小編向大家簡單介紹了jmeter 的GUI介面的壓測使用步驟,通過這個步驟我們可以應付大部分的壓測問題了。很多介面都可以通過這種方式來得到壓測報告,根據壓測報告的資料來分析線上真正要使用多少臺機器。 但是有的時
【原始碼】Gabor特徵提取——採用自定義的Gabor濾波器組提取影象特徵
第一個名為“gaborFilterBank.m”的函式生成一個自定義的Gabor濾波器組。 The first function named “gaborFilterBank.m” generates a custom-sized Gabor filter bank. 它建立了一個u
【OpenResty】lua指令碼實現nginx自定義log
1,OpenResty(Nginx) Nginx (engine x) 是一個高效能的HTTP和反向代理伺服器,也是一個IMAP/POP3/SMTP伺服器。Nginx是由伊戈爾·賽索耶夫為俄羅斯訪問量第二的Rambler.ru站點(俄文:Рамблер)