使用InnoSetup实现Setup安装程序界面美化

发布时间:2025-12-10 11:35:08 浏览次数:5

文章目录

      • 一、前言
      • 二、最终效果
      • 三、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 ~ 1281带符号 8 位
inteter-32768 ~ 327672带符号 16 位
longint-2147483648 ~ 21474836474带符号 32 位
byte0 ~ 2551带符号 8 位
word0 ~ 655352带符号 16 位

例:

varage:shortint;beginage:=18;end;
1.2、实型数据
类型占字节数有效位数
single47~8
real611~12
double815~16
extended1019~20
comp819~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}
需要做网站?需要网络推广?欢迎咨询客户经理 13272073477