How to completely disable specific component in Inno Setup from code section?

3.3k Views Asked by At

I have an Inno-setup script with a components page with checkboxs and a combobox. I want to unchecked and disable some components from the Code section, I used this answer to do it and I have now this code :

[Setup]
AppName=My Program
AppVersion=1.5
DefaultDirName={pf}\My Program
DefaultGroupName=My Program
UninstallDisplayIcon={app}\MyProg.exe
OutputDir=userdocs:Inno Setup Examples Output

[Types]
Name: "full"; Description: "Full installation"
Name: "compact"; Description: "Compact installation"
Name: "custom"; Description: "Custom installation"; Flags: iscustom

[Components]
Name: "program"; Description: "Program Files"; Types: full compact custom; 
Name: "help"; Description: "Help File"; Types: full
Name: "readme"; Description: "Readme File"; Types: full
Name: "readme\en"; Description: "English"; Flags: exclusive
Name: "readme\de"; Description: "German"; Flags: exclusive

[code]
procedure CurPageChanged(CurPageID: Integer);
begin
  if CurPageID = wpSelectComponents then
    if (True) then  //Here my own condition instead of "(True)"
    begin
      WizardForm.ComponentsList.Checked[1] := False;
      WizardForm.ComponentsList.ItemEnabled[1] := False;
    end;
end;

Using this, the checkbox "help" is unchecked and disabled from the code but, even if the user can't click on the "help" checkbox to check it, he can still choose "Full installation" with the combobox which change the state of the "help" checkbox from unchecked to checked (even if the checkbox stay disabled).

What I would like to do, is completely disable this component and prevent the user from selecting it (without regarding on how the user is trying do it, from clicking it or from choosing "Full installation" in the combobox).

1

There are 1 best solutions below

3
On BEST ANSWER

Here is another, still hacky way to do what you want. I've used a different concept here. Essentially, it's about preparing an array of indices of components that should be disabled and unchecked (which I'm callling ghosted here) and calling UpdateGhostItems(False) which unchecks and disables the items of the indices from that prepared array in the component list.

From the installation type combo box change event is updated only check state that this combo box might change by calling UpdateGhostItems(True):

[Setup]
AppName=My Program
AppVersion=1.5
DefaultDirName={pf}\My Program

[Types]
Name: "full"; Description: "Full installation"
Name: "compact"; Description: "Compact installation"
Name: "custom"; Description: "Custom installation"; Flags: iscustom

[Components]
Name: "program"; Description: "Program Files"; Types: full compact custom; 
Name: "help"; Description: "Help File"; Types: full
Name: "readme"; Description: "Readme File"; Types: full
Name: "readme\en"; Description: "English"; Flags: exclusive
Name: "readme\de"; Description: "German"; Flags: exclusive

[Code]
var
  TypeChange: TNotifyEvent;
  GhostItems: array of Integer;

procedure UpdateGhostItems(CheckOnly: Boolean);
var
  I: Integer;
begin
  for I := 0 to GetArrayLength(GhostItems) - 1 do
  begin
    WizardForm.ComponentsList.Checked[GhostItems[I]] := False;
    if not CheckOnly then
      WizardForm.ComponentsList.ItemEnabled[GhostItems[I]] := False;
  end;
end;

procedure TypesComboChange(Sender: TObject);
begin
  // call the original event method
  TypeChange(Sender);
  // this will uncheck all the items from the GhostItems array;
  // this includes those that were checked by the above method
  // call; for GhostItems array description see below
  UpdateGhostItems(True);
end;

procedure InitializeWizard;
begin
  // store the original TypesCombo change event method
  TypeChange := WizardForm.TypesCombo.OnChange;
  // and assign it our interceptor
  WizardForm.TypesCombo.OnChange := @TypesComboChange;

  // the following code block is for setting ghosted components;
  // in real you might call it in some later stage of your setup

  // quite comfortable looks to me using array of indices of the
  // components that should remain always unchecked and disabled
  // I'm gonna prepare this array at the initialization but it's
  // really upon you when would you do so; so let's ghost 1 item
  SetArrayLength(GhostItems, 1);
  // ...with index 1
  GhostItems[0] := 1;
  // this call will uncheck and disable all the items from the
  // prepared GhostItems array; do note that this is a one way
  // road - once you disable a component, it won't get enabled
  // again (you would have to remember their previous state)
  UpdateGhostItems(False);
end;