Inno Setup当另一个任务被选中时,取消选中一个任务 [英] Inno Setup Uncheck a task when another task is checked
问题描述
我试图拦截WizardForm.TasksList.OnClickCheck
事件,以便在选择另一个任务时可以取消选中该任务.我知道通常在这种情况下会使用单选按钮,但是由于使用了多个分层任务,并且如果使用单选按钮,则您始终必须选择以下一项,因此在选择另一个任务时自动取消选中一个任务的效果更好在任务子树顶部时选择的两个.为了保持一致性,重新设计任务层次结构是不可行的,因为这将包括两个临时任务,这些临时任务将在安装程序的未来版本中删除.我写了以下代码来做到这一点:
I am trying to intercept the WizardForm.TasksList.OnClickCheck
event so that I can uncheck a task when another task is selected. I know that normally radio buttons would be used in this situation, but automatically unchecking one task when another is selected works better here due to the use of multiple hierarchical tasks and the fact that if radio buttons are used, you always have to have one of the two selected when at the top of the task subtree. Redesigning the task hierarchy is not feasible in order to maintain consistency, as this is to include two temporary tasks that will be removed in a future version of the installer. I have written the following to do this:
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;
但是,当我运行代码时,我得到:
However, when I run the code, I get an:
超出范围
单击任何复选框时出现
错误,突出显示DefaultTasksClickCheck(Sender);
作为违规行.如果我注释掉这一行,我将不再收到错误,但显然不再还原原始事件处理程序,并且它仍然无法正确检查和取消选中任务,而在选中Task1时无法选中Task36.我做错了什么?
error, when clicking any checkbox, with DefaultTasksClickCheck(Sender);
highlighted as the offending line. If I comment out this line, I no longer get the error, but am obviously no longer restoring the original event handler and it still doesn't check and uncheck the tasks correctly, with Task36 uncheckable when Task1 is checked. What have I done wrong?
推荐答案
-
WizardForm.TasksList.OnClickCheck
不是由Inno Setup本身分配的(与WizardForm.ComponentsList.OnClickCheck
相反),因此您不能调用它.
The
WizardForm.TasksList.OnClickCheck
is not assigned by the Inno Setup itself (contrary toWizardForm.ComponentsList.OnClickCheck
), so you cannot call it.
要解决此问题,请执行以下任一操作:
To fix the problem, either:
- 完全删除
DefaultTasksClickCheck
; - 或者如果希望在以后的Inno Setup版本中使用该事件以防万一,请在调用它之前检查它是否为
nil
.
- completely remove the
DefaultTasksClickCheck
; - or if you want to be covered in case the event starts being used in future versions of Inno Setup, check if it is
nil
before calling it.
您不知道最近在OnClickCheck
处理程序中检查了哪些任务.因此,您必须记住先前检查过的任务才能正确决定要取消选择的任务.
You cannot know what task was checked most recently in the OnClickCheck
handler. So you have to remember the previously checked task to correctly decide what task to unselect.
[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 6中,除了使用索引之外,您还可以使用 WizardSelectTasks
.例如,请参见 Inno设置:如果选择了另一个组件,如何自动选择一个组件?.
In Inno Setup 6, instead of using indexes, you can also use task names with use of WizardIsTaskSelected
and WizardSelectTasks
. For an example, see Inno Setup: how to auto select a component if another component is selected?.
有关检测已检查项目的更通用解决方案,请参见 Inno Setup在TasksList中检测已更改的任务/项目. OnClickCheck事件.
这篇关于Inno Setup当另一个任务被选中时,取消选中一个任务的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!