19

In a prior question I asked how to have three optional components, where the user could also specify the locations for each component separately (e.g. a code part and two HTML web applications). @Miral gave me a great answer which I have now implemented:
three components in three user defined locations

I have a small esthetic issue remaining. I am always creating and asking the user for a CreateInputDirPage, in the wizard. The question comes after the wpSelectComponents.

Question: How do I skip the page if the component was not selected. That is, how do I skip my custom page?

I have a feeling it has to do with ShouldSkipPage(). But I have no idea what the PageID for my custom page is, and how to test to see what components were selected.

function ShouldSkipPage(PageID: Integer): Boolean;

The wizard calls this event function to determine whether or not a particular page (specified by PageID) should be shown at all. If you return True, the page will be skipped; if you return False, the page may be shown.

My script is enclosed below:

[Components]
Name: "Watson"; Description: "Watson Component"; Types: onlywatson full
Name: "Toby"; Description: "Toby Component"; Types: onlytoby full
Name: "Sherlock"; Description: "Sherlock Component"; Types: onlysherlock full

[Code]
var 
    TobyDirPage: TInputDirWizardPage;
    SherlockDirPage: TInputDirWizardPage;

procedure InitializeWizard;
begin
  TobyDirPage := CreateInputDirPage(wpSelectComponents,
    'Select Location for Toby Web Pages', 'Where should we store the sample Toby application files?',
    'The sample Toby stand-alone map application will be saved in the following folder.'#13#10#13#10 +
    'To continue, click Next. If you would like to select a different folder, click Browse.',
    False, 'New Folder');
  { Add item (with an empty caption) }
  TobyDirPage.Add('');
  { Set initial value (optional) }
  TobyDirPage.Values[0] := ExpandConstant('c:\wwwroot\Toby');
  
  SherlockDirPage := CreateInputDirPage(wpSelectComponents,
    'Select Location for Sherlock Web Pages', 'Where should we store the Sherlock Catalog Search Tool?',
    'Sherlock.html and it'#39 + 's associated files will be saved in the following folder.'#13#10#13#10 +
    'To continue, click Next. If you would like to select a different folder, click Browse.',
    False, 'New Folder');
  { Add item (with an empty caption) }
  SherlockDirPage.Add('');
  { Set initial value (optional) }
  SherlockDirPage.Values[0] := ExpandConstant('c:\wwwroot\Sherlock');
end;

function GetTobyDir(Param: String): String;
begin
  { Return the selected TobyDir }
  Result := TobyDirPage.Values[0];
end;

function GetSherlockDir(Param: String): String;
begin
  { Return the selected TobyDir }
  Result := SherlockDirPage.Values[0];
end;
Community
  • 1
  • 1
Dr.YSG
  • 7,171
  • 22
  • 81
  • 139

2 Answers2

29

As you correctly forefelt, you need to use the ShouldSkipPage event handler to conditionally skip the page. To check if a certain component is selected use the IsComponentSelected function and finally, to get ID of your custom page you need to store its ID. Putting all together might give you the following example script:

[Setup]
AppName=My Program
AppVersion=1.5
DefaultDirName={pf}\My Program
OutputDir=userdocs:Inno Setup Examples Output

[Components]
Name: "help"; Description: "Help File";

[Code]
var
  CustomPageID: Integer;

procedure InitializeWizard;
var
  CustomPage: TInputDirWizardPage;
begin
  CustomPage := CreateInputDirPage(wpSelectComponents, 'Caption', 
    'Description', 'SubCaption', False, 'NewFolderName');
  CustomPage.Add('Input');
  { store your custom page ID to further use in the ShouldSkipPage event }
  CustomPageID := CustomPage.ID;
end;

function ShouldSkipPage(PageID: Integer): Boolean;
begin
  { initialize result to not skip any page (not necessary, but safer) }
  Result := False;
  { if the page that is asked to be skipped is your custom page, then... }
  if PageID = CustomPageID then
    { if the component is not selected, skip the page }
    Result := not IsComponentSelected('help');
end;
Martin Prikryl
  • 188,800
  • 56
  • 490
  • 992
TLama
  • 75,147
  • 17
  • 214
  • 392
  • 1
    I think it is THE answer, but I have been busy today, and I want to test it out. But to me, it looks thorough and well explained. Thank you. – Dr.YSG Dec 18 '12 at 22:36
  • 1
    You're welcome! If you'd need any help related to this question, don't hesitate to drop a comment here ;-) – TLama Dec 18 '12 at 22:40
  • 1
    thanks for the answer. If I choose to not check that component, the page is really not shown as expected, but if I first choose the component, see the custom page and then go back to the components selection and change my choice - uncheck that component, the custom page is appears... is there a way to avoid this? – one Aug 31 '14 at 12:02
  • 1
    @one, that should not happen. Could you share a minimalistic script in which this would be reproducable ? – TLama Aug 31 '14 at 12:07
  • 3
    @TLama: He keeps Wizard page objects already so there's no need in caching their ID's as well. The check in ShouldSkipPage will look like `if (PageID = TobyDirPage.ID) then ... else if (PageID = SherlockDirPage.ID) then ...` – Fr0sT Oct 24 '14 at 12:32
  • In InnoSetup 6, the function is [`WizardIsComponentSelected`](http://www.jrsoftware.org/ishelp/topic_isxfunc_wizardiscomponentselected.htm). – Matthieu Oct 09 '19 at 12:38
6

My take on this is to use the TWizardPageShouldSkipEvent, I've made only a case-and-point script:

[Code]
var 
    TobyDirPage: TInputDirWizardPage;

function SkipEvent (Sender: TWizardPage): Boolean;
begin
    Result := not IsComponentSelected('Toby');
end; 

procedure InitializeWizard;
begin
    TobyDirPage := CreateInputDirPage(wpSelectComponents, yadda yadda yadda
    TobyDirPage.OnShouldSkipPage := @SkipEvent;
end;

Now, OnShouldSkipPage fires right after pressing Next on wpSelectComponents and before TobyDirPage gets painted and since you can attach that event to the page itself you don't need to fiddle with PageID's.

JasonXA
  • 268
  • 3
  • 6