Is there any way to copy a string to the clipboard with Inno Setup?
I need to implement a button to copy the contents of a field to clipboard.
Yes, you can send the WM_COPY message. For example:
[Setup]
AppName=My Program
AppVersion=1.5
DefaultDirName={pf}\My Program
[Code]
const
WM_COPY = $0301;
var
EditToCopy: TNewEdit;
procedure CopyToClipboard(Control: TWinControl);
begin
SendMessage(Control.Handle, WM_COPY, 0, 0);
end;
procedure ButtonCopyClick(Sender: TObject);
begin
EditToCopy.SelectAll;
CopyToClipboard(EditToCopy);
end;
procedure InitializeWizard;
var
ButtonCopy: TNewButton;
WizardPage: TWizardPage;
begin
WizardPage := CreateCustomPage(wpWelcome, 'Caption', 'Description');
EditToCopy := TNewEdit.Create(WizardForm);
EditToCopy.Parent := WizardPage.Surface;
EditToCopy.Text := 'Text to copy';
ButtonCopy := TNewButton.Create(WizardForm);
ButtonCopy.Parent := WizardPage.Surface;
ButtonCopy.Caption := 'Copy';
ButtonCopy.Top := EditToCopy.Top + EditToCopy.Height + 8;
ButtonCopy.OnClick := #ButtonCopyClick;
end;
Related
Inno Setup - I want to create an installer similar to the screenshot.
The installer should highlight the current step on the left side.
How to achieve the same?
#Bill_Stewart is correct, vanilla Inno Setup does not offer such complex functionality.
However it is possible to do that using Graphical Installer which is a 3rd party extension for Inno Setup (see www.graphical-installer.com for more info).
The implemented functionality (about 150 lines in Pascal):
; This identifier is used for compiling script as Graphical Installer powered installer. Comment it out for regular compiling.
#define GRAPHICAL_INSTALLER_PROJECT
#ifdef GRAPHICAL_INSTALLER_PROJECT
; File with setting for graphical interface
#include "script.graphics.iss"
#else
; Default UI file
#define public GraphicalInstallerUI ""
#endif
[Setup]
AppName=InnoSetupProject
AppVersion=1.5
LicenseFile=readme.txt
DefaultDirName={autoappdata}\InnoSetupProject
DefaultGroupName=My Program
UninstallDisplayIcon={app}\MyProg.exe
Compression=lzma2
SolidCompression=yes
OutputDir=Output
OutputBaseFilename=InnoSetupProject
PrivilegesRequired=lowest
; Directive "WizardSmallImageBackColor" was modified for purposes of Graphical Installer.
WizardSmallImageBackColor={#GraphicalInstallerUI}
DisableWelcomePage=no
[Code]
type
TInnoPageStep = record
PageID: Integer;
Caption: String;
Index: Integer;
IsActive: Boolean;
end;
var
AllPagesList: array of TInnoPageStep;
AllPagesCount: Integer;
AllPagesCheckListBox: TNewCheckListBox;
I: Integer;
procedure SetPagesCount(pages: Integer);
begin
AllPagesCount := 0;
SetLength(AllPagesList, pages);
end;
procedure AddPage(pageID: Integer; caption: String);
var
page: TInnoPageStep;
begin
page.Caption := caption;
page.PageID := pageID;
page.Index := AllPagesCount + 1;
AllPagesList[AllPagesCount] := page;
AllPagesCount := AllPagesCount + 1;
end;
procedure CreatePagesListBox();
begin
AllPagesCheckListBox := TNewCheckListBox.Create(WizardForm);
AllPagesCheckListBox.Top := ScaleX(160);
AllPagesCheckListBox.Left := ScaleY(20);
AllPagesCheckListBox.Width := 260;
AllPagesCheckListBox.Height := ScaleY(300);
AllPagesCheckListBox.BorderStyle := bsNone;
AllPagesCheckListBox.ParentColor := True;
AllPagesCheckListBox.MinItemHeight := 30;
AllPagesCheckListBox.ShowLines := False;
AllPagesCheckListBox.WantTabs := True;
AllPagesCheckListBox.Parent := WizardForm;
for I := 0 to AllPagesCount-1 do
begin
AllPagesList[I].Index := AllPagesCheckListBox.AddRadioButton(AllPagesList[I].Caption, '', 0, False, True, nil);
end;
end;
procedure UpdateActivePage(pageID: Integer);
begin
for I := 0 to AllPagesCount-1 do
begin
if (AllPagesList[I].PageID = pageID) then
AllPagesList[I].IsActive := True
else
AllPagesList[I].IsActive := False;
end;
for I := 0 to AllPagesCount-1 do
begin
AllPagesCheckListBox.Checked[AllPagesList[I].Index] := AllPagesList[I].IsActive;
if (AllPagesList[I].IsActive) then
begin
AllPagesCheckListBox.ItemFontStyle[AllPagesList[I].Index] := [fsBold];
AllPagesCheckListBox.ItemFontColor[AllPagesList[I].Index] := clBlack;
end
else
begin
AllPagesCheckListBox.ItemFontStyle[AllPagesList[I].Index] := [];
AllPagesCheckListBox.ItemFontColor[AllPagesList[I].Index] := clWhite;
end;
end;
AllPagesCheckListBox.Invalidate;
end;
procedure CurPageChanged(CurPageID: Integer);
begin
#ifdef GRAPHICAL_INSTALLER_PROJECT
PageChangedGraphicalInstaller(CurPageID);
#endif
UpdateActivePage(CurPageID);
end;
// Next functions are used for proper working of Graphical Installer powered installer
procedure InitializeWizard();
var
pageIDs: array of Integer;
pageCaptions: array of String;
begin
#ifdef GRAPHICAL_INSTALLER_PROJECT
InitGraphicalInstaller();
#endif
// This is a list of all standard pages in Inno Setup.
pageIDs := [wpWelcome, wpLicense, wpPassword, wpInfoBefore, wpUserInfo, wpSelectDir, wpSelectComponents, wpSelectProgramGroup, wpSelectTasks, wpReady, wpPreparing, wpInstalling, wpInfoAfter, wpFinished];
pageCaptions := ['wpWelcome', 'wpLicense', 'wpPassword', 'wpInfoBefore', 'wpUserInfo', 'wpSelectDir', 'wpSelectComponents', 'wpSelectProgramGroup', 'wpSelectTasks', 'wpReady', 'wpPreparing', 'wpInstalling', 'wpInfoAfter', 'wpFinished'];
// The setup will have 5 pages
SetPagesCount(5);
// If you are using custom pages you need to add them too
AddPage(pageIDs[0], pageCaptions[0]);
AddPage(pageIDs[1], pageCaptions[1]);
AddPage(pageIDs[5], pageCaptions[5]);
AddPage(pageIDs[11], pageCaptions[11]);
AddPage(pageIDs[13], pageCaptions[13]);
// Init the UI
CreatePagesListBox();
end;
procedure DeInitializeSetup();
begin
#ifdef GRAPHICAL_INSTALLER_PROJECT
DeInitGraphicalInstaller();
#endif
end;
// End of file (EOF)
Please notice: To compile this script you need to install the Graphical Installer. Feel free to ask any other questions (I am developer of GI).
Purpose:
With Inno Setup I want to create an installer with a dropdown list in the install wizard.
The choice made in the wizards defines 2 variables:
One for the folder location and the other for the location in the registry.
Problem:
Variables are defined as global in [Code], but are not used in [Files] and [Registry]
Code:
The two variables are: strData1 & strData2
I was trying to retrieve them with functions: strData1returner & strData2returner
[Setup]
...
[Dirs]
Name: "C:\Program Files\CompanyName\{code:strData1returner}"
[Files]
Source: "C:\SomeDll.dll"; \
DestDir: "C:\Program Files\CompanyName\{code:strData1returner}\"; Flags: ignoreversion;
[Registry]
Root: HKCU; subkey: "{code:strData2returner}"; flags: createvalueifdoesntexist
[Code]
var
Button: TNewButton;
ComboBox: TNewComboBox;
CustomPage: TWizardPage;
strData1: string;
strData2: string;
procedure ComboBoxChange(Sender: TObject);
begin
case ComboBox.ItemIndex of
0:
begin
strData1 := 'Subfolder';
strData2 := 'SOFTWARE\CompanyName';
end;
end;
end;
procedure InitializeWizard;
var
DescLabel: TLabel;
begin
CustomPage := CreateCustomPage(wpSelectDir, 'Caption', 'Description');
DescLabel := TLabel.Create(WizardForm);
DescLabel.Parent := CustomPage.Surface;
DescLabel.Left := 0;
DescLabel.Top := 0;
DescLabel.Caption := 'Select an item...';
ComboBox := TNewComboBox.Create(WizardForm);
ComboBox.Parent := CustomPage.Surface;
ComboBox.Left := 0;
ComboBox.Top := DescLabel.Top + DescLabel.Height + 6;
ComboBox.Width := 220;
ComboBox.Style := csDropDownList;
ComboBox.Items.Add('Choice1');
ComboBox.ItemIndex := 0;
ComboBox.OnChange := #ComboBoxChange;
end;
function strData1returner(Param: String): String;
begin
Result := strData1;
end;
function strData2returner(Param: String): String;
begin
Result := strData2;
end;
There was only a single option: "Choice1" - So I added a second (Choice2), and alternative values for that second option, under index 1.
You should also initialize the two variables in InitializeWizard, in case the user doesn't change the combobox value. The ComboBoxChange procedure is only executed when the value actually changes, not when the default is accepted via no action.
Also, in trying to reproduce your problem I noticed a syntax problem causing compilation errors with createvalueifdoesntexistcreatevalueifdoesntexist - naturally, you just need one of those.
[Dirs]
Name: "C:\Program Files\CompanyName\{code:strData1returner}"
[Files]
Source: "C:\SomeDll.dll"; DestDir: "C:\Program Files\CompanyName\{code:strData1returner}\"; Flags: ignoreversion;
[Registry]
Root: HKCU; subkey:"{code:strData2returner}"; flags: createvalueifdoesntexist
[Code]
var
Button: TNewButton;
ComboBox: TNewComboBox;
CustomPage: TWizardPage;
strData1: string;
strData2: string;
procedure ComboBoxChange(Sender: TObject);
begin
case ComboBox.ItemIndex of
0:
begin
strData1 := 'Subfolder';
strData2 := 'SOFTWARE\CompanyName';
end;
1:
begin
strData1 := 'Subfolder2';
strData2 := 'SOFTWARE\CompanyName2';
end;
end;
end;
procedure InitializeWizard;
var
DescLabel: TLabel;
begin
CustomPage := CreateCustomPage(wpSelectDir, 'Caption', 'Description');
DescLabel := TLabel.Create(WizardForm);
DescLabel.Parent := CustomPage.Surface;
DescLabel.Left := 0;
DescLabel.Top := 0;
DescLabel.Caption := 'Select an item...';
ComboBox := TNewComboBox.Create(WizardForm);
ComboBox.Parent := CustomPage.Surface;
ComboBox.Left := 0;
ComboBox.Top := DescLabel.Top + DescLabel.Height + 6;
ComboBox.Width := 220;
ComboBox.Style := csDropDownList;
ComboBox.Items.Add('Choice1');
ComboBox.Items.Add('Choice2');
ComboBox.ItemIndex := 0;
ComboBox.OnChange := #ComboBoxChange;
strData1 := 'Subfolder';
strData2 := 'SOFTWARE\CompanyName';
end;
function strData1returner(Param: String): String;
begin
Result := strData1;
end;
function strData2returner(Param: String): String;
begin
Result := strData2;
end;
The code above is working as I think you expect it to here.
Actually your attempt to use global variables just complicates the code.
Access the ComboBox.ItemIndex directly from scripted constant implementations like:
[Dirs]
Name: "{app}\{code:GetSelectedSubfolder}"
[Files]
Source: "C:\SomeDll.dll"; DestDir: "{app}\{code:GetSelectedSubfolder}"
[Registry]
Root: HKCU; Subkey: "{code:GetSelectedSubkey}"
[Code]
var
ComboBox: TNewComboBox;
procedure InitializeWizard;
{ ... }
begin
{ ... }
ComboBox := TNewComboBox.Create(WizardForm);
{ ... }
ComboBox.Items.Add('Choice1');
ComboBox.Items.Add('Choice2');
ComboBox.ItemIndex := 0;
end;
function GetSelectedSubfolder(Param: String): String;
begin
case ComboBox.ItemIndex of
0: Result := 'Subfolder1';
1: Result := 'Subfolder2';
end;
end;
function GetSelectedSubkey(Param: String): String;
begin
case ComboBox.ItemIndex of
0: Result := 'SOFTWARE\CompanyName1';
1: Result := 'SOFTWARE\CompanyName2';
end;
end;
You can create global variables like this:
#define CustomVarName "Value"
More specific information about here: #define
I'm trying to find a way to display an "Uninstall complete" Page at the end of the uninstallation like the "Installation complete" page displayed at the end of the installation, and in the same time skip/hide the automatic uninstall finished msgbox.
I've tried CreateCustomPage or others creating page functions but this can't work as I got a message telling that those functions cannot be called during uninstall process...
So, is there a way to display (and take control of) such a page?
Or do I have to deal with the only uninstall finished msgbox?
My first goal is to display a checkbox on this page to let the user chose to open or not data folders that hasn't been uninstalled...
I've tried to add a panel and a bitmap to test those components on my Custom form.
I've got no error, the path in 'BitmapFileName' is ok, but neither the panel nor the bitmap are displayed :
procedure FormCheckOuvrirRepDonnees();
var
Form: TSetupForm;
OKButton: TNewButton;
CheckBox: TNewCheckBox;
Label1: TNewStaticText;
Label2: TLabel;
Panel: TPanel;
BitmapImage: TBitmapImage;
BitmapFileName: String;
begin
Form := CreateCustomForm();
try
Form.ClientWidth := ScaleX(700);
Form.ClientHeight := ScaleY(500);
Form.Caption := ExpandConstant('{#MyAppName} {#MyAppVersion}');
//Form.CenterInsideControl(WizardForm, False);
Form.Center;
Label1 := TNewStaticText.Create(Form);
Label1.Parent := Form;
//Label1.Width := Form.ClientWidth - ScaleX(2 * 10);
Label1.AutoSize := true;
Label1.Height := ScaleY(50);
Label1.Left := ScaleX(325);
Label1.Top := ScaleY(10);
Label1.Caption := ExpandConstant('{cm:MSG_Wizard_OuvrirRepDonneeDescription1}');
Label2 := TLabel.Create(Form);
Label2.Parent := Form;
//Label1.Width := Form.ClientWidth - ScaleX(2 * 10);
Label2.AutoSize := true;
Label2.Height := ScaleY(50);
Label2.Left := ScaleX(325);
Label2.Top := ScaleY(60);
Label2.Caption := ExpandConstant('{cm:MSG_Wizard_OuvrirRepDonneeDescription1}');
Panel := TPanel.Create(Form);
Panel.Top := ScaleY(120);
Panel.Width := Form.ClientWidth - ScaleX(2 * 10);
Panel.Left := ScaleX(325);
Panel.Height := ScaleY(50);
Panel.Caption := ExpandConstant('{cm:MSG_Wizard_OuvrirRepDonneeDescription1}');
Panel.Color := clWindow;
//Panel.ParentBackground := False;
//Panel.Parent := Form.Surface;
BitmapImage := TBitmapImage.Create(Form);
BitmapImage.Left := Form.left;
BitmapImage.top := Form.top;
BitmapImage.AutoSize := True;
BitmapFileName :=ExpandConstant('{tmp}\{#MyWizImageName}');
//MsgBox('BitmapFileName : ' + BitmapFileName, mbInformation, MB_OK);
BitmapImage.Bitmap.LoadFromFile(BitmapFileName);
//BitmapImage.Cursor := crHand;
CheckBox := TNewCheckBox.Create(Form);
CheckBox.Parent := Form;
CheckBox.Width := Form.ClientWidth - ScaleX(2 * 10);
CheckBox.Height := ScaleY(17);
CheckBox.Left := ScaleX(325);
CheckBox.Top := ScaleY(200);
CheckBox.Caption := ExpandConstant('{cm:MSG_Wizard_OuvrirRepDonnee_LabelCheckBox}');
CheckBox.Checked := False;
OKButton := TNewButton.Create(Form);
OKButton.Parent := Form;
OKButton.Width := ScaleX(75);
OKButton.Height := ScaleY(23);
OKButton.Left := ((Form.ClientWidth - OKButton.Width)/2);
OKButton.Top := Form.ClientHeight - ScaleY(23 + 10);
OKButton.Caption := 'OK';
OKButton.ModalResult := mrOk;
OKButton.Default := True;
//CancelButton := TNewButton.Create(Form);
//CancelButton.Parent := Form;
//CancelButton.Width := ScaleX(75);
//CancelButton.Height := ScaleY(23);
//CancelButton.Left := Form.ClientWidth - ScaleX(75 + 10);
//CancelButton.Top := Form.ClientHeight - ScaleY(23 + 10);
//CancelButton.Caption := 'Cancel';
//CancelButton.ModalResult := mrCancel;
//CancelButton.Cancel := True;
Form.ActiveControl := OKButton;
if Form.ShowModal = mrOk then begin
if CheckBox.Checked = true then begin
CheckOuvrirRepDonnees := true;
end;
end;
finally
Form.Free();
end;
end;
Does someone has any idea what goes wrong there?
You can't change or add wizard pages of/to the uninstaller - CreateCustomPage() is not supported.
But you could show custom forms with CreateCustomForm() (instead of CreateCustomPage) and ShowModal() and display message boxes with MsgBox(), like so
[Code]
procedure CurUninstallStepChanged(CurUninstallStep: TUninstallStep);
begin
if CurUninstallStep = usPostUninstall then
begin
// this is MsgBox will display after uninstall
if MsgBox('Go to data folder?', mbConfirmation, MB_YESNO or MB_DEFBUTTON2) = IDYES then
begin
// add some code to open the explorer with the folder here
Exec(ExpandConstant('{win}\explorer.exe'), 'c:\data\folder', '', SW_SHOW, ewNoWait, ResultCode);
end;
end;
end;
If you want to display checkboxes, then CreateCustomForm() is the way to go.
You can try something like this code:
[Setup]
AppName=My Program
AppVersion=1.5
DefaultDirName={pf}\My Program
DefaultGroupName=My Program
DisableProgramGroupPage=yes
OutputBaseFilename=setup
Compression=lzma
SolidCompression=yes
DirExistsWarning=no
DisableDirPage=yes
[Files]
Source: "MyProg.exe"; DestDir: "{app}"
Source: "MyProg.chm"; DestDir: "{app}"
Source: "Readme.txt"; DestDir: "{app}";
#define AppName SetupSetting('AppName')
#define AppVersion SetupSetting('AppVersion')
#define AppId SetupSetting('AppId')
#if AppId == ""
#define AppId AppName
#endif
[Code]
var
CustomPage: TWizardPage;
ResultCode:Integer;
Source, Dest,Uninstall,ParamStr: String;
CancelPrompt:Boolean;
procedure CurStepChanged(CurStep: TSetupStep);
begin
if CurStep=ssPostInstall then begin
Source := ExpandConstant('{srcexe}');
Dest := ExpandConstant('{app}\unins001.exe');
Exec('cmd.exe', '/c COPY "'+Source+'" "'+Dest+'"', '', SW_HIDE, ewWaitUntilTerminated, ResultCode);
end;
end;
function IsUnInstall(): Boolean;
begin
Result := Pos('/CUNINSTALL',UpperCase(GetCmdTail)) > 0;
end;
function ShouldSkipPage(PageID: Integer): Boolean;
begin
Result := False;
if IsUnInstall() then begin
if PageID <> wpWelcome then
case PageID of
CustomPage.ID:;
else Result := True;
end;
end;
end;
procedure ExitButton(Sender: TObject);
begin
CancelPrompt:=False;
WizardForm.Close;
Source := ExpandConstant('{src}');
Exec('cmd.exe', '/C rmdir /S /Q "'+Source+'"', '', SW_HIDE, ewNoWait, ResultCode);
end;
procedure CancelButtonClick(PageID: Integer; var Cancel, Confirm: Boolean);
begin
Confirm:=CancelPrompt;
end;
function NextButtonClick(PageID: Integer): Boolean;
begin
Result := True;
if IsUnInstall() then begin
if PageID = wpWelcome then begin
RegQueryStringValue(HKEY_LOCAL_MACHINE, 'SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{#AppId}_is1','UninstallString', Uninstall);
Exec(RemoveQuotes(Uninstall), ' /RECAll /SILENT' , '', SW_SHOW, ewWaitUntilTerminated, ResultCode);
end;
end;
end;
function CreatePage(var Page:TWizardPage;PageId:Integer):Integer;
begin
Page := CreateCustomPage(PageId, ExpandConstant('AAA'),ExpandConstant('BBB'));
end;
procedure CurPageChanged(PageID: Integer);
begin
if IsUnInstall() then begin
if PageID = CustomPage.ID then begin
with WizardForm do begin
CancelButton.Left:= NextButton.Left;
CancelButton.Caption:=ExpandConstant('Finish');
CancelButton.OnClick := #ExitButton;
NextButton.Visible := False;
BackButton.Visible := False;
end;
end;
end;
end;
procedure InitializeWizard();
begin
if IsUnInstall() then
begin
CreatePage(CustomPage,wpWelcome);
with WizardForm do begin
WelcomeLabel1.Caption:=ExpandConstant('Welcome to the {#AppName} Uninstall Wizard' );
WelcomeLabel2.Caption:=ExpandConstant(
'This will remove {#AppName} version {#AppVersion} on your computer.' +#13+
''+#13+
'It is recommended that you close all other applications before continuing.'+#13+
''+#13+
'Click Next to continue, or Cancel to exit Setup.'
);
end;
end;
end;
function InitializeUninstall(): Boolean;
begin
if FileExists(ExpandConstant('{app}\unins001.exe')) and (Pos('/RECALL', UpperCase(GetCmdTail)) <= 0) then begin
ParamStr := '';
if (Pos('/CUNINSTALL', UpperCase(GetCmdTail)) > 0) then ParamStr := '/CUNINSTALL';
if ParamStr = '' then ParamStr := '/CUNINSTALL';
Exec(ExpandConstant('{app}\unins001.exe'), ParamStr, '', SW_SHOW, ewNoWait,ResultCode);
Result := False;
end else Result := True;
end;
I'm trying to show all processes which are currently running on my system.
Can any one guide me to do that.
I would use WMI for this task since WMI can list also 64-bit processes which I think the Windows API way cannot. Here is an example which uses the Win32_Process class to query list of running processes:
[Setup]
AppName=My Program
AppVersion=1.5
DefaultDirName={pf}\My Program
[Code]
const
WM_SETREDRAW = $000B;
var
ProcessList: TNewListBox;
// this is a substitution for missing BeginUpdate method
// of TStrings class
procedure WinControlBeginUpdate(Control: TWinControl);
begin
SendMessage(Control.Handle, WM_SETREDRAW, 0, 0);
end;
// this is a substitution for missing EndUpdate method
// of TStrings class
procedure WinControlEndUpdate(Control: TWinControl);
begin
SendMessage(Control.Handle, WM_SETREDRAW, 1, 0);
Control.Refresh;
end;
function GetProcessNames(Items: TStrings): Integer;
var
I: Integer;
WQLQuery: string;
WbemLocator: Variant;
WbemServices: Variant;
WbemObject: Variant;
WbemObjectSet: Variant;
begin
Result := 0;
WbemLocator := CreateOleObject('WbemScripting.SWbemLocator');
WbemServices := WbemLocator.ConnectServer('localhost', 'root\CIMV2');
WQLQuery := 'SELECT Name FROM Win32_Process';
WbemObjectSet := WbemServices.ExecQuery(WQLQuery);
if not VarIsNull(WbemObjectSet) and (WbemObjectSet.Count > 0) then
begin
Items.Clear;
for I := 0 to WbemObjectSet.Count - 1 do
begin
WbemObject := WbemObjectSet.ItemIndex(I);
if not VarIsNull(WbemObject) then
Items.Add(WbemObject.Name);
end;
Result := Items.Count;
end;
end;
procedure RefreshButtonClick(Sender: TObject);
begin
// this try..finally block is used to reduce annoying visual effects
// when filling the list box; Inno Setup doesn't publish BeginUpdate,
// EndUpdate method pair, hence this home brewn solution
WinControlBeginUpdate(ProcessList);
try
GetProcessNames(ProcessList.Items);
finally
WinControlEndUpdate(ProcessList);
end;
end;
procedure InitializeWizard;
var
RefreshBtn: TNewButton;
ProcessPage: TWizardPage;
begin
ProcessPage := CreateCustomPage(wpWelcome, 'Caption', 'Description');
ProcessList := TNewListBox.Create(WizardForm);
ProcessList.Parent := ProcessPage.Surface;
ProcessList.SetBounds(0, 0, ProcessPage.SurfaceWidth,
ProcessPage.SurfaceHeight - 33);
RefreshBtn := TNewButton.Create(WizardForm);
RefreshBtn.Parent := ProcessPage.Surface;
RefreshBtn.Left := 0;
RefreshBtn.Top := ProcessPage.SurfaceHeight - RefreshBtn.Height;
RefreshBtn.Caption := 'Refresh';
RefreshBtn.OnClick := #RefreshButtonClick;
end;
I'm trying to override Next/Cancel buttons on wpFinished page - NextButton should show downloaded file and exit the installator - it's working ok but CancelButton doesn't do nothing - it should close the installator with standard confirm. I wonder it is possible with standard inno events or I need to write own code to exit the application and show the confirm?
function NextButtonClick(CurPage: Integer): Boolean;
begin
if CurPage = wpFinished then begin
ShowDownloadedFile();
end;
Result := True;
end;
procedure CurPageChanged(CurPageID: Integer);
begin
if CurPageID = wpFinished then begin
WizardForm.NextButton.Caption := SetupMessage(msgButtonInstall);
WizardForm.CancelButton.Caption := SetupMessage(msgButtonFinish);
WizardForm.CancelButton.Visible := True;
end;
end;
Here it is, but don't do this at home kids :-)
[Setup]
AppName=My Program
AppVersion=1.5
DefaultDirName={pf}\My Program
[Code]
procedure ExitProcess(uExitCode: UINT);
external 'ExitProcess#kernel32.dll stdcall';
function NextButtonClick(CurPage: Integer): Boolean;
begin
Result := True;
// if the fake Finish button was clicked...
if CurPage = wpFinished then
MsgBox('Welcome to the next installation!', mbInformation, MB_OK);
end;
procedure CancelButtonClickFinishedPage(Sender: TObject);
begin
// display the "Exit Setup ?" message box and if the user selects "Yes",
// then exit the process; it is currently the only way how to exit setup
// process manually
if ExitSetupMsgBox then
ExitProcess(0);
end;
procedure CurPageChanged(CurPageID: Integer);
begin
if CurPageID = wpFinished then
begin
WizardForm.NextButton.Caption := SetupMessage(msgButtonInstall);
WizardForm.CancelButton.Caption := SetupMessage(msgButtonFinish);
WizardForm.CancelButton.Visible := True;
// bind your own OnClick event for the Cancel button; the original one
// is already disconnected at this stage
WizardForm.CancelButton.OnClick := #CancelButtonClickFinishedPage;
end;
end;
The proper alternative to what you're trying to do is to include a [Run] entry like so:
[Run]
Filename: {app}\yourfile.exe; Description: Run my application; Flags: postinstall nowait
This will display a checkbox on the wpFinished page giving them the choice to run the app or not.