如何从代码部分完全禁用 Inno Setup 中的特定组件?

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

我有一个 Inno-setup 脚本,其中包含一个带有复选框和组合框的组件页面。我想取消选中并禁用“代码”部分中的某些组件,我使用 this answer 来做到这一点,现在我有了这段代码:

[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;

使用这个,复选框“帮助”被取消选中并从代码中禁用,但是,即使用户不能点击“帮助”复选框来选中它,他仍然可以选择“完全安装”将“帮助”复选框的状态从未选中更改为选中的组合框(即使该复选框保持禁用状态)。

我想做的是完全禁用此组件并阻止用户选择它(不考虑用户如何尝试这样做,通过单击它或在组合框中选择“完全安装”) .

这是另一种仍然很老套的方法来做你想做的事。我在这里使用了不同的概念。本质上,它是关于准备一组应该被禁用和取消选中的组件索引(我在这里调用 ghosted)并调用 UpdateGhostItems(False) 取消选中和禁用的项目组件列表中准备好的数组的索引。

从安装类型组合框更改事件更新仅检查此组合框可能通过调用 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;