inno-setuppascalscript

How can I create separate install paths for Steam & Epic Games, selected by radio buttons, or a pathbox for custom install?


As the title suggests I'm looking to create radio buttons to choose the installation path, one for Steam, one for Epic Games, and a custom path box so the user can decide where to install. Selecting the Steam or Epic would install directly to the default path for those game directories, while choosing the Custom option would allow the user to enter the file path in a path box.


Example image from a similar program: Example Image


Solution

  • The following code adds three radio buttons to "Select Destination Location" page. They serve as presets to installation location.

    On first installation, it detects what folders exist and defaults to the first existing folder. On upgrade, it detects from the previous install path, what preset was selected (I'm aware that you won't use it due to UsePreviousDir=no, but I wanted to post complete solution, in case others want that).

    [Setup]
    DefaultDirName={code:GetDefaultDirName}
    DisableDirPage=no
    
    [Code]
    
    const 
      NoDirName = 'C:\nodirname';
    
    function SteamDirName: string;
    begin
      Result := 'D:\SteamLibrary\steamapps\common\Dead by Daylight'
    end;
    
    function EpicDirName: string;
    begin
      Result := ExpandConstant('{commonpf64}\Epic Games\Dead by Daylight');
    end;
    
    function GetDefaultDirName(Param: string): string;
    begin
      // If Steam folder exists, defaulting to Steam
      if DirExists(SteamDirName) then Result := SteamDirName
        else
      // else if Epic folder exists, defaulting to Epic
      if DirExists(EpicDirName) then Result := EpicDirName
      // Otherwise defaulting to an empty custom path,
      // but as DefaultDirName cannot be empty, using placeholder here,
      // which gets cleared later in InitializeWizard
        else Result := NoDirName; 
    end;
    
    var
      SteamButton: TNewRadioButton;
      EpicButton: TNewRadioButton;
      CustomButton: TNewRadioButton;
    
    procedure DirButtonClick(Sender: TObject);
    begin
      // This might be improved to remember the custom path and
      // restore it when CustomButton is checked
    
      if SteamButton.Checked then
        WizardForm.DirEdit.Text := SteamDirName
      else if EpicButton.Checked then
        WizardForm.DirEdit.Text := EpicDirName;
      WizardForm.DirEdit.Enabled := CustomButton.Checked;
      WizardForm.DirBrowseButton.Enabled := WizardForm.DirEdit.Enabled;
    end;
    
    function CreateButton(var Top: Integer): TNewRadioButton;
    begin
      Result := TNewRadioButton.Create(WizardForm);
      Result.Parent := WizardForm.DirEdit.Parent;
      Result.Top := Top;
      Result.Left := WizardForm.SelectDirBrowseLabel.Left;
      Result.Width := Result.Parent.ClientWidth - Result.Left;
      Result.OnClick := @DirButtonClick;
      Top := Result.Top + Result.Height + ScaleY(8);
    end;
    
    procedure InitializeWizard();
    var
      Top: Integer;
      Dir: string;
    begin
      WizardForm.SelectDirBrowseLabel.Visible := False;
      WizardForm.SelectDirLabel.Caption := 'Select where you want to install to.';
    
      Top := WizardForm.SelectDirBrowseLabel.Top;
      SteamButton := CreateButton(Top);
      SteamButton.Caption := '&Steam';
      SteamButton.Enabled := DirExists(SteamDirName);
    
      EpicButton := CreateButton(Top);
      EpicButton.Caption := '&Epic Games';
      EpicButton.Enabled := DirExists(EpicDirName);
    
      CustomButton := CreateButton(Top);
      CustomButton.Caption := '&Custom path:';
    
      WizardForm.DirBrowseButton.Top :=
        WizardForm.DirBrowseButton.Top + (Top - WizardForm.DirEdit.Top);
      WizardForm.DirEdit.Top := Top;
      WizardForm.DirEdit.TabOrder := CustomButton.TabOrder + 1;
      WizardForm.DirBrowseButton.TabOrder := WizardForm.DirEdit.TabOrder + 1;
    
      // for fresh install, when neither Steam nor Epic was found,
      // clear the installation path placeholder,
      // to force user to select some sensible value
      // (see also the comment in GetDefaultDirName)
      if CompareText(WizardForm.DirEdit.Text, NoDirName) = 0 then
      begin
        WizardForm.DirEdit.Text := '';
      end;
    
      Dir := WizardForm.DirEdit.Text;
      // Defaulting to Steam
      // (either because Steam was found or previously installed to Steam)
      if CompareText(Dir, SteamDirName) = 0 then
        SteamButton.Checked := True
      // Defaulting to Epic
      // (either because Epic was found or previously installed to Epic)
      else if CompareText(Dir, EpicDirName) = 0 then
        EpicButton.Checked := True
      // Defaulting to Custom (either because neither Steam nor Epic was found or
      // previously installed to neither Steam nor Epic)
      else
        CustomButton.Checked := True;
    
      DirButtonClick(nil);
    end;
    

    enter image description here