原文:INNO SETUP卸载程序中加入自定义窗体

[Setup]
AppName=My Program
AppVerName=My Program v.1.2
DefaultDirName={pf}/My Program

[Files]
Source: Files/*; DestDir: {app}

[Code]
const
bidDelAll = 1;
bidSkipAll = 2;
var
Form: TSetupForm;
CheckListBox: TNewCheckListBox;
AllButton, UnAllButton: TButton;
CancelButton, DelButton: TButton;
StaticText: TNewStaticText;

MsgForm: TSetupForm;
MsgAllButton, MsgSkipAllButton: TButton;
MsgCancelButton, MsgDelButton: TButton;

DelAllReadOnly: Boolean;
SkipAllReadOnly: Boolean;

CheckDirs, CheckFiles: Boolean;

function Size64(Hi, Lo: integer): Extended;
var
i: integer;
begin
Result:= Lo;
if Lo < 0 then
Result:= Result + 2147483647 + 2147483647 + 2;
i:= Hi;
while i > 0 do
begin
Result:= Result + 2147483647 + 2147483647 + 2;
i:= i - 1;
end;
end;

procedure FillListBox(const fromDir, fileMask: string; Level: Byte);
var
FSR, DSR: TFindRec;
FindResult: Boolean;
APath: string;
i: integer;
begin
APath := AddBackslash(fromDir);
FindResult := FindFirst(APath + fileMask, FSR);
try
while FindResult and CheckFiles do
begin
if FSR.Attributes and FILE_ATTRIBUTE_DIRECTORY = 0 then
begin
{files} i:= CheckListBox.AddCheckBox(FSR.Name,
FloatToStr(Size64(FSR.SizeHigh, FSR.SizeLow)) + ' byte',
Level, True, True, False, True, TStringList.Create);
TStrings(CheckListBox.ItemObject[i]).Text:= APath + FSR.Name;
end;
FindResult := FindNext(FSR);
end;
FindResult := FindFirst(APath + '*.*', DSR);
while FindResult and CheckDirs do
begin
CheckFiles:= True;
if ((DSR.Attributes and FILE_ATTRIBUTE_DIRECTORY) = FILE_ATTRIBUTE_DIRECTORY) and
not ((DSR.Name = '.') or (DSR.Name = '..')) then
begin
{dir} i:= CheckListBox.AddCheckBox(DSR.Name,'DIR', Level,
True, True, False, True, TStringList.Create);
TStrings(CheckListBox.ItemObject[i]).Text:= APath + DSR.Name;
{Recursion} FillListBox(APath + DSR.Name, fileMask, Level+1);
end;
FindResult := FindNext(DSR);
end;
finally
FindClose(FSR);
FindClose(DSR);
end;
end;

procedure ButtonOnClick(Sender: TObject);
begin
if TButton(Sender).Tag = 0 then
CheckListBox.CheckItem(0, coCheckWithChildren)
else
CheckListBox.CheckItem(0, coUnCheck);
end;

procedure MsgButtonOnClick(Sender: TObject);
begin
Case TButton(Sender).Tag of
bidDelAll : DelAllReadOnly:= True;
bidSkipAll: SkipAllReadOnly:= True;
end;
MsgForm.Close;
end;

function DelMsgBox(FileName: string): Boolean;
var
MsgLabel: TLabel;
begin
MsgForm:= CreateCustomForm;
MsgForm.ClientWidth := ScaleX(400);
MsgForm.ClientHeight := ScaleY(120);
MsgForm.Caption := 'Files to delete';
MsgForm.Center;

MsgLabel := TLabel.Create(MsgForm);
MsgLabel.Left := ScaleX(20);
MsgLabel.Top := ScaleY(20);
MsgLabel.Caption:= FileName + ' is protected file or directory!' + #10#10#13 + 'Do you want to delete the file with READONLY attribute?';
MsgLabel.Parent := MsgForm;

MsgAllButton := TButton.Create(MsgForm);
MsgAllButton.Parent := MsgForm;
MsgAllButton.Width := ScaleX(75);
MsgAllButton.Height := ScaleY(23);
MsgAllButton.Left := ScaleX(20);
MsgAllButton.Top := MsgForm.ClientHeight - ScaleY(23 + 10);
MsgAllButton.Caption := 'Delete All';
MsgAllButton.Tag:= bidDelAll;
MsgAllButton.OnClick := @MsgButtonOnClick;

MsgSkipAllButton := TButton.Create(MsgForm);
MsgSkipAllButton.Parent := MsgForm;
MsgSkipAllButton.Width := ScaleX(75);
MsgSkipAllButton.Height := ScaleY(23);
MsgSkipAllButton.Left := MsgAllButton.Left + MsgAllButton.Width + ScaleX(10);
MsgSkipAllButton.Top := MsgForm.ClientHeight - ScaleY(23 + 10);
MsgSkipAllButton.Caption := 'Skip All';
MsgSkipAllButton.Tag:= bidSkipAll;
MsgSkipAllButton.OnClick := @MsgButtonOnClick;

MsgCancelButton := TButton.Create(MsgForm);
MsgCancelButton.Parent := MsgForm;
MsgCancelButton.Width := ScaleX(75);
MsgCancelButton.Height := ScaleY(23);
MsgCancelButton.Left := MsgForm.ClientWidth - MsgCancelButton.Width - ScaleX(20);
MsgCancelButton.Top := MsgForm.ClientHeight - ScaleY(23 + 10);
MsgCancelButton.Caption := 'Skip';
MsgCancelButton.ModalResult := mrCancel;

MsgDelButton := TButton.Create(MsgForm);
MsgDelButton.Parent := MsgForm;
MsgDelButton.Width := ScaleX(75);
MsgDelButton.Height := ScaleY(23);
MsgDelButton.Left := MsgCancelButton.Left - MsgDelButton.Width - ScaleX(10);
MsgDelButton.Top := MsgForm.ClientHeight - ScaleY(23 + 10);
MsgDelButton.Caption := 'Delete';
MsgDelButton.ModalResult := mrOk;

MsgForm.ActiveControl:= MsgCancelButton;

if MsgForm.ShowModal() = mrOk then
Result:= True
else
Result:= False;
end;

procedure DeleteFiles();
var
SR: TFindRec;
i: integer;
str: string;
ResultCode: Integer;
begin
DelAllReadOnly:= False;
SkipAllReadOnly:= False;
for i:= CheckListBox.Items.Count - 1 downto 0 do
begin
if CheckListBox.State[i] = cbChecked then
begin
str:= Trim(TStrings(CheckListBox.ItemObject[i]).Text);
FindFirst(str, SR);
if ((SR.Attributes and FILE_ATTRIBUTE_READONLY) = FILE_ATTRIBUTE_READONLY) then
if Not (DelAllReadOnly or SkipAllReadOnly) then
if DelMsgBox(SR.Name) then
Exec('attrib', ' -h -s -r ' + '"' + str + '"',
'', SW_HIDE, ewWaitUntilTerminated, ResultCode);
if DelAllReadOnly then
Exec('attrib', ' -h -s -r ' + '"' + str + '"',
'', SW_HIDE, ewWaitUntilTerminated, ResultCode);

FindClose(SR);
DeleteFile(str);
RemoveDir(str);
end;
end;
end;

procedure BrowseRemainedFiles();
begin
Form:= CreateCustomForm;
Form.ClientWidth := ScaleX(400);
Form.ClientHeight := ScaleY(400);
Form.Caption := 'Files to delete';
Form.Center;

StaticText := TNewStaticText.Create(Form);
StaticText.Left:= ScaleX(20);
StaticText.Top := ScaleY(8);
StaticText.Caption := 'Some elements could not be removed.' + #10#13 +
'These can be removed manually.' + #10#13#13 +
'Choose which are necessary to delete' + #10#13 +
'or press Cancel button.';
StaticText.Font.Color:= clBlue;
StaticText.Font.Style:= [fsBold];
StaticText.AutoSize := True;
StaticText.Parent := Form;

CheckListBox := TNewCheckListBox.Create(Form);
CheckListBox.Left:= ScaleX(20);
CheckListBox.Top:= ScaleY(20);
CheckListBox.Width:= Form.ClientWidth - ScaleX(20*2);
CheckListBox.Height:= Form.ClientHeight - ScaleY(23*2 + 20);
// CheckListBox.Offset:= 0;
CheckListBox.Parent:= Form;

AllButton := TButton.Create(Form);
AllButton.Parent := Form;
AllButton.Width := ScaleX(75);
AllButton.Height := ScaleY(23);
AllButton.Left := ScaleX(20);
AllButton.Top := Form.ClientHeight - ScaleY(23 + 10);
AllButton.Caption := 'Select All';
AllButton.Tag:= 0;
AllButton.OnClick := @ButtonOnClick;

UnAllButton := TButton.Create(Form);
UnAllButton.Parent := Form;
UnAllButton.Width := ScaleX(75);
UnAllButton.Height := ScaleY(23);
UnAllButton.Left := AllButton.Left + AllButton.Width + ScaleX(10);
UnAllButton.Top := Form.ClientHeight - ScaleY(23 + 10);
UnAllButton.Caption := 'Clear All';
UnAllButton.Tag:= 1;
UnAllButton.OnClick := @ButtonOnClick;

CancelButton := TButton.Create(Form);
CancelButton.Parent := Form;
CancelButton.Width := ScaleX(75);
CancelButton.Height := ScaleY(23);
CancelButton.Left := Form.ClientWidth - CancelButton.Width - ScaleX(20);
CancelButton.Top := Form.ClientHeight - ScaleY(23 + 10);
CancelButton.Caption := 'Cancel';
CancelButton.ModalResult := mrCancel;
CancelButton.Cancel := True;

DelButton := TButton.Create(Form);
DelButton.Parent := Form;
DelButton.Width := ScaleX(75);
DelButton.Height := ScaleY(23);
DelButton.Left := CancelButton.Left - DelButton.Width - ScaleX(10);
DelButton.Top := Form.ClientHeight - ScaleY(23 + 10);
DelButton.Caption := 'Delete';
DelButton.ModalResult := mrOk;

Form.ActiveControl:= CancelButton;

CheckListBox.AddCheckBox(ExpandConstant('{app}'), '', 0, True, True, False, True, TStringList.Create);
TStrings(CheckListBox.ItemObject[0]).Text:= ExpandConstant('{app}');
CheckDirs:= True;
FillListBox(ExpandConstant('{app}'), '*', 1);
CheckDirs:= False;
FillListBox(ExpandConstant('{app}'), '*', 1);

if Form.ShowModal() = mrOk then DeleteFiles();
end;

procedure CurUninstallStepChanged(CurUninstallStep: TUninstallStep);
begin
if DirExists(ExpandConstant('{app}')) and (CurUninstallStep = usPostUninstall) then
BrowseRemainedFiles();
end;

INNO SETUP卸载程序中加入自定义窗体的更多相关文章

  1. Inno setup 卸载时删除程序文件夹(文件)

    Inno setup 卸载时删除程序文件夹(文件) //删除所有配置文件以达到干净卸载的目的 procedure CurUninstallStepChanged(CurUninstallStep: T ...

  2. Inno Setup技巧[界面]添加和自定义左下角标签

    原文 http://blog.sina.com.cn/s/blog_5e3cc2f30100cc49.html 本文介绍添加和自定义“左下角标签”的方法. 界面预览: Setup技巧[界面]添加和自定 ...

  3. C程序中引用自定义的C函数模块

    原文:C程序中引用自定义的C函数模块 我们知道,刚开始接触C语言编程,一般都是在一个.c或者.cpp(以下只说.c)的文件中编写代码,其中一定会有一个入口函数, 也就是main()函数,你可以将程序代 ...

  4. 微信小程序中的自定义组件

    微信小程序中的组件 前言 之前做小程序开发的时候,对于开发来说比较头疼的莫过于自定义组件了,当时官方对这方面的文档也只是寥寥几句,一笔带过而已,所以写起来真的是非常非常痛苦!! 好在微信小程序的库从 ...

  5. 使用inno setup打包程序完整脚本(.net框架检测,重复安装检测)

    ; 脚本由 Inno Setup 脚本向导 生成!; 有关创建 Inno Setup 脚本文件的详细资料请查阅帮助文档! #define MyAppName "小小鸟软件"#def ...

  6. Inno Setup安装程序单例运行

    1.源起: KV项目下载底层升级包,老是报出升级文件占用问题,反复分析,不得其所. 今天突然发现同时启动多个升级程序实例,分析认为安装包同时被调用多次,引发实例访问文件冲突,导致此问题. 安装程序由I ...

  7. Inno Setup卸载时注销bho

    Inno setup是一个制作安装包的免费工具,比如你用Qt开发完成一款软件,拿Inno setup打个安装包甩给客户安装就好了. 但是bho插件在注册后,万一用户卸载软件时,bho插件还是躺在管理加 ...

  8. 微信小程序中的自定义组件(components)

     其实小程序开发很像vue和react的结合,数据绑定和setData  重新渲染页面的数据,最近发现连写组件都是很像,也是醉了,自我认为哈, 因为小程序可以将页面内的功能模块抽象成自定义组件,以便在 ...

  9. 在C#一个程序中,将一个窗体中的数据传送到另一个窗体

    使用多个窗体搭建的程序,需要用到窗体间的数据传递,常用两种方法: 方法一 1,进入子窗体的Designer.cs,将子窗体中的私有控件控件定义为public 2.在主窗口程序Form1.cs中将子窗口 ...

随机推荐

  1. 编程算法基地-2.1利用字符串API

    2.1利用字符串API 字符串是Java类型最常用.并且是复合类型 串非常经常用于,其最佳API熟悉文档. 推断串中有没有反复的字符 String s ="abcdebxyz"; ...

  2. avalonjs1.5 入门教程

    迷你MVVM框架 avalonjs1.5 入门教程 avalon经过几年以后,已成为国内一个举足轻重的框架.它提供了多种不同的版本,满足不同人群的需要.比如avalon.js支持IE6等老旧浏览器,让 ...

  3. c# webbrowser  获取用户选中文字

    原文:c# webbrowser  获取用户选中文字 最近一直被一个问题困扰,有一个文本框,一个webbrowser控件,一个上下文菜单, webbrowser  获取用户选中文字" tit ...

  4. myeclipse解决JSP文件script调整背景颜色

    1进口MyEclipse主题后,打开jsp要么html文件,jsvascript部分原因遭遇了一层白色的.闪避这个时候.症状,如下面: watermark/2/text/aHR0cDovL2Jsb2c ...

  5. 大数据下的数据分析平台架构zz

    转自http://www.cnblogs.com/end/archive/2012/02/05/2339152.html 随着互联网.移动互联网和物联网的发展,谁也无法否认,我们已经切实地迎来了一个海 ...

  6. easyUI的combobox实现级联

    先简介下combobox: easyUI重写了select,取而代之的是combobox,有例如以下几种方式能够创建一个combobox 1.使用select标签,并加上class="eas ...

  7. 十天学Linux内核之第五天---有关Linux文件系统实现的问题

    原文:十天学Linux内核之第五天---有关Linux文件系统实现的问题 有时间睡懒觉了,却还是五点多醒了,不过一直躺倒九点多才算起来,昨晚一直在弄飞凌的嵌入式开发板,有些问题没解决,自己电脑系统的问 ...

  8. codeforces 438D

    在大大推荐下这个标题不明的人做.而我的最后一个非常喜欢的段树,因此,愤怒出手.认为基本上相同.大值,当最大值小于取模时能够剪枝. 今后再遇到此类问题算是能攻克了 // file name: d.cpp ...

  9. c#有关udp可靠传输(包传输数据包) 升级

    在c#有关udp可靠传输(包传输数据包)我们讨论,UDP包的发送,可是上一个程序有一个问题.就是数据比較大.一个Message类序列化后都有2048B,而实际的数据量也就只是 50B罢了,这就说明当中 ...

  10. 如何学习ACM

    我想对未来的同学有几句话要说: 1 我们几乎没有noi上来的队员,大家只能依靠后期的更加刻苦的努力. 2 我们没有专业的班级或者机制形成职业ACM队伍,所以大家只能尽早的投入进来,用尽一切课余时间去训 ...