Inno Setup在选中其他任务时取消选中任务

时间:2016-09-02 16:32:07

标签: inno-setup pascalscript

我正在尝试拦截WizardForm.TasksList.OnClickCheck事件,以便在选择其他任务时取消选中任务。我知道通常在这种情况下使用单选按钮,但是当选择另一个任务时自动取消选中一个任务在这里工作得更好,因为使用了多个分层任务,而且如果使用了单选按钮,你总是必须有一个在任务子树的顶部选择两个。重新设计任务层次结构是不可行的,以保持一致性,因为这包括将在未来版本的安装程序中删除的两个临时任务。我写了以下内容来做到这一点:

var
  DefaultTasksClickCheck: TNotifyEvent;

{ Uncheck tasks based on what other tasks are selected }
procedure UpdateTasks();
var
  intIndex: Integer;
begin
  with WizardForm.TasksList do
    begin
      if IsTaskSelected('Task1') then
        begin
          intIndex := WizardForm.TasksList.Items.IndexOf('Task36 Description');
          CheckItem(intIndex, coUncheck);
        end;
      if IsTaskSelected('Task36') then
        begin
          intIndex := WizardForm.TasksList.Items.IndexOf('Task1 Description');
          CheckItem(intIndex, coUncheck);
        end;
    end;
end;

{ Update the task states if the task states change and restore the original event handler procedure }
procedure TasksClickCheck(Sender: TObject);
begin
  DefaultTasksClickCheck(Sender);
  UpdateTasks;
end;

procedure InitializeWizard();
begin
  { Store the original Tasks Page OnClickCheck event procedure and assign custom procedure }
  DefaultTasksClickCheck := WizardForm.TasksList.OnClickCheck;
  WizardForm.TasksList.OnClickCheck := @TasksClickCheck;
end;

然而,当我运行代码时,我得到了一个:

  

超出Proc范围

错误,点击任意复选框时,DefaultTasksClickCheck(Sender);突出显示为违规行。如果我注释掉这一行,我不再收到错误,但显然不再恢复原始事件处理程序,它仍然没有正确检查和取消选中任务,当Task1被选中时,Task36取消选中。我做错了什么?

1 个答案:

答案 0 :(得分:2)

  1. Inno设置本身未分配WizardForm.TasksList.OnClickCheck(与WizardForm.ComponentsList.OnClickCheck相反),因此您无法调用它。

    要解决此问题,请执行以下操作:

    • 完全删除DefaultTasksClickCheck;
    • 或者如果您想要在Inno Setup的未来版本中开始使用该事件,请在调用之前检查它是否为nil
  2. 您无法知道OnClickCheck处理程序中最近检查的任务。因此,您必须记住先前检查过的任务,以正确决定要取消选择的任务。

  3. [Tasks]
    Name: Task1; Description: "Task1 Description"
    Name: Task36; Description: "Task36 Description"; Flags: unchecked
    
    [Code]
    
    var
      DefaultTasksClickCheck: TNotifyEvent;
      Task1Selected: Boolean;
    
    procedure UpdateTasks;
    var
      Index: Integer;
    begin
      { Task1 was just checked, uncheck Task36 }
      if (not Task1Selected) and IsTaskSelected('Task1') then
      begin
        Index := WizardForm.TasksList.Items.IndexOf('Task36 Description');
        WizardForm.TasksList.CheckItem(Index, coUncheck);
        Task1Selected := True;
      end
        else 
      { Task36 was just checked, uncheck Task1 }
      if Task1Selected and IsTaskSelected('Task36') then
      begin
        Index := WizardForm.TasksList.Items.IndexOf('Task1 Description');
        WizardForm.TasksList.CheckItem(Index, coUncheck);
        Task1Selected := False;
      end;
    end;
    
    procedure TasksClickCheck(Sender: TObject);
    begin
      if DefaultTasksClickCheck <> nil then
        DefaultTasksClickCheck(Sender);
      UpdateTasks;
    end;
    
    procedure CurPageChanged(CurPageID: Integer);
    begin
      if CurPageID = wpSelectTasks then
      begin
        { Only now is the task list initialized, check what is the current state }
        { This is particularly important during upgrades, }
        { when the task does not have its default state }
        Task1Selected := IsTaskSelected('Task1');
      end;
    end;
    
    procedure InitializeWizard();
    begin
      DefaultTasksClickCheck := WizardForm.TasksList.OnClickCheck;
      WizardForm.TasksList.OnClickCheck := @TasksClickCheck;
    end;
    

    有关检测已检查项目的更通用解决方案,请参阅Inno Setup Detect changed task/item in TasksList.OnClickCheck event

相关问题