问题
My Inno Setup program installs three programs during the installation.
I added the checkbox for each of the three programs to show after installation page in the [Run]
section:
Filename: "{app}\Program1.exe"; Description: "{cm:LaunchProgram,{#StringChange("Program1", '&', '&&')}}"; Flags: nowait postinstall skipifsilent unchecked runascurrentuser;
Filename: "{app}\Program2.exe"; Description: "{cm:LaunchProgram,{#StringChange("Program2", '&', '&&')}}"; Flags: nowait postinstall skipifsilent unchecked runascurrentuser;
Filename: "{app}\Program3.exe"; Description: "{cm:LaunchProgram,{#StringChange("Program3", '&', '&&')}}"; Flags: nowait postinstall skipifsilent unchecked runascurrentuser;
How can I make it only allow to check one box at time?
Thank you
回答1:
You have these options:
Turn the checkboxes to radio buttons (this solution is shown below).
Programmatically make sure that when one checkbox is checked, all others get unchecked (this solution is shown below too)
For a similar problem see also Inno Setup - Show children component as sibling and show check instead of square in checkbox.
Use Tasks entries with exclusive flag to trigger Run entries without the postinstall flag (instead of checkboxes created by
Run
entries withpostinstall
flag).
Turning the checkboxes to radio buttons
[Code]
var
RunListModified: Boolean;
procedure CurPageChanged(CurPageID: Integer);
var
I: Integer;
begin
{ The first time the Finished page shows, turn all checkboxes to radio buttons. }
{ (note that the Finished page can show multiple times, }
{ if the InfoAfterFile directive is set only, }
{ or if there is some custom page before the Finished page) }
if (CurPageID = wpFinished) and (not RunListModified) then
begin
{ Add a dummy "Run nothing" entry }
WizardForm.RunList.AddRadioButton('Run nothing', '', 0, True, True, -1);
for I := 0 to WizardForm.RunList.Items.Count - 2 do
begin
{ For all entries - take the first checkbox in the list, clone it to the end }
{ as a radio button with the same properties }
{ (mainly the caption and the object, which is actually index to the run list). }
{ Note that the ItemSubItem is always empty, ItemLevel always 0 and ItemEnabled }
{ always True. }
WizardForm.RunList.AddRadioButton(
WizardForm.RunList.ItemCaption[0],
WizardForm.RunList.ItemSubItem[0],
WizardForm.RunList.ItemLevel[0],
False,
WizardForm.RunList.ItemEnabled[0],
WizardForm.RunList.ItemObject[0]);
{ And delete the original checkbox, pulling the next on to the first place }
{ for the next round. }
WizardForm.RunList.Items.Delete(0);
end;
RunListModified := True;
end;
end;
function NextButtonClick(CurPageID: Integer): Boolean;
begin
if CurPageID = wpFinished then
begin
{ Make sure we remove the dummy "Run nothing" entry, }
{ otherwise the Inno Setup fails processing it. }
{ The test for RunList.Count is for a case that a restart is needed and }
{ the RunList is never populated/shown. }
{ The test for ItemObject is here only in case we ever get here multiple time. }
{ But it should not really happen. }
if (WizardForm.RunList.Items.Count > 0) and
(Integer(WizardForm.RunList.ItemObject[0]) = -1) then
begin
WizardForm.RunList.Items.Delete(0);
end;
end;
Result := True;
end;
For a similar question, see Showing run tasks as radio choices instead of check boxes?
Programmatically make sure that when one checkbox is checked, all others get unchecked
[Code]
var
RunListLastChecked: Integer;
procedure RunListClickCheck(Sender: TObject);
var
I: Integer;
Checked: Integer;
begin
{ Find if some other checkbox got checked }
Checked := -1;
for I := 0 to WizardForm.RunList.Items.Count - 1 do
begin
if WizardForm.RunList.Checked[I] and (I <> RunListLastChecked) then
begin
Checked := I;
end;
end;
{ If it was, uncheck the previously checked box and remember the new one }
if Checked >= 0 then
begin
if RunListLastChecked >= 0 then
begin
WizardForm.RunList.Checked[RunListLastChecked] := False;
end;
RunListLastChecked := Checked;
end;
{ Or if the previously checked box got unchecked, forget it. }
{ (This is not really necessary, it's just to clean the things up) }
if (RunListLastChecked >= 0) and
(not WizardForm.RunList.Checked[RunListLastChecked]) then
begin
RunListLastChecked := -1;
end;
end;
procedure InitializeWizard();
begin
WizardForm.RunList.OnClickCheck := @RunListClickCheck;
RunListLastChecked := -1;
end;
来源:https://stackoverflow.com/questions/35539827/how-to-allow-only-one-checked-box-in-run-section