2

How can I modify a InnoSetup installer to simplify it like this:

enter image description here

To display in a single wizard page the program directory selection, start menu group selection and desktop icon task, all in the same wizard page, very simplified and exquisite.

Can this be made using the built-in directives, or on the contrary I would need to use a custom pascal-script?. Any hints about how to achieve this, or maybe a reference to a full known sample?.

ElektroStudios
  • 19,105
  • 33
  • 200
  • 417
  • @Martin Prikryl Thanks, Your solution It is very helpful, now I'm aware I missed to take into consideration the tab order, and also to be honest I was struggling my head trying to figure out how to add the info properly (of the desktop shortcut) in the memo, and your answer has a nice example to do that. – ElektroStudios Mar 17 '23 at 17:05

2 Answers2

1

Writing such installer requires Pascal scripting, it not possible to achieve that using only directives.

My idea how to achieve this is: create a custom page with this design and "pass" the values from it to regular Inno pages, so you will not have to script everything.

Custom page can be shown as first, all other pages will be hidden, but the functionality will be done in those hidden pages so you save a lot of your work.

I want to mention: SO does not work this way, probably no one will write whole installer for you.

Start building the installer by yourself, you can find many of the "features" in various SO questions, for example:

To create a button on the bottom panel, see: How to create new About button in Inno Setup?

For background music, see: Playing sound during an Inno Setup install

Slappy
  • 5,250
  • 1
  • 23
  • 29
  • Thanks for your answer. Although I'm not interested in background music neither in adding a button in the bottom panel like FitGirl repack installers, I just would like to put / combine in a single wizard page the other controls / features that I mentioned. – ElektroStudios Mar 16 '23 at 03:03
  • I could create and design a new, custom page from scratch, but what I don't understand is, for example, how to assign (and how to use in first place) a folder dialog for the "Browse..." buttons and link those values in the way that this functionality will be done in those hidden pages as you said. I'm not understanding that. Could you please show (or link a reference) to a basic example of how to "pass" a value from it to regular Inno pages, so I will not have to script everything as you said?. Maybe seeying a simple example I could figure how to replicate it for the rest of controls. – ElektroStudios Mar 16 '23 at 03:03
  • Maybe what I'm really requesting is if you could show a basic example of how it would be your custom wizard page (just a custom wizard page with a single button or so, is that what I mean with "a basic example", I'm not requesting the full installer source-code but at least a demonstrative, not necessarily a functional example, for how to achieve this for one single control from the many controls that requires it) and how you will "pass" the value from it to regular Inno pages. Could you?. – ElektroStudios Mar 16 '23 at 03:06
  • Doesn't matter now, I've finally figured out how to achieve it. Thanks for your answer!. – ElektroStudios Mar 16 '23 at 13:04
0

I just did it, partially thanks to ChatGPT for giving me tips and code examples at related syntax and usage questions that I had while I was trying to figure out how to achieve this in a simple way (that is, avoiding to declare and set up all of the controls by myself). And of course, thanks to the Support Classes Reference which helped me more than the AI.

It was very tedious to analyze all the docs and code examples, but at the end it was more easy to put all this in practice than what I thought at first sight.

Note that maybe the control-positioning is not perfect because I'm not sure how to use "ScaleX" "ScaleY" properly, but hey, it seems to work fine for me with my screen DPI.

Here we go:

[Code]
Var
  CustomSelectDirPage: TWizardPage;

...

function IsCreateDesktopIconChecked(): Boolean;
var
  DesktopShortcutCheckBox: TNewCheckBox;
  Page: TWizardPage;
begin
  Page := PageFromID(CustomSelectDirPage.ID);
  DesktopShortcutCheckBox := TNewCheckBox(Page.Surface.Controls[12])
  Result := DesktopShortcutCheckBox.Checked;
end;

function CustomSelectDirPageNextButtonClick(Sender: TWizardPage): Boolean;
var
  DirExistsWarning: String;
  FDirEdit: TEdit;
begin
  Result := True;
  FDirEdit := TEdit(Sender.Surface.Controls[4]);
  DirExistsWarning := LowerCase('{#SetupSetting("DirExistsWarning")}'); //  "auto", "true" or "false"
  if (DirExistsWarning = 'true') and (DirExists(ExpandConstant(FDirEdit.Text)))  then
  begin
   if MsgBox('The Folder:' + #13#10#13#10 + ExpandConstant(FDirEdit.Text) + #13#10#13#10 +
             'already exists. Would you like to install to that folder anyway?', mbConfirmation, MB_YESNO) = IDNO then
    Result := false;
  end;
end;

procedure CreateCustomSelectDirPage();
var
  WizardStyle: String;

  // Pages
  ThisPage: TWizardPage;
  SelectDirPage: TWizardPage;
  SelectProgramGroupPage: TWizardPage;

  // Custom Controls
  DesktopShortcutCheckBox: TNewCheckBox;

  // wpSelectDir Controls
  FSelectDirBitmapImage: TBitmapImage;
  FDiskSpaceLabel: TNewStaticText;
  FDirBrowseButton: TButton;
  FDirEdit: TEdit;
  FSelectDirBrowseLabel: TNewStaticText;
  FSelectDirLabel: TNewStaticText;

  // wpSelectProgramGroup Controls
  FSelectGroupBitmapImage: TBitmapImage;
  FNoIconsCheck: TCheckBox;
  FGroupBrowseButton: TButton;
  FGroupEdit: TEdit;
  FSelectStartMenuFolderBrowseLabel: TNewStaticText;
  FSelectStartMenuFolderLabel: TNewStaticText;
begin
  WizardStyle := LowerCase('{#SetupSetting("WizardStyle")}'); //  "classic" or "modern"

  // Pages
  SelectDirPage          := PageFromID(wpSelectDir);
  SelectProgramGroupPage := PageFromID(wpSelectProgramGroup);
  ThisPage               := CreateCustomPage(wpInfoBefore, SelectDirPage.Caption + ' | ' + SelectProgramGroupPage.Caption,
                                                           SelectDirPage.Description + #13#10 + SelectProgramGroupPage.Description);
  CustomSelectDirPage := ThisPage

  // wpSelectDir Control References
  FSelectDirBitmapImage := TBitmapImage(SelectDirPage.Surface.Controls[0]);
  FDiskSpaceLabel       := TNewStaticText(SelectDirPage.Surface.Controls[1]);
  FDirBrowseButton      := TButton(SelectDirPage.Surface.Controls[2]);
  FDirEdit              := TEdit(SelectDirPage.Surface.Controls[3]);
  FSelectDirBrowseLabel := TNewStaticText(SelectDirPage.Surface.Controls[4]);
  FSelectDirLabel       := TNewStaticText(SelectDirPage.Surface.Controls[5]);

  // wpSelectDir Control Parenting
  FSelectDirBitmapImage.Parent := ThisPage.Surface;
  FDiskSpaceLabel.Parent       := ThisPage.Surface;
  FDirBrowseButton.Parent      := ThisPage.Surface;
  FDirEdit.Parent              := ThisPage.Surface;
  FSelectDirBrowseLabel.Parent := ThisPage.Surface;
  FSelectDirLabel.Parent       := ThisPage.Surface;

  // wpSelectDir Control Positioning
  if WizardStyle = 'classic' then
  begin
    FSelectDirBrowseLabel.Visible := False;
    FDirEdit.Top := FSelectDirLabel.Top + 30;
    FDirBrowseButton.Top := FDirEdit.Top;
  end;

  // wpSelectProgramGroup Control References
  FSelectGroupBitmapImage           := TBitmapImage(PageFromID(wpSelectProgramGroup).Surface.Controls[0])
  FNoIconsCheck                     := TCheckBox(PageFromID(wpSelectProgramGroup).Surface.Controls[1])
  FGroupBrowseButton                := TButton(PageFromID(wpSelectProgramGroup).Surface.Controls[2])
  FGroupEdit                        := TEdit(PageFromID(wpSelectProgramGroup).Surface.Controls[3])
  FSelectStartMenuFolderBrowseLabel := TNewStaticText(PageFromID(wpSelectProgramGroup).Surface.Controls[4])
  FSelectStartMenuFolderLabel       := TNewStaticText(PageFromID(wpSelectProgramGroup).Surface.Controls[5])

  // wpSelectProgramGroup Control Parenting
  FSelectGroupBitmapImage.Parent           := ThisPage.Surface;
  FSelectStartMenuFolderLabel.Parent       := ThisPage.Surface;
  FSelectStartMenuFolderBrowseLabel.Parent := ThisPage.Surface;
  FGroupEdit.Parent                        := ThisPage.Surface;
  FGroupBrowseButton.Parent                := ThisPage.Surface;
  FNoIconsCheck.Parent                     := ThisPage.Surface;

  // wpSelectProgramGroup Control Positioning
  if WizardStyle = 'modern' then
  begin
    FSelectGroupBitmapImage.Top           := FDirEdit.Top + 70;
    FSelectStartMenuFolderLabel.Top       := FSelectGroupBitmapImage.Top + 10;
    FSelectStartMenuFolderBrowseLabel.Top := FSelectStartMenuFolderLabel.Top + 35;
    FGroupEdit.Top                        := FSelectStartMenuFolderBrowseLabel.Top + 20;
    FGroupBrowseButton.Top                := FGroupEdit.Top;
    FNoIconsCheck.Top                     := FGroupEdit.Top - 42;
  end
  else
  begin
    FSelectStartMenuFolderBrowseLabel.Visible := False;
    FSelectGroupBitmapImage.Top           := FDirEdit.Top + 70;
    FSelectStartMenuFolderLabel.Top       := FSelectGroupBitmapImage.Top + 10;
    FGroupEdit.Top                        := FSelectStartMenuFolderLabel.Top + 30;
    FGroupBrowseButton.Top                := FGroupEdit.Top;
    FNoIconsCheck.Top                     := FGroupEdit.Top + 28;
  end;

  // Custom Controls
  DesktopShortcutCheckBox            := TNewCheckBox.Create(ThisPage);
  DesktopShortcutCheckBox.Parent     := ThisPage.Surface;
  DesktopShortcutCheckBox.Top        := FDirEdit.Top + 30;
  DesktopShortcutCheckBox.Caption    := CustomMessage('CreateDesktopIcon');
  DesktopShortcutCheckBox.Checked    := True;
  DesktopShortcutCheckBox.Width      := FNoIconsCheck.Width;

  ThisPage.OnNextButtonClick := @CustomSelectDirPageNextButtonClick;

end;

Note that you should set these directives like this:

DisableDirPage=True
DisableProgramGroupPage=True

And this is the resulting custom wizard page. It even looks better than FitGirl installers (without considering the missing additional buttons on the bottom bar in comparison):

enter image description here

UPDATE 1

I've updated the code above to also make it work properly on classic setup mode (WizardStyle=Classic), this is the resulting visual aspect:

enter image description here

UPDATE 2

I've updated again the code above to implement the functionality of the "Create a desktop shortcut" checkbox, and also to react to the DirExistsWarning directive setting in the custom wizard page.


ElektroStudios
  • 19,105
  • 33
  • 200
  • 417