“安裝界面太丑了,不堪入目!”
“這界面應(yīng)該屬于20年代初的舊產(chǎn)物……”
“難看!”
每每聽到設(shè)計(jì)師和產(chǎn)品經(jīng)理這樣的吐槽時(shí),心中難免會(huì)有一點(diǎn)失落。細(xì)看一下,咱們軟件的安裝包界面的確還是比較古老,仍然帶有xp系統(tǒng)自帶的界面邊框。于是趁著這次新版軟件發(fā)布之際,專門花了時(shí)間去研究界面設(shè)計(jì)。
**目標(biāo)要求:**
1、 界面border去掉原本windows自帶的對話框格式,采取扁平化設(shè)計(jì);
2、 簡化安裝流程,不要彈出那么多安裝向?qū)ы摚灰層脩粢恢秉c(diǎn)“下一步”,簡潔人性化;
3、 安裝界面可加載漂亮的背景圖片;
4、 優(yōu)化安裝包安裝時(shí)間。
**原型設(shè)計(jì):**
界面1
界面2
界面3
**開發(fā)工具:**
因?yàn)橹安捎肐nno setup設(shè)計(jì),而且它擁有Pascal腳本引擎,功能算強(qiáng)大,故采用Inno setup。
**主要流程:**

由圖中可以清晰地看出,所有向?qū)ы撝g都是通過“下一步”或者“上一步”進(jìn)行驅(qū)動(dòng)更換的。
**概要分析:**
這里需要調(diào)用兩個(gè)美化插件動(dòng)態(tài)庫:botva2.dll和InnoCallback.dll,用于界面的美化和功能完善。這里就不全部把代碼貼出來了,只針對其中的要點(diǎn)進(jìn)行分析概括。
在開始之前,先了解一下inno setup基本的過程和函數(shù)。
//該過程在開始的時(shí)候改變向?qū)Щ蛘呦驅(qū)ы摚灰竿褂肐nitializeSetup函數(shù)實(shí)現(xiàn)改變向?qū)ы摰墓δ埽驗(yàn)镮nitializeSetup函數(shù)觸發(fā)時(shí)向?qū)Т翱诓⒉淮嬖凇?procedure InitializeWizard();
//該函數(shù)在安裝程序初始化時(shí)調(diào)用,返回False 將中斷安裝,True則繼續(xù)安裝.
function InitializeSetup(): Boolean;
//該過程提供用戶完成預(yù)安裝和安裝之后的任務(wù),更多的是提供了安裝過程中的狀態(tài)。參數(shù)CurStep=ssInstall是在程序?qū)嶋H安裝前,CurStep=ssPostInstall是實(shí)際安裝完成后,而CurStep=ssDone是在一次成功的安裝完成后、安裝程序終止前(即點(diǎn)擊finish按鈕后執(zhí)行)。
procedure CurStepChanged(CurStep: TSetupStep);
//當(dāng)用戶單擊下一步按鈕時(shí)調(diào)用。如果返回True,向?qū)⒁频较乱豁摚蝗绻祷谾alse,它仍保留在當(dāng)前頁。
function NextButtonClick(CurPageID: Integer): Boolean;
//向?qū)д{(diào)用這個(gè)事件函數(shù)確定是否在所有頁或不在一個(gè)特殊頁 (用PageID 指定) 顯示。如果返回True,將跳過該頁;如果你返回False,該頁被顯示。注意: 這個(gè)事件函數(shù)不被wpWelcome、wpPreparing 和wpInstalling 頁調(diào)用,還有安裝程序已經(jīng)確定要跳過的頁也不會(huì)調(diào)用 (例如,沒有包含組件安裝程序的wpSelectComponents)。
function ShouldSkipPage(PageID: Integer): Boolean;
//在新向?qū)ы?(由CurPageID 指定) 顯示后調(diào)用。
procedure CurPageChanged(CurPageID: Integer);
1、 界面border去掉原本windows自帶的對話框格式,采取扁平化設(shè)計(jì)
//設(shè)置歡迎向?qū)ы摰某叽绱笮。?
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:=@WizardFormMouseDown; //可拉動(dòng)
2、 簡化安裝包安裝流程,不要用戶一直點(diǎn)“下一步”,簡潔人性化
這里只有兩個(gè)向?qū)ы摚粋€(gè)是選擇安裝目錄和許可協(xié)議的界面,一個(gè)是正在安裝的界面。用戶只需點(diǎn)擊“開始安裝”即可安裝,并有進(jìn)度條和百分比顯示,不用經(jīng)常性地點(diǎn)擊“下一步”。
3、 安裝界面可加載漂亮的圖片和動(dòng)畫效果
// 創(chuàng)建描述位圖
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; //可拉動(dòng)
//動(dòng)畫效果
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、 優(yōu)化安裝包安裝時(shí)間。
把不用的安裝文件重新梳理了一遍,減少打包時(shí)的體積,不用多次調(diào)用讀寫注冊表。
**難點(diǎn)分析:**
1、 如何跳過向?qū)ы摚?
//主要是程序調(diào)用“下一步”,然后在ShouldSkipPage函數(shù)中進(jìn)行跳過。
function ShouldSkipPage(PageID: Integer): Boolean;
begin
if PageID=wpWelcome then
result := true;
if PageID=wpSelectDir then
result := true;
end;
2、 “下一步”如何調(diào)用?
WizardForm.NextButton.OnClick(WizardForm);
3、 如何用鼠標(biāo)拉動(dòng)對話框?
重載WizardFormMouseDown過程,然后調(diào)用SendMessage(WizardForm.Handle, WM_SYSCOMMAND, $F012, 0);
4、 如何自定義瀏覽文件夾按鈕?
//記住,獲得的路徑要賦給WizardForm.DirEdit.Text,這是瀏覽文件夾向?qū)ы搘pSelectDir的路徑編輯框。
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);//取最后一個(gè)字符
if '\'=str then
Edit.Text := UserSelectDir
else
Edit.Text := UserSelectDir;
end;
//瀏覽文件夾向?qū)ы摰奈募A路徑
WizardForm.DirEdit.Text := Edit.Text;
end;
5、 如何點(diǎn)擊按鈕顯示“許可協(xié)議”?
ShellExec('', ExpandConstant('{tmp}\license.txt'),'', '', SW_SHOW, ewNoWait, ErrorCode)。
6、 如何安裝程序完成后自動(dòng)運(yùn)行程序?
Exec(ExpandConstant('{app}\MySoftware.exe'), '', '', SW_SHOW, ewNoWait, RCode);
7、 如何刪除文件夾?
DelTree(ExpandConstant('{app}\文件夾名稱'), True, True, False);
8、 如何關(guān)閉向?qū)ы摚?
WizardForm.Close;
9、 如何自定義完成向?qū)ы摰耐瓿砂粹o?
通過程序自行調(diào)用WizardForm.NextButton.OnClick(WizardForm);達(dá)到“下一步”的功能;
然后通過函數(shù)ShouldSkipPage一直調(diào)到最后完成頁wpFinished;
最后調(diào)用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:=@WizardFormMouseDown;
end;
end;
11、 如何讀寫注冊表?
//讀取信息
RegQueryStringValue(HKLM, 'Software\***\***','Version',svValue)
//寫入信息
RegWriteStringValue(HKLM, 'Software\***\***','Version', '4.0');
12、 安裝前如何判斷是否有進(jìn)程正在進(jìn)行?
//安裝前判斷是否有進(jìn)程正在運(yùn)行
function IsModuleLoaded(modulename: String ): Boolean;
external 'IsModuleLoaded@files:psvince.dll stdcall setuponly';
IsModuleLoaded('Mysoftware.exe');
13、 如何使用botva2.dll插件創(chuàng)建自定義按鈕?
//調(diào)用動(dòng)態(tài)庫函數(shù)
function BtnCreate(hParent :HWND; Left, Top, Width, Height :integer; FileName :PAnsiChar; ShadowWidth :integer; IsCheckBtn :boolean) :HWND;
external 'BtnCreate@files: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); //改變數(shù)值,達(dá)到百分比和進(jìn)度條的同步
ProgressBar.Position := w;
end;
end;
**錯(cuò)誤解決:**
對于某些電腦環(huán)境,安裝時(shí)只要點(diǎn)擊“退出”按鈕或者安裝完后總會(huì)遇到這個(gè)錯(cuò)誤,彈出以下提示圖片:
錯(cuò)誤問題
解決辦法:
因?yàn)檎{(diào)用WizardForm.Close或者WizardForm.NextButton.OnClick(WizardForm)退出時(shí)沒有進(jìn)行WizardForm的資源釋放,所以導(dǎo)致了該錯(cuò)誤。只要在退出或者完成前加上WizardForm.Release即可解決。