You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Inno Setup中TNewCheckListBox选中状态不更新问题求助

问题原因分析

你的代码问题出在页面创建时机:PortSelectionPage 在 InitializeWizard 中执行,此时配置页面刚被创建,用户还没有机会勾选任何选项,ListBox.Checked 数组全是初始的 False,所以 SelectedConfigs 自然不会被填充。

之前放在 CurStepChanged 中能正常工作,是因为该事件是在安装步骤切换时触发,此时用户已经完成了配置页面的选择操作。

解决方案

需要把读取复选框选中状态的逻辑,移到用户完成配置页面操作之后执行,推荐两种实现方式:

方式一:绑定配置页面的「Next按钮点击事件」

当用户在配置页面勾选完选项,点击Next按钮时,立即读取选中状态并更新 SelectedConfigs 数组。

修改后的完整代码

var
  ListBox:         TNewCheckListBox;
  SelectedConfigs: array of Integer;
  ConfigPage:      TWizardPage; // 全局变量保存配置页面对象

function ConfigurationPage(): TWizardPage;
var
  I:    Integer;
begin
  Result := CreateCustomPage(wpSelectComponents, 'Select Configuration', 
    'Please select the configuration you would like to install to.');
  ConfigPage := Result; // 保存配置页面到全局变量

  ListBox := TNewCheckListBox.Create(Result);
  ListBox.Parent := Result.Surface;
  ListBox.Left := ScaleX(0);
  ListBox.Top := ScaleY(0);
  ListBox.Width := Result.SurfaceWidth;
  ListBox.Height := Result.SurfaceHeight;
  ListBox.BorderStyle := bsNone;

  for I := 0 to GetArrayLength(ConfigurationNames) - 1 do
  begin
    ListBox.AddCheckBox(
      ConfigurationNames[I], '', 0, False, True, False, False, nil);
  end;

  ListBox.ItemIndex := 0;
end;

// 配置页面Next按钮点击事件处理函数
procedure ConfigPageNextButtonClick(Sender: TWizardPage; var Cancel: Boolean);
var
  I: Integer;
  ArrayLength: Integer;
begin
  // 清空之前的选中记录
  SetArrayLength(SelectedConfigs, 0);
  
  for I := 0 to ListBox.Items.Count - 1 do
  begin
    Log(Format('ListBox[%d], %s is checked? %d', [
      I, ListBox.Items[I], ListBox.Checked[I]]));
    if ListBox.Checked[I] then
    begin
      ArrayLength := GetArrayLength(SelectedConfigs);
      SetArrayLength(SelectedConfigs, ArrayLength + 1);
      SelectedConfigs[ArrayLength] := I;
      Log(Format('Config %d was selected...', [I]));
    end;
  end;
end;

procedure InitializeWizard;
var                         
  PortPage: TWizardPage;
begin
  ConfigPage := ConfigurationPage;
  // 绑定Next按钮点击事件
  ConfigPage.OnNextButtonClick := @ConfigPageNextButtonClick;
  
  // 创建端口选择页面(仅负责页面创建,不处理选中逻辑)
  PortPage := CreateCustomPage(ConfigPage.ID, 'Select Port', 
    'Please select the port you want the configurations to receive on.');
end;

方式二:使用CurPageChanged事件

当用户切换到端口选择页面时,读取配置页面的选中状态,这种方式适合需要在端口页面加载前准备数据的场景。

核心代码添加

在原代码基础上,新增 CurPageChanged 事件处理:

var
  ListBox:         TNewCheckListBox;
  SelectedConfigs: array of Integer;
  ConfigPage:      TWizardPage;
  PortPage:        TWizardPage;

// ... 保留原ConfigurationPage函数 ...

procedure InitializeWizard;
begin
  ConfigPage := ConfigurationPage;
  PortPage := CreateCustomPage(ConfigPage.ID, 'Select Port', 
    'Please select the port you want the configurations to receive on.');
end;

// 页面切换事件处理
procedure CurPageChanged(CurPageID: Integer);
var
  I: Integer;
  ArrayLength: Integer;
begin
  // 当用户进入端口页面时,读取配置页面的选中项
  if CurPageID = PortPage.ID then
  begin
    SetArrayLength(SelectedConfigs, 0);
    for I := 0 to ListBox.Items.Count - 1 do
    begin
      Log(Format('ListBox[%d], %s is checked? %d', [
        I, ListBox.Items[I], ListBox.Checked[I]]));
      if ListBox.Checked[I] then
      begin
        ArrayLength := GetArrayLength(SelectedConfigs);
        SetArrayLength(SelectedConfigs, ArrayLength + 1);
        SelectedConfigs[ArrayLength] := I;
        Log(Format('Config %d was selected...', [I]));
      end;
    end;
  end;
end;
关键注意点
  • 页面创建阶段(InitializeWizard)仅负责创建UI控件,不要在这个阶段读取用户交互后的状态,此时用户还未操作任何控件。
  • 所有需要获取用户选择的逻辑,都要放在用户完成对应页面操作的事件中触发(如按钮点击、页面切换)。

内容的提问来源于stack exchange,提问作者Woody1193

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.31 04:09:29