How to build a Treeview design (a task group with

2019-01-26 02:41发布

问题:

I'm trying to build a Treeview hierarchy of checkable elements and labels that must be more or less like this:

Standalone Controls (label, root)
|__Check/Uncheck all controls of all groups (checkbox)
|  |
|  |__Controls group 1 (group description label)
|  |  |__Check/Uncheck all these controls (checkbox)
|  |     |__Control name 1 (task)
|  |     |__Control name 2 (task)
|  |     |__Control name 3 (task)
|  |       
|  |__Controls group 2 (group description label)
|  |  |__Check/Uncheck all these controls (checkbox)
|  |     |__Control name 1 (task)
|  |     |__Control name 2 (task)
|  |     |__Control name 3 (task)

...and so on.

Or this variant below in case of the hierarchy shown above could be too hard to code it:

Standalone Controls (label, root)
|
|__Controls group 1 (group description label)
|  |__Check/Uncheck all these controls (checkbox)
|     |__Control name 1 (task)
|     |__Control name 2 (task)
|     |__Control name 3 (task)
|       
|__Controls group 2 (group description label)
|  |__Check/Uncheck all these controls (checkbox)
|     |__Control name 1 (task)
|     |__Control name 2 (task)
|     |__Control name 3 (task)

However, what I got so far is this:

This is a sample of the code I have:

[CustomMessages]
StandaloneDescr=%nStandalone Controls
ButtonsDescr=%nButtons
CheckboxesDescr=%nCheckboxes
GroupboxesDescr=%nGroupboxes
KnobsDescr=%nKnobs
...

[Tasks]
Name: WinFormsControls; Description: Check/Uncheck all; GroupDescription: {cm:StandaloneDescr}

Name: WinFormsControls; Description: Check/Uncheck all; GroupDescription: {cm:ButtonsDescr}
Name: WinFormsControls\CButton; Description: CButton
Name: WinFormsControls\GlassButton; Description: Glass Button
Name: WinFormsControls\MyCommandButtonNET; Description: My Command Button.NET
Name: WinFormsControls\PulseButton; Description: Pulse Button

Name: WinFormsControls; Description: Check/Uncheck all; GroupDescription: {cm:CheckboxesDescr}
Name: WinFormsControls\DontShowAgainCheckbox; Description: Don't Show Again Checkbox

Name: WinFormsControls; Description: Check/Uncheck all; GroupDescription: {cm:GroupboxesDescr}
Name: WinFormsControls\Grouper; Description: Grouper

Name: WinFormsControls; Description: Check/Uncheck all; GroupDescription: {cm:KnobsDescr}
Name: WinFormsControls\Knob; Description: Knob
Name: WinFormsControls\KnobControl; Description: KnobControl

...

How can I do this right?.

回答1:

If I understand your question correctly, the problem is that the main "Standalone controls" checkbox does not work, right? Because it's not a part of the hierarchy.


The easiest solution is to give up on the GroupDescription's and move them to the checkbox description:

[Setup]
ShowTasksTreeLines=yes

[Tasks]
Name: WinFormsControls; Description: "Standalone controls"

Name: WinFormsControls\Buttons; Description: "Buttons"
Name: WinFormsControls\Buttons\CButton; Description: CButton
Name: WinFormsControls\Buttons\GlassButton; Description: Glass Button
Name: WinFormsControls\Buttons\MyCommandButtonNET; Description: My Command Button.NET
Name: WinFormsControls\Buttons\PulseButton; Description: Pulse Button

Name: WinFormsControls\Checkboxes; Description: "Checkboxes"
Name: WinFormsControls\Checkboxes\DontShowAgainCheckbox; Description: Don't Show Again Checkbox

Name: WinFormsControls\Groupboxes; Description: "Groupboxes"
Name: WinFormsControls\Groupboxes\Grouper; Description: Grouper

Name: WinFormsControls\Knobs; Description: "Knobs"
Name: WinFormsControls\Knobs\Knob; Description: Knob
Name: WinFormsControls\Knobs\KnobControl; Description: KnobControl


If you want to keep the GroupDescription's, you can bind the main "Check/Uncheck all" to the other checkboxes programmatically:

procedure TasksListClickCheck(Sender: TObject);
var
  Index: Integer;
begin
  if WizardForm.TasksList.ItemIndex = 1 then
  begin
    for Index := 2 to WizardForm.TasksList.Items.Count - 1 do
      WizardForm.TasksList.Checked[Index] := WizardForm.TasksList.Checked[1];
  end;
end;

procedure InitializeWizard();
begin
  WizardForm.TasksList.OnClickCheck := @TasksListClickCheck;
end;

If you really need the hierarchy (indentation), you need to build a custom page. Inno Setup does not support nested group descriptions in the Tasks section. It ignores the GroupDescription parameter for child tasks.

var
  TasksList: TNewCheckListBox;

procedure InitializeWizard();
var
  CustomSelectTasksPage: TWizardPage;
begin
  CustomSelectTasksPage :=
    CreateCustomPage(wpSelectTasks, SetupMessage(msgWizardSelectTasks), SetupMessage(msgSelectTasksDesc));

  TasksList := TNewCheckListBox.Create(WizardForm);
  TasksList.Left := WizardForm.TasksList.Left; 
  TasksList.Top := WizardForm.SelectTasksLabel.Top; 
  TasksList.Width := WizardForm.TasksList.Width; 
  TasksList.Height := WizardForm.TasksList.Top + WizardForm.TasksList.Height - WizardForm.SelectTasksLabel.Top; 

  TasksList.BorderStyle := WizardForm.TasksList.BorderStyle;
  TasksList.Color := WizardForm.TasksList.Color;
  TasksList.ShowLines := WizardForm.TasksList.ShowLines;
  TasksList.MinItemHeight := WizardForm.TasksList.MinItemHeight;
  TasksList.ParentColor := WizardForm.TasksList.ParentColor;
  TasksList.WantTabs := WizardForm.TasksList.WantTabs;

  TasksList.Parent := CustomSelectTasksPage.Surface;

  TasksList.AddGroup('Standalone controls', '', 0, nil);
  TasksList.AddCheckBox('Check/Uncheck all', '', 0, True, True, False, True, nil);
    TasksList.AddGroup('Buttons', '', 1, nil);
    TasksList.AddCheckBox('Check/Uncheck all', '', 1, True, True, False, True, nil);
      TasksList.AddCheckBox('CButton', '', 2, True, True, False, True, nil);
      TasksList.AddCheckBox('Glass Button', '', 2, True, True, False, True, nil);
      TasksList.AddCheckBox('My Command Button.NET', '', 2, True, True, False, True, nil);
      TasksList.AddCheckBox('Pulse Button', '', 2, True, True, False, True, nil);
    TasksList.AddGroup('Checkboxes', '', 1, nil);
    TasksList.AddCheckBox('Check/Uncheck all', '', 1, True, True, False, True, nil);
      TasksList.AddCheckBox('Don''t Show Again Checkbox', '', 2, True, True, False, True, nil);
    TasksList.AddGroup('Knobs', '', 1, nil);
    TasksList.AddCheckBox('Check/Uncheck all', '', 1, True, True, False, True, nil);
      TasksList.AddCheckBox('KnobControl', '', 2, True, True, False, True, nil);
end;

And you will need to bind the tasks to actions in sections like [Files], [Run] or [Registry] using a Check parameters:

[Files]
Source: "CButton.dll"; DestDir: "{app}"; Check: GetCustomTask(2)

[Code]

var
  TasksList: TNewCheckListBox;

{ ... }

function GetCustomTask(TaskIndex: Integer): Boolean;
begin 
  Result := TasksList.Checked[TaskIndex];
end;

For a similar question, see How to split tasklist at tasks page of Inno Setup into multiple columns?