因为项目需要,需要打 windows 安装包,要求安装界面完全按照需求来。作为没接触过这块儿的服务端宝宝,在此期间踩了很多坑。

坑不提也罢,最终结果圆满,记录下与大部分网上PO出来的做法不太一样的小心得,备忘。

网上搜到的自定义界面,都用的 botva2.dll ,我没用。应该说,用过,但遇到了图片变形的问题,短时间内没解决,所以最后全都用的 Inno Setup 原生类。Inno Setup 官方文档很详细,而且开源,所以原生用起来还是很顺利的。此前没接触过 Pascal 语言,但影响不大。

加载透明图片或按钮

网上多用 botva2.dll 来加载 png 图片,以达到圆角效果。由于遇到图片变形,我开始在官方文档里找替代方案。

Inno Setup 本身提供一个类 TBitmapImage 来支持带 alpha 通道的bmp 图片,也就是 32 位的 bmp 图片,支持透明效果。PhotoShop 中可通过添加 alpha 通道来生成 32 位 bmp 图。

显示图片方法:

val BmpImg : TBitmapImage;

BmpImg := TBitmapImage.Create(WizardForm); // 卸载时将 WizardForm 换为 UninstallProgressForm 即可
with BmpImg do
begin
Parent := WizardForm; // 卸载时将 WizardForm 换为 UninstallProgressForm 即可
Bitmap := TAlphaBitmap.Create;
Bitmap.AlphaFormat := afDefined; // 须设置此值,才能读取图片的 alpha 通道,应在加载图片文件前设置
Bitmap.LoadFromFile(ExpandConstant('{tmp}\xxx.bmp'));
BackColor := clNone; // 背景色应设置为 clNone,否则默认透明处为白色
OnClick := @some_procedure; // 按钮的点击回调,非按钮图片不需要
end;

按钮的点击回调形如:procedure some_procedure(sender: TObject);

设置 BmpImg.Enabled := False 可使图片的点击事件失效。

富文本

Inno Setup 的类 TRichEditViewer 支持 .rtf 格式的富文本内容,可用于显示许可协议或其他说明文档,使用如下:

val RichViewer : TRichEditViewer;
RichText : AnsiString;

LoadStringFromFile(ExpandConstant('{tmp}\xxx.rtf'), RichText);  // 读取文件内容至 RichText

RichViewer := TRichEditViewer.Create(WizardForm); // 卸载时将 WizardForm 换为 UninstallProgressForm 即可
with RichViewer do
begin
Parent := WizardForm; // 卸载时将 WizardForm 换为 UninstallProgressForm 即可
    ReadOnly := true; // 只读
    SCROLLBARS := ssVertical; // 滚动条类型
    BorderStyle := bsNone; // 边框类型
    RTFText := licenseText;     // 内容
    UseRichEdit := True; // 须设置此值为 True,才会按照富文本方式读取内容
end;

获取磁盘空间

界面上需要显示所需磁盘空间和剩余磁盘空间。

所需磁盘空间,WizardForm.DiskSpaceLabel 中有对所需磁盘的描述,可以将此描述通过 [Messages] 段设置 "DiskSpaceMBLabel=[mb]" 使之只剩下所需磁盘大小。然后通过 WizardForm.DiskSpaceLabel.Caption 可获得所需磁盘大小,字符串类型(如 "10.3" ),单位MB。

剩余磁盘空间,调用 Inno Setup 提供的 GetSpaceOnDisk 函数即可,将第一个参数设置为安装所在磁盘号,如 "C:" 。

例子:

[Messages]
DiskSpaceMBLabel=[mb] [Code]
function GetSpaceNeeded(); // 返回所需磁盘空间,字符串类型 "10.3",单位MB
begin
Result := WizardForm.DiskSpaceLabel.Caption;
end; function GetSpaceLeft(); // 返回剩余空间大小,整数类型,单位MB
var freeDiskSpace, totalDiskSpace : Cardinal;
begin
GetSpaceOnDisk(Copy(WizardForm.DirEdit.text, 1, 2), true, freeDiskSpace, totalDiskSpace)
Result := freeDiskSpace
end;

进度条

引入了外部依赖 user32.dll 的 SetTimer 来设置定时器,InnoCallback.dll 的 wrapcallback 来封装函数。其中 user32.dll 为操作系统自带,InnoCallback.dll 需要自行下载。

在安装或卸载进度变化的时候,WizardForm.ProgressGauge 和 UninstallProgressForm.ProgressBar 中的值会相应变化,定时读取其中的值即可实现实时进度变化。

例子:

type
TTimerProc = procedure(h:longword; msg:longword; idevent:longword; dwTime:longword); function SetTimer(hWnd, nIDEvent, uElapse, lpTimerFunc: LongWord): LongWord; external 'SetTimer@user32.dll stdcall delayload';
function TimerCallBack(P: TTimerProc; ParamCount: integer):LongWord; external 'wrapcallback@{%TEMP}\InnoCallback.dll stdcall delayload'; procedure RefreshProgressBar(h, AMsg, IdEvent, dwTime: LongWord);  // 刷新进度条
  var
    i1, i2 : integer;
  begin
    i1 := WizardForm.ProgressGauge.Position - WizardForm.ProgressGauge.Min; // 卸载时 WizardForm.ProgressGauge 应替换为 UninstallProgressForm.ProgressBar
    i2 := WizardForm.ProgressGauge.Max - WizardForm.ProgressGauge.Min; // 卸载时 WizardForm.ProgressGauge 应替换为 UninstallProgressForm.ProgressBar
    ProgressImg.Width := Round(i1 * TotalWidthOfProgressImg / i2);
  end; procedure CurPageChanged(CurPageID: Integer);
  begin
    if CurPageID = wpInstalling then // 安装时在 wpInstalling 页面调用定时器
      begin
    SetTimer(0, 0, 10, TimerCallBack(@TimerProc, 4));
end;
end; procedure InitializeUninstallProgressForm(); // 卸载时在 InitializeUninstallProgressForm 中调用定时器
  begin
    SetTimer(0, 0, 10, TimerCallBack(@TimerProc, 4));
end;

其他

1、安装界面中要用到的图片和资源,在 [Files] 段中应放到前面,因为安装程序读取资源时会先解压排在该资源前的所有文件。如果安装包界面资源在应用文件后面,安装界面打开会很慢很慢很慢很慢。

2、去掉关闭安装程序的二次确认框:

procedure CancelButtonClick(CurPageID: Integer; var Cancel, Confirm: Boolean);
begin
Confirm := False;
end;

3、手动触发下一步

WizardForm.NextButton.OnClick(WizardForm)

Inno Setup 自定义界面心得的更多相关文章

  1. 制作部署安装包:Inno Setup

    制作部署安装包:Inno Setup 前一篇尝试Office 2003 VSTO的开发.部署有提到用VS开发一个简单的VSTO程序.打包C/S程序,我首先想到的是VS里自带的Setup Project ...

  2. Inno Setup入门(一)——最简单的安装脚本

    地址:http://379910987.blog.163.com/blog/static/3352379720110238252326/ 一个最简单的安装脚本: 1.最简单的安装文件脚本: [setu ...

  3. C/S打包 客户端/windows程序 Inno Setup

    之前介绍过InstallShield打包工具,本文再介绍更加方便的打包工具Inno Setup Inno Setup相对来说,比InstallShield更容易使用,不需要去等VS去创建项目,只要提供 ...

  4. [Tool]Inno Setup创建软件安装程序。

    这篇博客将介绍如何使用Inno Setup创建一个软件安装程序. Inno Setup官网:http://www.jrsoftware.org/isinfo.php. 可以下载到最新的Inno Set ...

  5. inno setup读取注册表遇到的一个坑

    一.背景 目前,公司针对PR开发的一个插件需要发布到64位系统上.该插件包括一个prm格式的文件和若干个DLL文件.其中,prm文件需要复制到PR公共插件目录下,DLL需要复制到Windows系统目录 ...

  6. 一个简单的inno setup模板

    一.模板代码 基本功能包括多路径安装.多语言.自定义图标. [Setup] ShowLanguageDialog=yes AppCopyright=Copyright Reserved(C) , 36 ...

  7. Inno Setup 版本 5.5.3+ 简体中文语言包

    ; *** Inno Setup 版本 + 简体中文消息 *** [LangOptions] LanguageName=<7B80><4F53><> Languag ...

  8. 解决Inno Setup制作中文安装包在非中文系统上显示乱码的问题

    尼玛,好几个月没更新了.囧... 目前我司新的客户端开发已经接近尾声,该改的bug已经改完,该重构的地方也都差不多了.视觉效果也已经根据美工的样式改完了.所以,就差制作安装包了.正所谓万事俱备,只欠东 ...

  9. Inno Setup怎样创建一个自动申请管理员身份运行的快捷

    如果你使用的是 Unicode 版本的 Inno Setup,那么以下是更为专业的解决方法.    这是 mlaan 提及的再一种方法. QUOTE(     CodeAutomation3.iss) ...

随机推荐

  1. mongodb设置用户名和密码

    需求:我们需要在一个mongodb上面新建两个数据库,每个数据库的用户名和密码不一样,讲道理来说我们直接设置admin,就可以控制所有的数据库,不过用起来总是感觉有各种问题,目前还不太熟悉mongod ...

  2. 挑战App Store,微信通过“跳一跳”秀了一下“小程序”的肌肉

    2017年即将结束的时候,微信放了一个大招.随着最新的微信v6.6.1版本更新,基于小程序的"小游戏"板块正式上线.微信上首发的这款"小游戏"叫"跳一 ...

  3. ConcurrentDictionary内部函数的使用说明

    AddOrUpdate(...)函数的使用: private static ConcurrentDictionary<long, string> condic = new Concurre ...

  4. Swift学习第一天--面向过程

    //: Playground - noun: a place where people can play import UIKit //---------------------- Hello wor ...

  5. Node.js平台的一些使用总结

    Node.js的安装 菜鸟教程 npm -v查看npm的版本. npm更新 npm官网 npm权限问题 由于npm经常会因为权限问题,不能全局安装模块,所以解决办法如下: npm官网 npm切换淘宝源 ...

  6. 小白的Python之路 day4 软件目录结构规范

    软件目录结构规范 为什么要设计好目录结构? "设计项目目录结构",就和"代码编码风格"一样,属于个人风格问题.对于这种风格上的规范,一直都存在两种态度: 一类同 ...

  7. kafka 消费​

    前置资料  kafka kafka消费中的问题及解决方法: 情况1: 问题:脚本读取kafka 数据,写入到数据库,有时候出现MySQL server has gone away,导致脚本死掉.再次启 ...

  8. KD树

    k-d树 在计算机科学里,k-d树( k-维树的缩写)是在k维欧几里德空间组织点的数据结构.k-d树可以使用在多种应用场合,如多维键值搜索(例:范围搜寻及最邻近搜索).k-d树是空间二分树(Binar ...

  9. thinkinginjava学习笔记01_导论

    初学java,希望旅途愉快  :) 类型决定对象的接口,(有人认为类是类型的特定实现),接口确定对象所能发出的请求(消息),满足请求的代码和隐藏的数据一起构成实现: 对象设计时,应该很好地完成一项任务 ...

  10. 如何用css写打印样式

    打印样式 打印样式就是针对网页被打印时设置给文档的样式,由于打印时是显示在纸上,跟屏幕还是有区别的,对于有打印需求的网页往往需要设置专门的打印样式来适配页面. @media print 声明自己是打印 ...