3

I've the following code (taken from Use two/multiple selected directories from custom page in Files section):

[Code]
var
  DirPage: TInputDirWizardPage;

function GetDir(Param: String): String;
begin
  Result := DirPage.Values[StrToInt(Param)];
end;

procedure InitializeWizard;
var
  S1, S2: String; 
begin
  S1 := SetupMessage(msgSelectDirDesc);
  StringChangeEx(S1, '[name]', 'ProgramName', false);
  S2 := SetupMessage(msgSelectDirLabel3);
  StringChangeEx(S2, '[name]', 'ProgramName', false);

  { create a directory input page }
  DirPage := CreateInputDirPage(
    wpSelectDir, SetupMessage(msgWizardSelectDir), S1, S2, False, '');
  { add directory input page items }
  DirPage.Add('Path to Apache:');
  DirPage.Add('Path to PHP:');
  DirPage.Add('Path to Server Files:');
  { assign default directories for the items from the previously stored data; if }
  { there are no data stored from the previous installation, use default folders }
  { of your choice }
  DirPage.Values[0] := GetPreviousData('Directory1', 'C:\Apache');
  DirPage.Values[1] := GetPreviousData('Directory2', 'C:\PHP');
  DirPage.Values[2] := GetPreviousData('Directory3', 'C:\Apache\htdocs\Server Files');
end;

procedure RegisterPreviousData(PreviousDataKey: Integer);
begin
  { store chosen directories for the next run of the setup }
  SetPreviousData(PreviousDataKey, 'Directory1', DirPage.Values[0]);
  SetPreviousData(PreviousDataKey, 'Directory2', DirPage.Values[1]);
  SetPreviousData(PreviousDataKey, 'Directory3', DirPage.Values[2]);
end; 

I'd like to make this behave like the traditional folder select page, so when selecting a folder, Inno Setup should keep the default folder name unless manually overwritten by the user. I.e.: if I select the folder "C:\Program Files\" it should keep the original folder like "C:\Program Files\PHP" or "C:\Program Files\Apache". Is this possible?

Martin Prikryl
  • 188,800
  • 56
  • 490
  • 992
Steve
  • 2,510
  • 4
  • 34
  • 53

2 Answers2

3

To get the default behavior of Browse button on "Select Destination Location" (triggered by AppendDefaultDirName directive), for Browse buttons on your custom page, set these parameters of CreateInputDirPage:

  • AAppendDir to True
  • ANewFolderName to the "default folder name"

The problem is, that this affects all input boxes/buttons. While you want to affect only the first input box/button (or you want a different ANewFolderName for each box/button).


To modify a behavior of some box only, you have to reimplement their functionality from the scratch. Though the browse dialog functionality is not exposed. There's only BrowseForFolder function, which is slightly different.

var
  DirPage: TInputDirWizardPage;

procedure NormalBrowseClick(Sender: TObject);
var
  Directory: string;
begin
  Directory := DirPage.Values[TButton(Sender).Tag];
  if BrowseForFolder(SetupMessage(msgWizardSelectDir), Directory, False) then
  begin
    DirPage.Values[TButton(Sender).Tag] := Directory;
  end;
end;

procedure InitializeWizard();
begin
  DirPage := CreateInputDirPage(
    wpSelectDir, SetupMessage(msgWizardSelectDir), '', '', True, 'Apache');
  { add directory input page items }
  DirPage.Add('Path to Apache:');
  DirPage.Add('Path to PHP:');
  DirPage.Add('Path to Server Files:');

  DirPage.Buttons[1].Tag := 1;
  DirPage.Buttons[1].OnClick := @NormalBrowseClick;
  DirPage.Buttons[2].Tag := 2;
  DirPage.Buttons[2].OnClick := @NormalBrowseClick;
  { assign default directories for the items from the previously stored data; if }
  { there are no data stored from the previous installation, use default folders }
  { of your choice }
  DirPage.Values[0] := GetPreviousData('Directory1', 'C:\Apache');
  DirPage.Values[1] := GetPreviousData('Directory2', 'C:\PHP');
  DirPage.Values[2] := GetPreviousData('Directory3', 'C:\Apache\htdocs\Server Files');
end;

To get the exact behaviour with the same "browse" dialog, you can hack it be invoking a functionality of the hidden "Select Destination Location" page or of another hidden TInputDirWizardPage with different settings of AAppendDir:

var
  DirPage: TInputDirWizardPage;
  HiddenPage: TInputDirWizardPage;

procedure AppendDirBrowseClick(Sender: TObject);
begin
  HiddenPage.Values[0] := DirPage.Values[0];
  HiddenPage.Buttons[0].OnClick(HiddenPage.Buttons[0]);
  DirPage.Values[0] := HiddenPage.Values[0];
end;

function SkipPage(Sender: TWizardPage): Boolean;
begin
  Result := True;
end;

procedure InitializeWizard();
begin
  DirPage := CreateInputDirPage(
    wpSelectDir, SetupMessage(msgWizardSelectDir), '', '', False, '');

  DirPage.Add('Path to Apache:');
  DirPage.Add('Path to PHP:');
  DirPage.Add('Path to Server Files:');

  { assign default directories for the items from the previously stored data; if }
  { there are no data stored from the previous installation, use default folders }
  { of your choice }
  DirPage.Values[0] := GetPreviousData('Directory1', 'C:\Apache');
  DirPage.Values[1] := GetPreviousData('Directory2', 'C:\PHP');
  DirPage.Values[2] := GetPreviousData('Directory3', 'C:\Apache\htdocs\Server Files');

  DirPage.Buttons[0].OnClick := @AppendDirBrowseClick;

  HiddenPage := CreateInputDirPage(
    wpSelectDir, SetupMessage(msgWizardSelectDir), '', '', True, 'Apache');
  HiddenPage.Add('');
  HiddenPage.OnShouldSkipPage := @SkipPage;
end;

The code needs Unicode version of Inno Setup. Calling HiddenPage.Buttons[0].OnClick strangely does not work in Ansi version.

Martin Prikryl
  • 188,800
  • 56
  • 490
  • 992
  • So am I wrong in assuming that *"you want to affect only the first input box/button"*? Then use the trivial solution suggested in the first section. – Martin Prikryl Dec 17 '18 at 19:49
  • I'd like to affect each button with it's specific directory. Button1 should add "Apache", Button2 "PHP", Button3 "Server Files" to the path that is browsed. So I can't use the first code sample (or I couldn't figure out how to customize it). – Steve Dec 17 '18 at 20:23
  • OK, I see. So you can use the code from the third section. Just that you need to create two hidden pages, each with `AAppendDir = True` and different settings of `ANewFolderName`. – Martin Prikryl Dec 18 '18 at 07:40
  • 1
    This works, I've posted an answer with the final code. – Steve Jan 03 '19 at 12:10
2

For future reference, here is the full working code based on Martin's answer. Make sure to add "DisableDirPage=yes" to the [Setup] section.

Note: Due to a bug, the code below works only in the unicode version of InnoSetup.

[Code]
var
  DirPage: TInputDirWizardPage;
  HiddenPage: TInputDirWizardPage;
  HiddenPage2: TInputDirWizardPage;
  HiddenPage3: TInputDirWizardPage;

procedure AppendDirBrowseClick(Sender: TObject);
begin
  HiddenPage.Values[0] := DirPage.Values[0];
  HiddenPage.Buttons[0].OnClick(HiddenPage.Buttons[0]);
  DirPage.Values[0] := HiddenPage.Values[0];
end;

procedure AppendDirBrowseClick2(Sender: TObject);
begin
  HiddenPage2.Values[0] := DirPage.Values[1];
  HiddenPage2.Buttons[0].OnClick(HiddenPage2.Buttons[0]);
  DirPage.Values[1] := HiddenPage2.Values[0];
end;

procedure AppendDirBrowseClick3(Sender: TObject);
begin
  HiddenPage3.Values[0] := DirPage.Values[2];
  HiddenPage3.Buttons[0].OnClick(HiddenPage3.Buttons[0]);
  DirPage.Values[2] := HiddenPage3.Values[0];
end;

function SkipPage(Sender: TWizardPage): Boolean;
begin
  Result := True;
end;

procedure InitializeWizard();
begin
  DirPage := CreateInputDirPage(
    wpSelectDir, SetupMessage(msgWizardSelectDir), '', '', False, '');

  DirPage.Add('Path to Apache:');
  DirPage.Add('Path to PHP:');
  DirPage.Add('Path to Server Files:');

  { assign default directories for the items from the previously stored data; if }
  { there are no data stored from the previous installation, use default folders }
  { of your choice }
  DirPage.Values[0] := GetPreviousData('Directory1', 'C:\Apache');
  DirPage.Values[1] := GetPreviousData('Directory2', 'C:\PHP');
  DirPage.Values[2] := GetPreviousData('Directory3', 'C:\Apache\htdocs\Server Files');

  DirPage.Buttons[0].OnClick := @AppendDirBrowseClick;
  DirPage.Buttons[1].OnClick := @AppendDirBrowseClick2;
  DirPage.Buttons[2].OnClick := @AppendDirBrowseClick3;

  HiddenPage := CreateInputDirPage(
    wpSelectDir, SetupMessage(msgWizardSelectDir), '', '', True, 'Apache');
  HiddenPage.Add('');
  HiddenPage.OnShouldSkipPage := @SkipPage;

  HiddenPage2 := CreateInputDirPage(
    wpSelectDir, SetupMessage(msgWizardSelectDir), '', '', True, 'PHP');
  HiddenPage2.Add('');
  HiddenPage2.OnShouldSkipPage := @SkipPage;

  HiddenPage3 := CreateInputDirPage(
    wpSelectDir, SetupMessage(msgWizardSelectDir), '', '', True, 'Server Files');
  HiddenPage3.Add('');
  HiddenPage3.OnShouldSkipPage := @SkipPage;
end;
Steve
  • 2,510
  • 4
  • 34
  • 53