How to close finished Inno Setup installer after a certain time? - inno-setup

How to close the installer on the "Finished" page after a certain time?
It could also be interpreted as: how to close the installer after some time of non-activity? (close/cancel install). Is this possible?

Setup a timer once the "Finished" page displays to trigger the close.
[Code]
function SetTimer(hWnd, nIDEvent, uElapse, lpTimerFunc: LongWord): LongWord;
external 'SetTimer#User32.dll stdcall';
function KillTimer(hWnd, nIDEvent: LongWord): LongWord;
external 'KillTimer#User32.dll stdcall';
var
PageTimeoutTimer: LongWord;
PageTimeout: Integer;
procedure UpdateFinishButton;
begin
WizardForm.NextButton.Caption :=
Format(SetupMessage(msgButtonFinish) + ' - %ds', [PageTimeout]);
end;
procedure PageTimeoutProc(
H: LongWord; Msg: LongWord; IdEvent: LongWord; Time: LongWord);
begin
if PageTimeout > 1 then
begin
Dec(PageTimeout);
UpdateFinishButton;
end
else
begin
WizardForm.NextButton.OnClick(WizardForm.NextButton);
end;
end;
procedure CurPageChanged(CurPageID: Integer);
begin
if CurPageID = wpFinished then
begin
PageTimeout := 10;
UpdateFinishButton;
PageTimeoutTimer := SetTimer(0, 0, 1000, CreateCallback(#PageTimeoutProc));
end;
end;
function NextButtonClick(CurPageID: Integer): Boolean;
begin
if CurPageID = wpFinished then
begin
KillTimer(0, PageTimeoutTimer);
PageTimeoutTimer := 0;
end;
Result := True;
end;
For CreateCallback function, you need Inno Setup 6. If you are stuck with Inno Setup 5, you can use WrapCallback function from InnoTools InnoCallback library.
Related questions:
MsgBox - Make unclickable OK Button and change to countdown - Inno Setup;
Inno Setup - Automatically submitting uninstall prompts.

Related

Inno setup - adding an animated gif [duplicate]

I have prepared simple script that displays image under ProgressGauge bar on wpInstalling Page.
But... I need more complex functionality.
What I need is multiple images show, each after X (e.g. 7) seconds (with loop when installation longer then X secs * number of images) or each after X (e.g. 10) percent of installation. I have tried to embed images display in ProgressGauge.Position, but I failed.
Here is what I have:
procedure CurPageChanged(CurPageID: Integer);
var
BmpFile: TBitmapImage;
begin
ExtractTemporaryFile('01.bmp');
ExtractTemporaryFile('02.bmp');
ExtractTemporaryFile('03.bmp');
if CurPageID = wpInstalling then
begin
BmpFile:= TBitmapImage.Create(WizardForm);
BmpFile.Bitmap.LoadFromFile(ExpandConstant('{tmp}\01.bmp'));
BmpFile.Width:= ScaleX(420);
BmpFile.Height:= ScaleY(180);
BmpFile.Left := WizardForm.ProgressGauge.Left + ScaleX(0);
BmpFile.Top := WizardForm.ProgressGauge.Top + ScaleY(35);
// BmpFile.Parent:= WizardForm.InstallingPage;
// BmpFile:= TBitmapImage.Create(WizardForm);
// BmpFile.Bitmap.LoadFromFile(ExpandConstant('{tmp}\03.bmp'));
// BmpFile.Width:= ScaleX(420);
// BmpFile.Height:= ScaleY(400);
// BmpFile.Left := WizardForm.ProgressGauge.Left + ScaleX(0);
// BmpFile.Top := WizardForm.ProgressGauge.Top + ScaleY(35);
// BmpFile.Parent:= WizardForm.InstallingPage;
// BmpFile:= TBitmapImage.Create(WizardForm);
// BmpFile.Bitmap.LoadFromFile(ExpandConstant('{tmp}\03.bmp'));
// BmpFile.Width:= ScaleX(420);
// BmpFile.Height:= ScaleY(400);
// BmpFile.Left := WizardForm.ProgressGauge.Left + ScaleX(0);
// BmpFile.Top := WizardForm.ProgressGauge.Top + ScaleY(35);
// BmpFile.Parent:= WizardForm.InstallingPage;
end;
end;
The goal is:
On the wpInstalling there should be X images displayed, every next per X seconds or after X percent of installation.
Since the ProgressGauge has no progress change events and there is no way to process setup application messages you will need to use the Windows API timer. This timer needs a callback function which you can't define in Inno Setup script unfortunately so you will need some external library to do this job for you. However there's the InnoCallback library which can do exactly this.
For the following code copy the InnoCallback.dll library into your setup directory, merge this code with your Inno Setup script and implement some kind of a slideshow page turning in the OnSlideTimer event which will be called periodically (with the current settings each second).
[Files]
Source: "InnoCallback.dll"; DestDir: "{tmp}"; Flags: dontcopy
[code]
var
TimerID: Integer;
type
TTimerProc = procedure(Wnd: HWND; Msg: UINT; TimerID: UINT_PTR;
SysTime: DWORD);
function WrapTimerProc(Callback: TTimerProc; ParamCount: Integer): LongWord;
external 'wrapcallback#files:InnoCallback.dll stdcall';
function SetTimer(hWnd: HWND; nIDEvent, uElapse: UINT;
lpTimerFunc: UINT): UINT; external 'SetTimer#user32.dll stdcall';
function KillTimer(hWnd: HWND; uIDEvent: UINT): BOOL;
external 'KillTimer#user32.dll stdcall';
procedure OnSlideTimer(Wnd: HWND; Msg: UINT; TimerID: UINT_PTR;
SysTime: DWORD);
begin
{ here you can turn your slideshow pages; use some variable to store the }
{ current index of the slide you are on, note that this procedure is called }
{ periodically each 1000 ms (see below why), so here you can also check the }
{ progress value, if you want to }
end;
procedure StartSlideTimer;
var
TimerCallback: LongWord;
begin
TimerCallback := WrapTimerProc(#OnSlideTimer, 4);
{ third parameter here is the timer's timeout value in milliseconds }
TimerID := SetTimer(0, 0, 1000, TimerCallback);
end;
procedure KillSlideTimer;
begin
if TimerID <> 0 then
begin
if KillTimer(0, TimerID) then
TimerID := 0;
end;
end;
function InitializeSetup: Boolean;
begin
Result := True;
TimerID := 0;
end;
procedure DeinitializeSetup;
begin
KillSlideTimer;
end;
procedure CurPageChanged(CurPageID: Integer);
begin
if CurPageID = wpInstalling then
StartSlideTimer
else
KillSlideTimer;
end;

Inno Setup - Animate a control roll out from right in a determinate page

I am trying to use this code (with InnoCallback DLL library):
[Code]
var
MainPanelAnimated: Boolean;
AnimationTimer: LongWord;
procedure AnimationTimerProc(
H: LongWord; Msg: LongWord; IdEvent: LongWord; Time: LongWord);
var
L: Integer;
begin
L := WizardForm.MainPanel.Left + ScaleX(5);
if L > 0 then
begin
L := 0;
KillTimer(0, AnimationTimer);
end;
WizardForm.MainPanel.Left := L;
end;
procedure CurPageChanged(CurPageID: Integer);
var
HoverTimerCallback: LongWord;
begin
if WizardForm.OuterNotebook.ActivePage = WizardForm.InnerPage then
begin
if not MainPanelAnimated then
begin
HoverTimerCallback := WrapTimerProc(#AnimationTimerProc, 4);
AnimationTimer := SetTimer(0, 0, 5, HoverTimerCallback);
WizardForm.MainPanel.Left := -WizardForm.MainPanel.Width;
MainPanelAnimated := True;
end;
end;
end;
from How to animate a control roll out in Inno Setup (answer of Martin Prikryl), to show the same effect but from right to left and in a determinate page of setup. How to do this?
Use CurPageID in CurPageChanged to select on what page to show the animation.
[Code]
function SetTimer(hWnd: longword; nIDEvent, uElapse: LongWord; lpTimerFunc: LongWord):
LongWord; external 'SetTimer#user32.dll stdcall';
function KillTimer(hWnd, nIDEvent: LongWord): LongWord;
external 'KillTimer#User32.dll stdcall';
var
AnimationTimer: LongWord;
procedure AnimationTimerProc(
H: LongWord; Msg: LongWord; IdEvent: LongWord; Time: LongWord);
var
L: Integer;
begin
L := WizardForm.MainPanel.Left - ScaleX(5);
if L < 0 then
begin
L := 0;
KillTimer(0, AnimationTimer);
end;
WizardForm.MainPanel.Left := L;
end;
procedure CurPageChanged(CurPageID: Integer);
begin
if CurPageID = wpReady then
begin
AnimationTimer := SetTimer(0, 0, 5, CreateCallback(#AnimationTimerProc));
WizardForm.MainPanel.Left := WizardForm.MainPanel.Width;
end;
end;
For CreateCallback function, you need Inno Setup 6. If you are stuck with Inno Setup 5, you can use WrapCallback function from InnoTools InnoCallback library.

How to animate a control roll out in Inno Setup

I want to animate a control roll out in my installer.
You can see this video.
You can use a timer to animate a control.
[Code]
function SetTimer(hWnd: longword; nIDEvent, uElapse: LongWord; lpTimerFunc: LongWord):
LongWord; external 'SetTimer#user32.dll stdcall';
function KillTimer(hWnd, nIDEvent: LongWord): LongWord;
external 'KillTimer#User32.dll stdcall';
var
MainPanelAnimated: Boolean;
AnimationTimer: LongWord;
procedure AnimationTimerProc(
H: LongWord; Msg: LongWord; IdEvent: LongWord; Time: LongWord);
var
L: Integer;
begin
L := WizardForm.MainPanel.Left + ScaleX(5);
if L > 0 then
begin
L := 0;
KillTimer(0, AnimationTimer);
end;
WizardForm.MainPanel.Left := L;
end;
procedure CurPageChanged(CurPageID: Integer);
begin
if WizardForm.OuterNotebook.ActivePage = WizardForm.InnerPage then
begin
if not MainPanelAnimated then
begin
AnimationTimer := SetTimer(0, 0, 5, CreateCallback(#AnimationTimerProc));
WizardForm.MainPanel.Left := -WizardForm.MainPanel.Width;
MainPanelAnimated := True;
end;
end;
end;
For CreateCallback function, you need Inno Setup 6. If you are stuck with Inno Setup 5, you can use WrapCallback function from InnoTools InnoCallback library.
(the animation is actually more smooth than the image shows)
For right-to-left animation, see Inno Setup - Animate a control roll out from right in a determinate page.

MsgBox - Make unclickable OK Button and change to countdown - Inno Setup

How to change OK button into a countdown timer like this...
5,4,3,2,1,0 [MsgBox Closes automatically] don't display 0
Proceeds to setup procedure.
The button should not be clickable and faded. Like inactive window/button/box.
this one:
not this one:
I use the code code from this question: How to show a message box for a specified time?
There's no built-in function with such functionality. Neither in Inno Setup, nor WinAPI.
You have to implement the dialog on your own and use a timer to implement the count down.
[Code]
function SetTimer(hWnd: LongWord; nIDEvent, uElapse: LongWord;
lpTimerFunc: LongWord): LongWord; external 'SetTimer#user32.dll stdcall';
function KillTimer(hWnd: HWND; uIDEvent: LongWord): BOOL;
external 'KillTimer#user32.dll stdcall';
var
CountdownButton: TNewButton;
Countdown: Integer;
procedure UpdateCountDownButtonCaption;
begin
CountdownButton.Caption := Format('%d sec', [Countdown]);
end;
procedure CountdownProc(
H: LongWord; Msg: LongWord; IdEvent: LongWord; Time: LongWord);
begin
Dec(Countdown);
if Countdown = 0 then
begin
CountdownButton.Enabled := True;
TForm(CountdownButton.Parent).Close;
end
else
begin
UpdateCountDownButtonCaption;
end;
end;
procedure CountdownMessageBoxCloseQuery(Sender: TObject; var CanClose: Boolean);
begin
{ Prevent the dialog from being close by the X button and Alt-F4 }
CanClose := CountdownButton.Enabled;
end;
procedure CountdownMessageBox(Message: string; Seconds: Integer);
var
Form: TSetupForm;
MessageLabel: TLabel;
Timer: LongWord;
begin
Form := CreateCustomForm;
try
Form.ClientWidth := ScaleX(256);
Form.ClientHeight := ScaleY(96);
Form.Caption := 'Information';
Form.Position := poMainFormCenter;
Form.OnCloseQuery := #CountdownMessageBoxCloseQuery;
MessageLabel := TLabel.Create(Form);
MessageLabel.Top := ScaleY(16);
MessageLabel.Left := ScaleX(16);
MessageLabel.AutoSize := True;
MessageLabel.Caption := Message;
MessageLabel.Parent := Form;
if CountdownButton <> nil then
RaiseException('Countdown in progress already');
Countdown := Seconds;
CountdownButton := TNewButton.Create(Form);
CountdownButton.Parent := Form;
CountdownButton.Width := ScaleX(88);
CountdownButton.Height := ScaleY(26);
CountdownButton.Left :=
Form.ClientWidth - CountdownButton.Width - ScaleX(18);
CountdownButton.Top :=
Form.ClientHeight - CountdownButton.Height - ScaleX(11);
UpdateCountDownButtonCaption;
CountdownButton.Name := 'CountdownButton';
CountdownButton.ModalResult := mrOk;
CountdownButton.Default := True;
CountdownButton.Enabled := False;
Timer := SetTimer(0, 0, 1000, CreateCallback(#CountdownProc));
try
Form.ShowModal();
finally
KillTimer(0, Timer);
end;
finally
Form.Free();
CountdownButton := nil;
end;
end;
For CreateCallback function, you need Inno Setup 6. If you are stuck with Inno Setup 5, you can use WrapCallback function from InnoTools InnoCallback library.
Use it like:
CountdownMessageBox('Message here', 10);
Related questions:
How to show a message box for a specified time?
Inno Setup - How to close finished installer after a certain time?
Inno Setup - Automatically submitting uninstall prompts.

How to Delete / Hide / Disable [OK] button on message box

Here's the code...
ifdef UNICODE
#define AW "W"
#else
#define AW "A"
#endif
const
MB_TIMEDOUT = 32000;
MB_ICONERROR = $10;
MB_ICONQUESTION = $20;
MB_ICONWARNING = $30;
MB_ICONINFORMATION = $40;
function MessageBoxTimeout(hWnd: HWND; lpText: string; lpCaption: string;
uType: UINT; wLanguageId: Word; dwMilliseconds: DWORD): Integer;
external 'MessageBoxTimeout{#AW}#user32.dll stdcall';
procedure InitializeWizard;
begin
MessageBoxTimeout(WizardForm.Handle, 'Some ' +
'message', 'Setup', MB_OK or MB_ICONINFORMATION, 0, 5000);
end;
I just want the message box to appear without the button. What code to be added or removed? Where would I insert it? Thanks!
Does this a code from How to disable the “Next” button on the wizard form in Inno Setup? work with my script? I can't seem to to make it working.
You cannot.
But as you already know from MsgBox - Make unclickable OK Button and change to countdown - Inno Setup, you can implement the message box from a scratch yourself. This way, you can customize it any way you want.
Actually, all you need is to remove the button from my answer to the above question.
[Code]
function SetTimer(hWnd: LongWord; nIDEvent, uElapse: LongWord;
lpTimerFunc: LongWord): LongWord; external 'SetTimer#user32.dll stdcall';
function KillTimer(hWnd: HWND; uIDEvent: LongWord): BOOL;
external 'KillTimer#user32.dll stdcall';
var
TimeoutForm: TSetupForm;
procedure TimeoutProc(H: LongWord; Msg: LongWord; IdEvent: LongWord; Time: LongWord);
begin
TimeoutForm.Tag := TimeoutForm.Tag - 1;
if TimeoutForm.Tag = 0 then
begin
TimeoutForm.Close;
end;
end;
procedure TimeoutMessageBoxCloseQuery(Sender: TObject; var CanClose: Boolean);
begin
{ Prevent the dialog from being closed by the X button and Alt-F4 }
CanClose := (TimeoutForm.Tag = 0);
end;
procedure TimeoutMessageBox(Message: string; Seconds: Integer);
var
MessageLabel: TLabel;
Timer: LongWord;
begin
TimeoutForm := CreateCustomForm;
try
TimeoutForm.ClientWidth := ScaleX(256);
TimeoutForm.ClientHeight := ScaleY(64);
TimeoutForm.Caption := 'Information';
TimeoutForm.Position := poMainFormCenter;
TimeoutForm.OnCloseQuery := #TimeoutMessageBoxCloseQuery;
TimeoutForm.Tag := Seconds;
MessageLabel := TLabel.Create(TimeoutForm);
MessageLabel.Top := ScaleY(16);
MessageLabel.Left := ScaleX(16);
MessageLabel.AutoSize := True;
MessageLabel.Caption := Message;
MessageLabel.Parent := TimeoutForm;
Timer := SetTimer(0, 0, 1000, CreateCallback(#TimeoutProc));
try
TimeoutForm.ShowModal();
finally
KillTimer(0, Timer);
end;
finally
TimeoutForm.Free();
TimeoutForm := nil;
end;
end;
For CreateCallback function, you need Inno Setup 6. If you are stuck with Inno Setup 5, you can use WrapCallback function from InnoTools InnoCallback library.

Resources