Search code examples
user-interfaceinno-setuppascalscript

Add 4 license pages in Inno Setup


I followed Martin's answer here to create UI for 4 license pages in my Inno Setup installer.

The code looks like below (work in progress..)

[Files]
Source: "license2_english.txt"; Flags: dontcopy
Source: "license3_english.txt"; Flags: dontcopy
Source: "license4_english.txt"; Flags: dontcopy

[Code]

var 
  SecondLicensePage: TOutputMsgMemoWizardPage;
  License2AcceptedRadio: TRadioButton;
  License2NotAcceptedRadio: TRadioButton;

  ThirdLicensePage: TOutputMsgMemoWizardPage;
  License3AcceptedRadio: TRadioButton;
  License3NotAcceptedRadio: TRadioButton;

  FourthLicensePage: TOutputMsgMemoWizardPage;
  License4AcceptedRadio: TRadioButton;
  License4NotAcceptedRadio: TRadioButton;

procedure CheckLicense2Accepted(Sender: TObject);
begin
  // Update Next button when user (un)accepts the license
  WizardForm.NextButton.Enabled := License2AcceptedRadio.Checked;
end;

procedure CheckLicense3Accepted(Sender: TObject);
begin
  // Update Next button when user (un)accepts the license
  WizardForm.NextButton.Enabled := License3AcceptedRadio.Checked;
end;

procedure CheckLicense4Accepted(Sender: TObject);
begin
  // Update Next button when user (un)accepts the license
  WizardForm.NextButton.Enabled := License4AcceptedRadio.Checked;
end;

function CloneLicenseRadioButtonL2(Source: TRadioButton): TRadioButton;
begin
  Result := TRadioButton.Create(WizardForm);
  Result.Parent := SecondLicensePage.Surface;
  Result.Caption := Source.Caption;
  Result.Left := Source.Left;
  Result.Top := Source.Top;
  Result.Width := Source.Width;
  Result.Height := Source.Height;
  Result.Anchors := Source.Anchors;
  Result.OnClick := @CheckLicense2Accepted;
end;

function CloneLicenseRadioButtonL3(Source: TRadioButton): TRadioButton;
begin
  Result := TRadioButton.Create(WizardForm);
  Result.Parent := ThirdLicensePage.Surface;
  Result.Caption := Source.Caption;
  Result.Left := Source.Left;
  Result.Top := Source.Top;
  Result.Width := Source.Width;
  Result.Height := Source.Height;
  Result.Anchors := Source.Anchors;
  Result.OnClick := @CheckLicense3Accepted;
end;

function CloneLicenseRadioButtonL4(Source: TRadioButton): TRadioButton;
begin
  Result := TRadioButton.Create(WizardForm);
  Result.Parent := FourthLicensePage.Surface;
  Result.Caption := Source.Caption;
  Result.Left := Source.Left;
  Result.Top := Source.Top;
  Result.Width := Source.Width;
  Result.Height := Source.Height;
  Result.Anchors := Source.Anchors;
  Result.OnClick := @CheckLicense4Accepted;
end;

//Create license wizards
procedure InitializeWizard();
var
  LicenseFileNameL2: string;
  LicenseFileNameL3: string;
  LicenseFilenameL4: string;
                 
  LicenseFilePathL2: string;
  LicenseFilePathL3: string;
  LicenseFilePathL4: string;
begin
  Log(Format('Temp :  %s', [ExpandConstant('{tmp}')]));
  // Create second license page, with the same labels as the original license page
  SecondLicensePage :=
    CreateOutputMsgMemoPage(
      wpLicense, SetupMessage(msgWizardLicense), SetupMessage(msgLicenseLabel),
      SetupMessage(msgLicenseLabel3), '');

  // Create third license page, with the same labels as the original license page
  ThirdLicensePage :=
    CreateOutputMsgMemoPage(
      wpLicense, SetupMessage(msgWizardLicense), SetupMessage(msgLicenseLabel),
      SetupMessage(msgLicenseLabel3), '');

  FourthLicensePage :=
    CreateOutputMsgMemoPage(
      wpLicense, SetupMessage(msgWizardLicense), SetupMessage(msgLicenseLabel),
      SetupMessage(msgLicenseLabel3), '');

  // Shrink license box to make space for radio buttons
  SecondLicensePage.RichEditViewer.Height := WizardForm.LicenseMemo.Height;
  ThirdLicensePage.RichEditViewer.Height  := WizardForm.LicenseMemo.Height;
  FourthLicensePage.RichEditViewer.Height := WizardForm.LicenseMemo.Height;

  // Load license
  // Loading ex-post, as Lines.LoadFromFile supports UTF-8,
  // contrary to LoadStringFromFile.
  LicenseFileNameL2 := 'license2_english.txt';
  LicenseFileNameL3 := 'license3_english.txt';
  LicenseFileNameL4 := 'license4_english.txt';

  LicenseFilePathL2 := ExpandConstant('{tmp}\' + LicenseFileNameL2);
  LicenseFilePathL3 := ExpandConstant('{tmp}\' + LicenseFileNameL3);
  LicenseFilePathL4 := ExpandConstant('{tmp}\' + LicenseFileNameL4);

  ExtractTemporaryFile(LicenseFileNameL2);
  ExtractTemporaryFile(LicenseFileNameL3);
  ExtractTemporaryFile(LicenseFileNameL4);

  SecondLicensePage.RichEditViewer.Lines.LoadFromFile(LicenseFilePathL2);
  ThirdLicensePage.RichEditViewer.Lines.LoadFromFile(LicenseFilePathL3);
  FourthLicensePage.RichEditViewer.Lines.LoadFromFile(LicenseFilePathL4);

  DeleteFile(LicenseFilePathL2);
  DeleteFile(LicenseFilePathL3);
  DeleteFile(LicenseFilePathL4);


  // Clone accept/do not accept radio buttons for the second license
  License2AcceptedRadio :=
    CloneLicenseRadioButtonL2(WizardForm.LicenseAcceptedRadio);
  License2NotAcceptedRadio :=
    CloneLicenseRadioButtonL2(WizardForm.LicenseNotAcceptedRadio);

  License3AcceptedRadio :=
    CloneLicenseRadioButtonL3(WizardForm.LicenseAcceptedRadio);
  License3NotAcceptedRadio :=
    CloneLicenseRadioButtonL3(WizardForm.LicenseNotAcceptedRadio);

  License4AcceptedRadio :=
    CloneLicenseRadioButtonL4(WizardForm.LicenseAcceptedRadio);
  License4NotAcceptedRadio :=
    CloneLicenseRadioButtonL4(WizardForm.LicenseNotAcceptedRadio);


  // Initially not accepted
  License2NotAcceptedRadio.Checked := True;
  License3NotAcceptedRadio.Checked := True;
  License4NotAcceptedRadio.Checked := True;
end;

procedure CurPageChanged(CurPageID: Integer);
begin
  // Update Next button when user gets to second license page
  if CurPageID = SecondLicensePage.ID then
  begin
    CheckLicense2Accepted(nil);
  end;
end;

procedure CurPageChangedL3(CurPageID: Integer);
begin
  // Update Next button when user gets to second license page
  if CurPageID = ThirdLicensePage.ID then
  begin
    CheckLicense3Accepted(nil);
  end;
end;

procedure CurPageChangedL4(CurPageID: Integer);
begin
  // Update Next button when user gets to second license page
  if CurPageID = FourthLicensePage.ID then
  begin
    CheckLicense4Accepted(nil);
  end;
end;

With this code, I see the following issues:

  1. License 4 page comes up before License 2 and 3
  2. In page 2, initially the radio button is initialized to "I do not accept". In this case the "Next" button is enabled and user can move to the next screen.

Image shows Next button enabled even when "I do not accept is selected". Also License 4 is coming before License 2

Next button enabled even when "I do not accept is selected". Also License 4 is coming before License 2

I know I have made a basic mistake somewhere when I tried to expand Martin's answer to cover additional licenses, but I couldn't figure it out yet.

Let me know if anyone has a idea to fix/debug this.

Thanks! a


Solution

  • I'm not gonna try to fix your issues as the way you triplicated all the code is pretty inefficient and hard to maintain. Factor out the creation of the additional license pages instead. Something like this:

    [Setup]
    LicenseFile=license1.txt
    
    [Files]
    Source: "license2.txt"; Flags: dontcopy
    Source: "license3.txt"; Flags: dontcopy
    Source: "license4.txt"; Flags: dontcopy
    
    [Code]
    
    var
      LicenseAcceptedRadioButtons: array of TRadioButton;
    
    procedure CheckLicenseAccepted(Sender: TObject);
    begin
      // Update Next button when user (un)accepts the license
      WizardForm.NextButton.Enabled :=
        LicenseAcceptedRadioButtons[TComponent(Sender).Tag].Checked;
    end;
    
    procedure LicensePageActivate(Sender: TWizardPage);
    begin
      // Update Next button when user gets to second license page
      CheckLicenseAccepted(LicenseAcceptedRadioButtons[Sender.Tag]);
    end;
    
    function CloneLicenseRadioButton(
      Page: TWizardPage; Source: TRadioButton): TRadioButton;
    begin
      Result := TRadioButton.Create(WizardForm);
      Result.Parent := Page.Surface;
      Result.Caption := Source.Caption;
      Result.Left := Source.Left;
      Result.Top := Source.Top;
      Result.Width := Source.Width;
      Result.Height := Source.Height;
      // Needed for WizardStyle=modern / WizardResizable=yes
      Result.Anchors := Source.Anchors;
      Result.OnClick := @CheckLicenseAccepted;
      Result.Tag := Page.Tag;
    end;
    
    var
      LicenseAfterPage: Integer;
    
    procedure AddLicensePage(LicenseFileName: string);
    var
      Idx: Integer;
      Page: TOutputMsgMemoWizardPage;
      LicenseFilePath: string;
      RadioButton: TRadioButton;
    begin
      Idx := GetArrayLength(LicenseAcceptedRadioButtons);
      SetArrayLength(LicenseAcceptedRadioButtons, Idx + 1);
    
      Page :=
        CreateOutputMsgMemoPage(
          LicenseAfterPage, SetupMessage(msgWizardLicense),
          SetupMessage(msgLicenseLabel), SetupMessage(msgLicenseLabel3), '');
      Page.Tag := Idx;
    
      // Shrink license box to make space for radio buttons
      Page.RichEditViewer.Height := WizardForm.LicenseMemo.Height;
      Page.OnActivate := @LicensePageActivate;
    
      // Load license
      // Loading ex-post, as Lines.LoadFromFile supports UTF-8,
      // contrary to LoadStringFromFile.
      ExtractTemporaryFile(LicenseFileName);
      LicenseFilePath := ExpandConstant('{tmp}\' + LicenseFileName);
      Page.RichEditViewer.Lines.LoadFromFile(LicenseFilePath);
      DeleteFile(LicenseFilePath);
    
      // Clone accept/do not accept radio buttons
      RadioButton :=
        CloneLicenseRadioButton(Page, WizardForm.LicenseAcceptedRadio);
      LicenseAcceptedRadioButtons[Idx] := RadioButton;
    
      RadioButton :=
        CloneLicenseRadioButton(Page, WizardForm.LicenseNotAcceptedRadio);
      // Initially not accepted
      RadioButton.Checked := True;
    
      LicenseAfterPage := Page.ID;
    end;
    
    procedure InitializeWizard();
    begin
      LicenseAfterPage := wpLicense;
      AddLicensePage('license2.txt');
      AddLicensePage('license3.txt');
      AddLicensePage('license4.txt');
    end;
    

    enter image description here

    enter image description here

    enter image description here

    enter image description here