10

I have added a checkbox to the "Additional Tasks" page of an InnoSetup script with

[Tasks]
Name: "StartMenuEntry" ; Description: "Start my app when Windows starts" ; GroupDescription: "Windows Startup"; MinVersion: 4,4; 

I want to initialize this checkbox when the wpSelectTasks page shows, and read the value when the Next button is clicked. I can't work out how to access the checkbox `checked' value.

function NextButtonClick(CurPageID: Integer): Boolean;

var
  SelectTasksPage : TWizardPage ;
  StartupCheckbox : TCheckbox ;

begin
Result := true ;
case CurPageID of

    wpSelectTasks :
        begin
        SelectTasksPage := PageFromID (wpSelectTasks) ;
        StartupCheckbox := TCheckbox (SelectTasksPage... { <== what goes here??? }
        StartupCheckboxState := StartupCheckbox.Checked ;
        end ;
    end ;    
end ;     
rossmcm
  • 5,493
  • 10
  • 55
  • 118
  • Normally, you don't need to. You would just include the 'Tasks' parameter with the specific task in registry entries involved with auto start. – Sertac Akyuz May 07 '12 at 23:00
  • Thanks @Sertac, Yep I realise that, but I want the state of the checkbox to be initialised from a command line parameter when the setup is invoked, and I want to be able to record the state of it after the wizard page, so I can use it to influence the behaviour of later scripts. Plus it is something I want to know how to do generally... – rossmcm May 07 '12 at 23:06

2 Answers2

18

The task check boxes are in fact items in the WizardForm.TasksList check list box. If you know their indexes you can access them pretty easily. Note, that the items can be grouped (what is just your case) and each new group takes also one item in that check list box, so for your case the item index will be 1:

[Setup]
AppName=TasksList
AppVersion=1.0
DefaultDirName={pf}\TasksList

[Tasks]
Name: "TaskEntry"; Description: "Description"; GroupDescription: "Group";

[code]
function NextButtonClick(CurPageID: Integer): Boolean;
begin
  Result := True;
  if CurPageID = wpSelectTasks then
  begin
    if WizardForm.TasksList.Checked[1] then
      MsgBox('First task has been checked.', mbInformation, MB_OK)
    else
      MsgBox('First task has NOT been checked.', mbInformation, MB_OK);
  end;
end;

procedure CurPageChanged(CurPageID: Integer);
begin
  if CurPageID = wpSelectTasks then
    WizardForm.TasksList.Checked[1] := False;
end;

Here is illustrated how the WizardForm.TasksList check list box would looks like when you'd have two tasks with different groups:

enter image description here

To access the task check box by its description try the following:

[Setup]
AppName=Task List
AppVersion=1.0
DefaultDirName={pf}\TasksList

[Tasks]
Name: "Task"; Description: "Task Description"; GroupDescription: "Group 1";

[code]
function NextButtonClick(CurPageID: Integer): Boolean;
var
  Index: Integer;
begin
  Result := True;
  if CurPageID = wpSelectTasks then
  begin
    Index := WizardForm.TasksList.Items.IndexOf('Task Description');
    if Index <> -1 then
    begin
      if WizardForm.TasksList.Checked[Index] then
        MsgBox('First task has been checked.', mbInformation, MB_OK)
      else
        MsgBox('First task has NOT been checked.', mbInformation, MB_OK);
    end;
  end;
end;

procedure CurPageChanged(CurPageID: Integer);
var
  Index: Integer;
begin
  if CurPageID = wpSelectTasks then
  begin
    Index := WizardForm.TasksList.Items.IndexOf('Task Description');
    if Index <> -1 then    
      WizardForm.TasksList.Checked[Index] := False;
  end;
end;   
TLama
  • 75,147
  • 17
  • 214
  • 392
  • You're welcome! Anyway, I'm not a fan of this kind of index hardcoding however I couldn't find a way how to get index by the task name, you can use `WizardForm.TasksList.Items.IndexOf('TaskDescription')` to find the check box index though, but it's by task description, not by task name. – TLama May 08 '12 at 01:42
  • 1
    Agreed. I've made that change. – rossmcm May 08 '12 at 02:19
  • 3
    there is a better function : `IsTaskSelected('tatata')`, working with indexes didnt work for me. Also I recommend executing actions in the `PrepareToInstall` callback, and only store global variables in the `NextButtonClick` of course because of the potential press on **back**. – v.oddou Dec 20 '13 at 05:04
  • @v.oddou, you're right, but OP knew `IsTaskSelected` function. What's more, there was a requirement to select a task as well (see the question title). And to keep things uniform it's just better to use the same access to read as well as to write the selection state of an item (yes, you can use `IsTaskSelected` to read the state and index to set it but, you know, it's not that smooth as if you do it the same way). Your second point I don't get. Please note, that this example is **only** for illustrative purposes. It's not a real script. The aim was just to show that read/write access. – TLama Dec 20 '13 at 10:05
  • @v.oddou, P.S. I always test what I'm posting except when I explicitly say I don't. Maybe you have used wrong indexes because e.g. groups are items as well. I don't know. But of course, if you need just to read the state, use simply `IsTaskSelected`. This question is about read and write access... – TLama Dec 20 '13 at 10:13
1

Great answer above. Gave me just what I needed.

I had a case where I have a bunch of secondary installers that I used the 'checkonce' option on, but I wanted them to be re-checked if the folder was missing (e.g. the user wiped out the install folder manually), e.g.

[Tasks]
Name: "InstallPython" ; Description: "Install Python"     ; Flags: checkedonce
Name: "InstallNPP"    ; Description: "Install Notepad++"  ; Flags: checkedonce

[Code]
procedure CurPageChanged(CurPageID: Integer);
var
ItemIx: Integer;

begin
    if CurPageID = wpSelectTasks then begin
        if not DirExists(ExpandConstant('{app}')) then begin
            for ItemIx := 0 to (WizardForm.TasksList.Items.Count - 1) do
                WizardForm.TasksList.Checked[ItemIx] := True;
        end
    end
end;
Wade Hatler
  • 1,785
  • 20
  • 18