How to disable NextButton when file is not selected on InputFilePage (CreateInputFilePage)? - inno-setup

My Inno Setup program have a custom "input file page" that was created using CreateInputFilePage.
How can I disable the NextButton in this page until the file path is properly picked by the user?
In other words, I need to make the NextButton unclickable while the file selection form is empty, and clickable when the file selection form is filled.
Thank you.

The easiest way is to use NextButtonClick to validate the inputs and display an error message when the validation fails.
var
FilePage: TInputFileWizardPage;
procedure InitializeWizard();
begin
FilePage := CreateInputFilePage(wpSelectDir, 'caption', 'description', 'sub caption');
FilePage.Add('prompt', '*.*', '.dat');
end;
function NextButtonClick(CurPageID: Integer): Boolean;
begin
Result := True;
if (CurPageID = FilePage.ID) and
(Length(FilePage.Edits[0].Text) = 0) then
begin
MsgBox('Please select a file.', mbError, MB_OK);
WizardForm.ActiveControl := FilePage.Edits[0];
Result := False;
end;
end;
If you really want to update the "Next" button state while the input changes, it is a bit more complicated:
procedure FilePageEditChange(Sender: TObject);
begin
WizardForm.NextButton.Enabled := (Length(TEdit(Sender).Text) > 0);
end;
procedure FilePageActivate(Sender: TWizardPage);
begin
FilePageEditChange(TInputFileWizardPage(Sender).Edits[0]);
end;
procedure InitializeWizard();
var
Page: TInputFileWizardPage;
Edit: TEdit;
begin
Page := CreateInputFilePage(wpSelectDir, 'caption', 'description', 'sub caption');
{ To update the Next button state when the page is entered }
Page.OnActivate := #FilePageActivate;
Edit := Page.Edits[Page.Add('prompt', '*.*', '.dat')];
{ To update the Next button state when the edit contents changes }
Edit.OnChange := #FilePageEditChange;
end;

Related

Run Files and Programs according to custom checkboxes after clicking on Finish Button in Inno Setup

I have created some custom checkboxes in the finished page of Inno Setup.
For example launching an app, opening a text file etc.
I need when the user clicks on the finish button I check those checkboxes and do whatever that is needed. How can I do such a thing in Inno Setup?
Here is the code:
procedure CurPageChanged(CurPageID: Integer);
begin
if CurPageID = wpFinished then
begin
Launch := TNewCheckBox.Create(WizardForm);
Launch.Parent := WizardForm;
Launch.Left := WizardForm.ClientWidth - 350;
Launch.Top := WizardForm.CancelButton.Top;
Launch.Width := 120;
Launch.Height := WizardForm.CancelButton.Height;
Launch.Caption := 'Launch';
end;
end;
In NextButtonClick event handler, test if your checkbox is checked and act accordingly.
function NextButtonClick(CurPageID: Integer): Boolean;
var
ResultCode: Integer;
Path: string;
Message: string;
begin
if CurPageID = wpFinished then
begin
if Launch.Checked then
begin
Path := ExpandConstant('{app}\MyProg.exe');
if ExecAsOriginalUser(Path, '', '', SW_SHOW, ewNoWait, ResultCode) then
begin
Log('Executed MyProg');
end
else
begin
Message := 'Error executing MyProg: ' + SysErrorMessage(ResultCode);
MsgBox(Message, mbError, MB_OK);
end;
end;
end;
Result := True;
end;
Simply check the checkbox state:
if (Launch.Checked = True) then
begin
// checkbox is checked
end
else
begin
// Checkbox is unchecked
end;
The best place is to use function NextButtonClick(CurPageID: Integer): Boolean;
however in that case you need to make your checkbox a global variable (so it is accessible).

Inno Setup remove/hide/disable the NextButton on a custom wizard page

I would like to disable the "Next" button from my custom wizard page.
The fact is that I've no issue to change the caption of it for example, but if I set the NextButton.Enabled to False, Inno Setup show me the Welcome page instead of my Custom Page. Any Idea?
procedure CurPageChanged(CurPageID: Integer);
begin
WizardForm.NextButton.Caption := 'test'; { Works }
WizardForm.NextButton.Enabled := false ; { delete my custom page }
WizardForm.CancelButton.Caption := 'Finish';
end;
procedure CreateTheWizardPages;
var
Page: TWizardPage;
TestConnectivityButton: TButton;
begin
Page := CreateCustomPage(wpWelcome, 'Connectivity Test', '');
CurPageChanged(Page.ID);
TestConnectivityButton := TButton.Create(Page);
TestConnectivityButton.Width := ScaleX(100);
TestConnectivityButton.Height := ScaleY(30);
TestConnectivityButton.Caption := CustomMessage('TestConnectivityAccessButtonLabel');
TestConnectivityButton.OnClick := #TestConnectivityWindow;
TestConnectivityButton.Parent := Page.Surface;
end;
procedure InitializeWizard;
begin
CreateTheWizardPages;
end;
You have to make the changes, when you enter your custom page only – When CurPageChanged event function is called with CurPageID equal to Page.ID.
And you cannot call CurPageChanged yourself!
var
Page: TWizardPage;
procedure CurPageChanged(CurPageID: Integer);
begin
if CurPageID = Page.ID then
begin
WizardForm.NextButton.Caption := 'Test';
WizardForm.NextButton.Enabled := False ;
WizardForm.CancelButton.Caption := 'Finish';
end;
end;
procedure CreateTheWizardPages;
var
TestConnectivityButton: TButton;
begin
Page := CreateCustomPage(wpWelcome, 'Connectivity Test', '');
TestConnectivityButton := TButton.Create(Page);
TestConnectivityButton.Width := ScaleX(100);
TestConnectivityButton.Height := ScaleY(30);
TestConnectivityButton.Caption :=
CustomMessage('TestConnectivityAccessButtonLabel');
TestConnectivityButton.OnClick := #TestConnectivityWindow;
TestConnectivityButton.Parent := Page.Surface;
end;
Another option is using Page.OnActivate event instead of CurPageChanged event function.

Inno Setup Create dependency between custom check boxes

I have a custom page SelectPage that I am creating two custom check boxes on. The relevant parts of the code from InitializeWizard procedure are below:
//Define the Restart Services Checkbox
RestartServicesCheckBox := TNewCheckBox.Create(WizardForm);
with RestartServicesCheckBox do
begin
Parent := SelectPage.Surface;
Caption := 'Restart Services';
Left := OptionsLabel.Left;
Top := OptionsLabel.Top + ScaleY(20);
Checked := True;
end;
//Define the Restart Server Checkbox
RestartServerCheckBox := TNewCheckBox.Create(WizardForm);
with RestartServerCheckBox do
begin
Parent := SelectPage.Surface;
Caption := 'Restart Server';
Left := OptionsLabel.Left;
Top := RestartServicesCheckBox.Top + ScaleY(22);
Checked := False
end;
This works and I get the check boxes that I want and they perform the actions that I assign to them. What I am struggling to work out is how to assign a dependency between the two, so that if one is checked, the other is automatically unchecked. However, I do not want a radio buttons type dependency, as both checkboxes might need to be unchecked. I was looking at trying to intercept the OnClick event something like this:
var
DefaultOnClick: TNotifyEvent;
procedure InitializeWizard();
begin
//Store the original OnClick event procedure and assign custom procedure
DefaultOnClick := WizardForm.TCheckBox.OnClick;
WizardForm.TCheckBox.OnClick := #OnClick;
end;
//Uncheck and Restart Services if Restart Server is checked and vice versa
procedure UpdateOptions();
begin
with RestartServicesCheckBox do
begin
if RestartServicesCheckBox.Checked then
begin
Checked := False;
end;
end;
with RestartServerCheckBox do
begin
if RestartServerCheckBox.Checked then
begin
Checked := False;
end;
end;
end;
//Update the options check boxes if the states change and restore the original event handler procedures
procedure OnClick(Sender: TObject);
begin
DefaultOnClick(Sender);
UpdateOptions;
end;
However, I do not know what the full event name is that I need to intercept. It clearly isn't WizardForm.TCheckBox.OnClick anyway. What would this event name be and will this method work? Alternatively, is there a simpler way to do this?
It is the TCheckBox.OnClick event that you need to use.
var
RestartServicesCheckBox: TNewCheckBox;
RestartServerCheckBox: TNewCheckBox;
procedure RestartServicesCheckBoxClick(Sender: TObject);
begin
if RestartServicesCheckBox.Checked then
RestartServerCheckBox.Checked := False;
end;
procedure RestartServerCheckBoxClick(Sender: TObject);
begin
if RestartServerCheckBox.Checked then
RestartServicesCheckBox.Checked := False;
end;
procedure InitializeWizard();
begin
// Define the Restart Services Checkbox
RestartServicesCheckBox := TNewCheckBox.Create(WizardForm);
with RestartServicesCheckBox do
begin
...
Checked := True;
OnClick := #RestartServicesCheckBoxClick;
end;
// Define the Restart Server Checkbox
RestartServerCheckBox := TNewCheckBox.Create(WizardForm);
with RestartServerCheckBox do
begin
...
Checked := False;
OnClick := #RestartServerCheckBoxClick;
end;
end;
Though I think that three radio buttons might be better:
Do not restart
Restart service only
Restart server

Inno Setup replace buttons at wpFinished page

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.

Checkbox :: Select one at a time

This is the code section from inno setup.My intention is to make two Checkbox where at a time one is being selected.
But this code return error when first checkbox is clicked.
[code]
procedure CheckBoxOnClick(Sender: TObject);
var
Box2,CheckBox: TNewCheckBox;
begin
if CheckBox.Checked then ///error:"Could not call proc" [sud it be global if then how to or what to change?]
BEGIN
CheckBox.State := cbUnchecked;
Box2.State := cbChecked;
END else
BEGIN
CheckBox.State := cbChecked;
Box2.State := cbUnchecked;
END;
end;
procedure Box2OnClick(Sender: TObject);
var
Box2,CheckBox: TNewCheckBox;
begin
if Box2.Checked then ///error:same
BEGIN
CheckBox.State := cbChecked;
Box2.State := cbUnchecked;
END else
BEGIN
CheckBox.State := cbUnchecked;
Box2.State := cbChecked;
END;
end;
procedure CreateTheWizardPages;
var
Page: TWizardPage;
Box2,CheckBox: TNewCheckBox;
begin
{ TButton and others }
Page := CreateCustomPage(wpWelcome, '', '');
CheckBox := TNewCheckBox.Create(Page);
CheckBox.Top :=ScaleY(8)+ScaleX(50);
CheckBox.Width := Page.SurfaceWidth;
CheckBox.Height := ScaleY(17);
CheckBox.Caption := 'Do this';
CheckBox.Checked := True;
CheckBox.OnClick := #CheckBoxOnClick;
CheckBox.Parent := Page.Surface;
Box2 := TNewCheckBox.Create(Page);
Box2.Top :=ScaleY(8)+ScaleX(70);
Box2.Width := Page.SurfaceWidth;
Box2.Height := ScaleY(17);
Box2.Caption := 'No,Thanks.';
Box2.Checked := False;
Box2.OnClick := #Box2OnClick;
Box2.Parent := Page.Surface;
end;
procedure InitializeWizard();
//var
begin
{ Custom wizard pages }
CreateTheWizardPages;
end;
Please tell me where to change..
The cause of your error is that your are referencing CheckBox which is defined locally in that method. At this point CheckBox has not been created. Which means your calling CheckBox.Checked when CheckBox is undefined (most likely NIL)
Each declaration of CheckBox represents a new variable and does not reference the other variables with the same name. This is due to scoping rules.
One option to solve your problem is to remove the local declarations of Box2, and CheckBox in each method and declare them globally.

Resources