文章目录
- 一、前言
- 二、最终效果
- 三、GitHub工程
- 四、实现原理
- 五、界面美化逻辑实现
- 1、资源目录
- 2、创建文本
- 3、创建按钮
- 4、创建背景图
- 5、启动定时器
- 6、创建输入编辑框
- 7、设置UI对象显示与隐藏
- 8、监听安装进度
- 六、Demo工程具体使用
- 1、中文支持
- 2、放exe程序文件
- 3、放界面图片素材
- 4、使用
- 七、补充:iss脚本基础知识
- 1、[Setup]
- 2、[Languages]
- 3、[Tasks]
- 4、[Files]
- 5、[Icons]
- 6、[Run]
- 7、[Registry]
- 8、[Code]
- 八、补充2:Pascal语法简单介绍
- 1、数据类型
- 1.1、整型数据
- 1.2、实型数据
- 1.3、字符类型
- 1.4、布尔类型
- 1.5、CONST常量
- 2、赋值语句
- 3、if语句
- 4、case语句
- 5、for循环语句
- 6、while循环语句
- 7、引用其他脚本
- 8、define常量与应用
一、前言
之前我写过一篇《Unity发布PC版,使用Inno Setup制作安装程序》,建议先看那一下那篇文章。今天,我要讲讲通过InnoSetup如何实现Setup安装程序的界面美化。
二、最终效果
如下,效果还可以吧,觉得不错的可以点个赞~
三、GitHub工程
本文的Demo我已上传到GitHub,感兴趣的同学可以下载下来学习,觉得不错的话,记得给个星星~
GitHub工程地址:https://github.com/linxinfa/Beautiful-InnoSetup-Demo
四、实现原理
首先,你需要安装InnoSetup。
InnoSetup下载地址:https://jrsoftware.org/isinfo.php
InnoSetup通过 Pascal Scripting: Event Functions这种事件机制,把流程节点的控制交给Pascal Script,使其可以控制上一步、下一步等等的操作。
界面的美化,主要是调用两个美化插件动态库:botva2.dll和 InnoCallback.dll。用其来控制贴图的位置和样式,和给按钮绑定相应的事件等等的。
点击下载InnoCallback.dll
点击下载botva2.dll
五、界面美化逻辑实现
美化界面用到了botva2.dll。需要引入DllsImport.iss。
#include "DllsImport.iss"
1、资源目录
界面资源放在res/tmp目录中,包括我们引用的两个dll:botva2.dll、InnoCallback.dll
2、创建文本
接口:
function TLabel.Create(hParent:HWND):TLabel
例:
var lblWelcome:TLabel;beginlblWelcome := TLabel.Create(WizardForm);with lblWelcome dobeginParent := WizardForm;Caption := '欢迎安装XXX应用程序';Transparent := true;Font.Size:= 20Font.Name:='黑体'Font.Color:=$ffffffLeft := DpiScale(190);Top := DpiScale(195);end;end;
3、创建按钮
接口
function BtnCreate(hParent:HWND; Left,Top,Width,Height:integer; FileName:PAnsiChar; ShadowWidth:integer;IsCheckBtn:boolean):HWND;
例:
var btnOneKey:HWND;BtnOneKeyFont:TFont;begin// 创建按钮btnOneKey:=BtnCreate(WizardForm.Handle,DpiScale(240),DpiScale(260),DpiScale(177), DpiScale(43), ExpandConstant('{tmp}\btnOneKeyInstall.png'), 1, False);//设置按钮文字BtnSetText(btnOneKey, '一键安装');//文字字体BtnOneKeyFont:= TFont.Create;with BtnOneKeyFont do begin Size := 20;Name:='黑体';Color:=$ffffff;end;//应用字体BtnSetFont(btnOneKey, BtnOneKeyFont.Handle);BtnSetFontColor(btnOneKey,$FAFAFA,$FFFFFF,$FFFFFF,$FFFFFF);//设置按钮点击函数BtnSetEvent(btnOneKey, BtnClickEventID, WrapBtnCallback(@btnOneKey_OnClick,1));end;// 按钮点击回调procedure btnOneKey_OnClick(hBtn:HWND);beginWizardForm.NextButton.OnClick(WizardForm);WizardForm.NextButton.OnClick(WizardForm);end;
4、创建背景图
var imgBg1:Longint;winW:integer;winH:integer;begin//窗口宽高winW:=DpiScale(660)winH:=DpiScale(480)//创建背景图imgBg1 := ImgLoad(WizardForm.Handle, ExpandConstant('{tmp}\bg.png'), (0), (0), winW, winH, True, True);//设置背景图的隐藏//ImgSetVisibility(imgBg1, false);end
5、启动定时器
接口
function SetTimer(hWnd: longword; nIDEvent, uElapse: LongWord; lpTimerFunc: LongWord): LongWord;
例:
通过定时器轮播背景图
SetTimer(0, 0, 50, WrapTimerProc(@PageInstall_TimerProc, 4));procedure PageInstall_TimerProc(H: LongWord; Msg: LongWord; IdEvent: LongWord; Time: LongWord);begin//轮播背景图逻辑end
6、创建输入编辑框
beginedtSelectDir1 := TEdit.Create(WizardForm);with edtSelectDir1 dobeginParent:= WizardForm;Text := WizardForm.DirEdit.Text;Font.Size:= 10Font.Color:=$555555Left:= DpiScale(132);Top := DpiScale(189);Width:= DpiScale(311);Height:= DpiScale(24);BorderStyle:=bsNone;TabStop := false;OnChange:=@EdtSelectDir1_EditChanged;end;end
7、设置UI对象显示与隐藏
//隐藏按钮BtnSetVisibility(btn, false);//隐藏图片ImgSetVisibility(imgBig, false);//隐藏文本TLabel、隐藏输入框TEditTconSetVisible(lbl, false);TconSetVisible(edt, false);
8、监听安装进度
用到了Windows的API。
function SetWindowLong(Wnd: HWnd; Index: Integer; NewLong: Longint): Longint; external 'SetWindowLongA@user32.dll stdcall';
例:
//设置监听PBOldProc:=SetWindowLong(WizardForm.ProgressGauge.Handle,-4, PBCallBack(@PBProc,4));//回调function PBProc(h:hWnd;Msg, wParam,lParam:Longint):Longint;varpr, pos,total: Longint;w : integer;begin// CallWindowProc是将消息信息传送给指定的窗口过程的函数Result:=CallWindowProc(PBOldProc, h, Msg, wParam,lParam);if (Msg=$402) and (WizardForm.ProgressGauge.Position > WizardForm.ProgressGauge.Min) thenbeginpos:=WizardForm.ProgressGauge.Position-WizardForm.ProgressGauge.Min;total:=WizardForm.ProgressGauge.Max-WizardForm.ProgressGauge.Min;pr:=pos*100/total;//更新进度条PageInstall_SetProgress(pr);Notify_DoNotifyProgress(pos, total);end;end;
六、Demo工程具体使用
1、中文支持
为了支持setup程序显示中文,需要配置中文语言文件:ChineseSimplified.isl
点击查看ChineseSimplified.isl
需将ChineseSimplified.isl放在InnoSetup安装目录中的Languages目录中。
2、放exe程序文件
将要打包的程序文件放在pkgs目录中,如下放在pkgs/v1目录中,我用的是Unity发布了一个windows平台的包。
iss脚本中指明路径,并指明主程序文件,即.exe文件
#define MyAppPkgDir ".\pkgs\v1"#define MyAppExeName "我的应用.exe"
3、放界面图片素材
界面素材放在res/tmp目录中
在iss中需要执行解压拷贝
// 将tmp的资源, 解压到安装运行时搞出来的临时目录ExtractTemporaryFile('bg.png');ExtractTemporaryFile('bg2.png');ExtractTemporaryFile('btclose.png');ExtractTemporaryFile('btmin.png');ExtractTemporaryFile('btn.png');ExtractTemporaryFile('btnOneKeyInstall.png');ExtractTemporaryFile('check.png');ExtractTemporaryFile('progress.png');ExtractTemporaryFile('progressBg.png');for i := 1 to InsBgAni_ImgCount doExtractTemporaryFile(Format('pic%d.png',[i]) );
4、使用
用InnoSetup打开MakePCSetup.iss
执行脚本(按F9),即可生成setup程序
生成的setup文件在output目录中。
七、补充:iss脚本基础知识
我们通过上一篇的教程(点击查看),可以生成一个iss脚本,我们需要看懂这个脚本,然后对他进行修改和新增代码,实现我们的界面美化功能。
建议过程中可以翻翻Inno Setup帮助说明文档:https://jrsoftware.org/ishelp/index.php
我们的iss脚本的结构是这样的:
[Setup][Languages][Tasks][Files][Icons][Run][Registry][Code]
1、[Setup]
这个段包含用于安装程序和卸载程序的全局设置。
例
[Setup]AppId=123456789AppName="我的应用"AppVersion=1.5AppPublisher="公司名"DefaultDirName={autopf}\My ProgramDefaultGroupName=My Program
2、[Languages]
InnoSetup制作的安装程序,支持多种语言设置,默认是英文的,如果要设置中文,需要配置对应的中文语言。
语言文件是.isl格式的,将其放在InnoSetup安装目录中的Languages目录中。
然后在脚本中指明语言文件。
[Languages]Name: "chs"; MessagesFile: "compiler:Languages\ChineseSimplified.isl"
哪里下载这个ChineseSimplified.isl呢?点我下载。
3、[Tasks]
它定义安装程序在执行安装期间所有由用户定制的任务。这些任务以选项框和单选项形式在附加任务向导页中出现。
例:
[Tasks]Name: "desktopicon"; Description: "创建桌面快捷方式"; GroupDescription: "添加快捷方式:"; Flags: checkedonceName: "quicklaunchicon"; Description: "创建快速运行栏快捷方式"; GroupDescription: "添加快捷方式:"; Flags: checkedonce
4、[Files]
定义安装程序要安装在用户系统上的任何文件。
例:
[Files]Source: "CTL3DV2.DLL"; DestDir: "{sys}"; Flags: onlyifdoesntexist uninsneveruninstallSource: "MYPROG.EXE"; DestDir: "{app}"Source: "MYPROG.CHM"; DestDir: "{app}"Source: "README.TXT"; DestDir: "{app}"; Flags: isreadme
5、[Icons]
定义所有创建在开始菜单或其它位置 (比如桌面) 的快捷方式。
例:
[Icons]Name: "{group}\My Program"; Filename: "{app}\MYPROG.EXE"; WorkingDir: "{app}"Name: "{group}\Uninstall My Program"; Filename: "{uninstallexe}"
6、[Run]
用来指定程序完成安装后要执行的程序。
例:
[Run]Filename: "{app}\MYPROG.EXE"; Description: "Launch application"; Flags: postinstall nowait skipifsilent unchecked
7、[Registry]
定义安装程序在用户系统上创建、修改或删除的任何注册表项/值。
例:
[Registry]Root: HKLM; Subkey: "Software\My Company"; Flags: uninsdeletekeyifemptyRoot: HKLM; Subkey: "Software\My Company\My Program"; Flags: uninsdeletekeyRoot: HKLM; Subkey: "Software\My Company\My Program\Settings"; ValueType: string; ValueName: "InstallPath"; ValueData: "{app}"
其中Root的值简写对照表如下
HKCU(HKEY_CURRENT_USER)HKLM(HKEY_LOCAL_MACHINE)HKCR(HKEY_CLASSES_ROOT)HKU(HKEY_USERS)HKCC(HKEY_CURRENT_CONFIG)
8、[Code]
最重头的部分来了,[Code]部分使用的是Pascal语言编写的。我们的界面美化,就是在这里实现的。
八、补充2:Pascal语法简单介绍
1、数据类型
1.1、整型数据
类型数值范围占字节数格式
| shortint | -128 ~ 128 | 1 | 带符号 8 位 |
| inteter | -32768 ~ 32767 | 2 | 带符号 16 位 |
| longint | -2147483648 ~ 2147483647 | 4 | 带符号 32 位 |
| byte | 0 ~ 255 | 1 | 带符号 8 位 |
| word | 0 ~ 65535 | 2 | 带符号 16 位 |
例:
varage:shortint;beginage:=18;end;
1.2、实型数据
类型占字节数有效位数
| single | 4 | 7~8 |
| real | 6 | 11~12 |
| double | 8 | 15~16 |
| extended | 10 | 19~20 |
| comp | 8 | 19~20 |
例:
vara:single;begina:=1.3;end;
1.3、字符类型
例:
vara:String;b:String;begina:="hello world";b:=format('字符串拼接:%s', a);end;
1.4、布尔类型
例:
vara:boolean;begina:=true;end;
1.5、CONST常量
例:
constpi=3.14159;zero=0;
2、赋值语句
变量名:=表达式;
例:
a:="hello world";
3、if语句
例:
if x>y thena:="big"elsea:="small";
4、case语句
例:
var month,days:integer; begin write('Input month:');readln(month); case month of 1,3,5,7,8,10,12:days:=31; 4,6,9,11:days:=30; 2:days:=28; else days:=0; end;end;
5、for循环语句
例:
求N的阶乘,N!=1*2*3*…*N,这里 N不大于 10。
var n,i:integer;s:longint;begin write('Enter n=');readln(n);s:=1; for i:=2 to n dos:=s*i; writeln(n, '的阶乘为:', s);end;
6、while循环语句
例:
vara,:integer;begina:=10;while a>0 dobegina:=a-1;end;end;
7、引用其他脚本
#include "DllsImport.iss"
8、define常量与应用
#define MyAppName "我的应用名"[Setup]AppName={#MyAppName}