Вопрос Чекбоксы с перехватом выбора друг друга

AlexS

Новичок
Всем привет! Возник вопрос. На странице есть чекбоксы (в моём случае три), возможность выбора второго и третьего зависит от того, выбран ли первый.
Чтобы понятнее было, их задача состоит в добавлении ключей реестра. Первый (основной) создает пункты в контекстном меню, второй добавляет возможность сделать пункты вложенными, третий добавляет иконки к пунктам меню. Собственно тут задача: если выбирается второй или третий чекбокс, то автоматически выбирается и первый; если снять отметку с первого, то снимаются отметки со второго и(или) третьего. Как такое реализуется в TasksList я уже разобрался, а вот как решить с отдельными чекбосами уже дня два вожусь. Прошу помощи.

[Setup]
AppName=My Program
AppVersion=1.5
CreateAppDir=no
DisableWelcomePage=yes

[Languages]
Name: "default"; MessagesFile: "compiler:Default.isl"

[_Code]
var
CustomPage: TWizardPage;
AddToMenu, CascadeMenu, AddMenuIcons: TNewCheckBox;

procedure InitializeWizard();
begin
{ Creates custom wizard page }
CustomPage := CreateCustomPage(wpWelcome, 'CustomPage_Caption', 'CustomPage_Description');

{ AddToMenu }
AddToMenu := TNewCheckBox.Create(WizardForm);
with AddToMenu do
begin
Parent := CustomPage.Surface;
SetBounds(ScaleX(32),ScaleY(16),ScaleX(177),ScaleY(17));
Caption := 'Добавить в контекстное меню';
end;

{ CascadeMenu }
CascadeMenu := TNewCheckBox.Create(WizardForm);
with CascadeMenu do
begin
Parent := CustomPage.Surface;
SetBounds(ScaleX(32),ScaleY(40),ScaleX(177),ScaleY(17));
Caption := 'Вложенные пункты меню';
end;

{ AddMenuIcons }
AddMenuIcons := TNewCheckBox.Create(WizardForm);
with AddMenuIcons do
begin
Parent := CustomPage.Surface;
SetBounds(ScaleX(32),ScaleY(64),ScaleX(177),ScaleY(17));
Caption := 'Иконки в контекстном меню';
end;
end;

[Setup]
AppName=My Program
AppVersion=1.5
CreateAppDir=no
DisableWelcomePage=yes

[Languages]
Name: "en"; MessagesFile: "compiler:Languages\English.isl"
Name: "ru"; MessagesFile: "compiler:Languages\Russian.isl"

[Tasks]
Name: "interginshell"; Description: "{cm:IntergInShellDescr}"; GroupDescription: "{cm:AdditSettings}";
Name: "shellmenuicon"; Description: "{cm:shellmenuiconDescr}"; GroupDescription: "{cm:AdditSettings}";
Name: "cascadshellmenu"; Description: "{cm:CascadShellMenuDescr}"; GroupDescription: "{cm:AdditSettings}";


[CustomMessages]
ru.AdditSettings=Дополнительные настройки:
ru.IntergInShellDescr=Встроить в контекстное меню Windows
ru.CascadShellMenuDescr=Каскадное контекстное меню
ru.shellmenuiconDescr=Иконки в контекстном меню
en.AdditSettings=Additional settings:
en.IntergInShellDescr=Integrate in Windows context menu
en.CascadShellMenuDescr=Cascaded context menu
en.shellmenuiconDescr=Icons in context menu

[_Code]
var
DefaultTasksClickCheck: TNotifyEvent;
TaskItemSelected: Boolean;

procedure UpdateTasks;
var
Index: Integer;
Index2: Integer;
begin
if (not TaskItemSelected) and (not IsTaskSelected('interginshell')) then
begin
Index := WizardForm.TasksList.Items.IndexOf(ExpandConstant ('{cm:CascadShellMenuDescr}'));
WizardForm.TasksList.CheckItem(Index, coUncheck);
Index2 := WizardForm.TasksList.Items.IndexOf(ExpandConstant ('{cm:shellmenuiconDescr}'));
WizardForm.TasksList.CheckItem(Index2, coUncheck);
TaskItemSelected := True;
end;

if TaskItemSelected and IsTaskSelected('shellmenuicon') then
begin
Index := WizardForm.TasksList.Items.IndexOf(ExpandConstant ('{cm:IntergInShellDescr}'));
WizardForm.TasksList.CheckItem(Index, cocheck);
TaskItemSelected := False;
end;
if TaskItemSelected and IsTaskSelected('cascadshellmenu') then
begin
Index := WizardForm.TasksList.Items.IndexOf(ExpandConstant ('{cm:IntergInShellDescr}'));
WizardForm.TasksList.CheckItem(Index, cocheck);
TaskItemSelected := False;
end;
end;

procedure TasksClickCheck(Sender: TObject);
begin
if DefaultTasksClickCheck <> nil then
DefaultTasksClickCheck(Sender);
UpdateTasks;
end;

procedure InitializeWizard();
begin
DefaultTasksClickCheck := WizardForm.TasksList.OnClickCheck;
WizardForm.TasksList.OnClickCheck := @TasksClickCheck;
end;
 
Последнее редактирование:

ZVSRus

Участник
[Setup]
AppName=My Program
AppVersion=1.5
CreateAppDir=no
DisableWelcomePage=yes
OutputDir=.

[Languages]
Name: "default"; MessagesFile: "compiler:Default.isl"

[ Code]
var
CustomPage: TWizardPage;
AddToMenu, CascadeMenu, AddMenuIcons: TNewCheckBox;

procedure Check0(Sender: TObject);
begin
if not AddToMenu.Checked then
begin
CascadeMenu.Checked := False;
AddMenuIcons.Checked := False;
end;
end;

procedure Check1(Sender: TObject);
begin
if CascadeMenu.Checked then
begin
AddToMenu.Checked := True;
end;
end;

procedure Check2(Sender: TObject);
begin
if AddMenuIcons.Checked then
begin
AddToMenu.Checked := True;
end;
end;

procedure InitializeWizard();
begin
{ Creates custom wizard page }
CustomPage := CreateCustomPage(wpWelcome, 'CustomPage_Caption', 'CustomPage_Description');

{ AddToMenu }
AddToMenu := TNewCheckBox.Create(WizardForm);
with AddToMenu do
begin
Parent := CustomPage.Surface;
SetBounds(ScaleX(32),ScaleY(16),ScaleX(177),ScaleY(17));
Caption := 'Добавить в контекстное меню';
Checked := True;
OnClick := @Check0;
end;

{ CascadeMenu }
CascadeMenu := TNewCheckBox.Create(WizardForm);
with CascadeMenu do
begin
Parent := CustomPage.Surface;
SetBounds(ScaleX(32),ScaleY(40),ScaleX(177),ScaleY(17));
Checked := True;
OnClick := @Check1;
Caption := 'Вложенные пункты меню';
end;

{ AddMenuIcons }
AddMenuIcons := TNewCheckBox.Create(WizardForm);
with AddMenuIcons do
begin
Parent := CustomPage.Surface;
SetBounds(ScaleX(32),ScaleY(64),ScaleX(177),ScaleY(17));
Checked := True;
OnClick := @Check2;
Caption := 'Иконки в контекстном меню';
end;
end;
 
Последнее редактирование:

AlexS

Новичок
Ах вон оно как :facepalm:... Я это уже делал, но прикручивал все действия в одну процедуру, потому и не работало...
ZVSRus, спасибо большое за ответ и помощь!
 

AlexS

Новичок
Пришла мысль сделать работу чекбоксов похожей на работу чекбоксов в CheckListBox(ах). А точнее научить первый(главный) чекбокс принимать полуотмеченный вид в случае если отмечен только один из дочерних чекбоксов, имею ввиду свойство CheckBox.State := cbGrayed при участии CheckBox.AllowGrayed := True.
Вобщем, частично получилось, но возникла другая, не понятная мне проблема. Первый (он же родитель) чекбокс перестал реагировать на попытки отметить его путем клика по нему, его тип отметки меняется только при отметке дочерних чекбоксов.
Я чего-то не понимаю, то ли что-то упустил в процедуре, то ли вообще не в ту сторону поехал(может есть функция какая-то(искал - не нашел)). Ткните пожалуйста на решение, если кто знает путь к нему...

Код:
[Setup]
AppName=My Program
AppVersion=1.5
CreateAppDir=no
DisableWelcomePage=yes
OutputDir=.

[Languages]
Name: "default"; MessagesFile: "compiler:Default.isl"

[ Code]
var
CustomPage: TWizardPage;
AddToMenu, CascadeMenu, AddMenuIcons: TNewCheckBox;

// это пробник, он тоже отказываеся работать...
//procedure CheckBoxClickCheck(Sender: TObject);
//begin
//  case AddToMenu.State of
//    cbUnchecked: begin
//      CascadeMenu.Checked := False;
//      AddMenuIcons.Checked := False;
//      end;
//    cbChecked: begin
//      CascadeMenu.Checked := True;
//      AddMenuIcons.Checked := True;
//      end;
//    cbGrayed: begin
//      CascadeMenu.Checked := False;
//      AddMenuIcons.Checked := True;
//      end;
//  end;
//end;

procedure CheckBoxClickCheck(Sender: TObject);
begin
  if CascadeMenu.Checked and AddMenuIcons.Checked then
  begin
     AddToMenu.State := cbChecked;
     AddToMenu.AllowGrayed := True;
  end;
  if not CascadeMenu.Checked and not AddMenuIcons.Checked then
  begin
     AddToMenu.State := cbUnchecked;
     AddToMenu.AllowGrayed := True;
  end;
  if CascadeMenu.Checked and not AddMenuIcons.Checked then
  begin
     AddToMenu.State := cbGrayed;
     AddToMenu.AllowGrayed := True;
  end;
  if not CascadeMenu.Checked and AddMenuIcons.Checked then
  begin
     AddToMenu.State := cbGrayed;
     AddToMenu.AllowGrayed := True;
  end;
end;

procedure InitializeWizard();
begin
{ Creates custom wizard page }
CustomPage := CreateCustomPage(wpWelcome, 'CustomPage_Caption', 'CustomPage_Description');

{ AddToMenu }
AddToMenu := TNewCheckBox.Create(WizardForm);
with AddToMenu do
begin
Parent := CustomPage.Surface;
SetBounds(ScaleX(32),ScaleY(16),ScaleX(177),ScaleY(17));
Caption := 'Добавить в контекстное меню';
Checked := True;
OnClick := @CheckBoxClickCheck;
end;

{ CascadeMenu }
CascadeMenu := TNewCheckBox.Create(WizardForm);
with CascadeMenu do
begin
Parent := CustomPage.Surface;
SetBounds(ScaleX(32),ScaleY(40),ScaleX(177),ScaleY(17));
Checked := True;
OnClick := @CheckBoxClickCheck;
Caption := 'Вложенные пункты меню';
end;

{ AddMenuIcons }
AddMenuIcons := TNewCheckBox.Create(WizardForm);
with AddMenuIcons do
begin
Parent := CustomPage.Surface;
SetBounds(ScaleX(32),ScaleY(64),ScaleX(177),ScaleY(17));
Checked := True;
OnClick := @CheckBoxClickCheck;
Caption := 'Иконки в контекстном меню';
end;
end;
 

AlexS

Новичок
Пришла мысль сделать работу чекбоксов похожей на работу чекбоксов в CheckListBox(ах)
Добавил одну процедуру и всё заработало. Процедура немного корявая(по-моему), но работает. Если есть у кого другие варианты или идеи - предлагайте... Метод кстати удобен при создании чекбоксов на кастомной странице (и не только) с зависимостью от выбора друг друга без использования CheckListBox(а). Позволяет раскидать чекбоксы по разным координатам страницы... Как-то так.

Код:
[Setup]
AppName=My Program
AppVersion=1.5
CreateAppDir=no
DisableWelcomePage=yes
OutputDir=.

[Languages]
Name: "default"; MessagesFile: "compiler:Default.isl"

[ Code]
var
CustomPage: TWizardPage;
AddToMenu, CascadeMenu, AddMenuIcons: TNewCheckBox;

procedure CheckBoxClickCheck2(Sender: TObject);
begin
  case AddToMenu.State of
    cbUnchecked: begin
      CascadeMenu.Checked := False;
      AddMenuIcons.Checked := False;
      end;
    cbChecked: begin
      CascadeMenu.Checked := True;
      AddMenuIcons.Checked := True;
      end;
    cbGrayed: begin
      if CascadeMenu.Checked and not AddMenuIcons.Checked or
      not CascadeMenu.Checked and AddMenuIcons.Checked
      then begin AddToMenu.State := cbGrayed; end;
      end;
  end;
end;

procedure CheckBoxClickCheck(Sender: TObject);
begin
  if CascadeMenu.Checked and AddMenuIcons.Checked then
  begin
     AddToMenu.State := cbChecked;
  end;
  if not CascadeMenu.Checked and not AddMenuIcons.Checked then
  begin
     AddToMenu.State := cbUnchecked;
  end;
  if CascadeMenu.Checked and not AddMenuIcons.Checked then
  begin
     AddToMenu.State := cbGrayed;
  end;
  if not CascadeMenu.Checked and AddMenuIcons.Checked then
  begin
     AddToMenu.State := cbGrayed;
  end;
end;

procedure InitializeWizard();
begin
{ Creates custom wizard page }
CustomPage := CreateCustomPage(wpWelcome, 'CustomPage_Caption', 'CustomPage_Description');

{ AddToMenu }
AddToMenu := TNewCheckBox.Create(WizardForm);
with AddToMenu do
begin
Parent := CustomPage.Surface;
SetBounds(ScaleX(32),ScaleY(16),ScaleX(177),ScaleY(17));
Caption := 'Добавить в контекстное меню';
Checked := True;
OnClick := @CheckBoxClickCheck2;
end;

{ CascadeMenu }
CascadeMenu := TNewCheckBox.Create(WizardForm);
with CascadeMenu do
begin
Parent := CustomPage.Surface;
SetBounds(ScaleX(32),ScaleY(40),ScaleX(177),ScaleY(17));
Checked := True;
OnClick := @CheckBoxClickCheck;
Caption := 'Вложенные пункты меню';
end;

{ AddMenuIcons }
AddMenuIcons := TNewCheckBox.Create(WizardForm);
with AddMenuIcons do
begin
Parent := CustomPage.Surface;
SetBounds(ScaleX(32),ScaleY(64),ScaleX(177),ScaleY(17));
Checked := True;
OnClick := @CheckBoxClickCheck;
Caption := 'Иконки в контекстном меню';
end;
end;
 
Последнее редактирование:

ZVSRus

Участник
Сомневаюсь что код работает правильно. Визуально да, работает правильно, но когда снимаешь галочку со 2 чекбокса, будет установлен компонент что находится под 3 чекбоксом, и на оборот снимаешь галочку с 3 чекбокса, будет установлен компонент что находится под 2 чекбоксом. Под 1 чекбоксом компонент будет установлен только когда все 3 чекбокса выбраны. Как я понимаю компонент что будет находится под чекбоксом 1 должен по любому устанавливаться, так-как он у вас главный.
 

AlexS

Новичок
когда снимаешь галочку со 2 чекбокса, будет установлен компонент что находится под 3 чекбоксом, и на оборот
Да вроде нет. Подставил под чекбоксы задачу на внесение ключей реестра, вносятся соответственно своему чекбоксу(кроме первого)...
Под 1 чекбоксом компонент будет установлен только когда все 3 чекбокса выбраны. Как я понимаю компонент что будет находится под чекбоксом 1 должен по любому устанавливаться, так-как он у вас главный.
Да. Тут действительно проблема. Надо подумать...:scratchhead:

Код:
[Setup]
AppName=My Program
AppVersion=1.5
CreateAppDir=no
DisableWelcomePage=yes
OutputDir=.

[Registry]
Root: HKCR; SubKey: .002; ValueType: string; ValueData: "Пункт меню"; Check: MnuCheck; Flags: uninsdeletevalue uninsdeletekeyifempty
Root: HKCR; SubKey: .002; ValueType: string; ValueName: Icon; ValueData: "{app}\MyApp.exe"; Check: IconsMnuCheck; Flags: uninsdeletevalue uninsdeletekeyifempty
Root: HKCR; SubKey: .002; ValueType: string; ValueName: SubMenu; ValueData: "1"; Check: CascMnuCheck; Flags: uninsdeletevalue uninsdeletekeyifempty

[Languages]                                                                               
Name: "default"; MessagesFile: "compiler:Default.isl"

[ Code]
var
CustomPage: TWizardPage;
AddToMenu, CascadeMenu, AddMenuIcons: TNewCheckBox;

function CheckParam(s: string): boolean;
var
  i: integer;
begin
  for i := 0 to ParamCount do begin
  Result := ParamStr(i) = s;
  if Result then Break;
  end;
end;

function MnuCheck: Boolean; begin Result := AddToMenu.Checked; end;
function CascMnuCheck: Boolean; begin Result := CascadeMenu.Checked; end;
function IconsMnuCheck: Boolean; begin Result := AddMenuIcons.Checked; end;

procedure CheckBoxClickCheck2(Sender: TObject);
begin
  case AddToMenu.State of
    cbUnchecked: begin
      CascadeMenu.Checked := False;
      AddMenuIcons.Checked := False;
      end;
    cbChecked: begin
      CascadeMenu.Checked := True;
      AddMenuIcons.Checked := True;
      end;
    cbGrayed: begin
      if CascadeMenu.Checked and not AddMenuIcons.Checked or
      not CascadeMenu.Checked and AddMenuIcons.Checked
      then begin AddToMenu.State := cbGrayed; end;
      end;
  end;
end;

procedure CheckBoxClickCheck(Sender: TObject);
begin
  if CascadeMenu.Checked and AddMenuIcons.Checked then
  begin
     AddToMenu.State := cbChecked;
  end;
  if not CascadeMenu.Checked and not AddMenuIcons.Checked then
  begin
     AddToMenu.State := cbUnchecked;
  end;
  if CascadeMenu.Checked and not AddMenuIcons.Checked then
  begin
     AddToMenu.State := cbGrayed;
  end;
  if not CascadeMenu.Checked and AddMenuIcons.Checked then
  begin
     AddToMenu.State := cbGrayed;
  end;
end;

procedure InitializeWizard();
begin
{ Creates custom wizard page }
CustomPage := CreateCustomPage(wpWelcome, 'CustomPage_Caption', 'CustomPage_Description');

{ AddToMenu }
AddToMenu := TNewCheckBox.Create(WizardForm);
with AddToMenu do
begin
Parent := CustomPage.Surface;
SetBounds(ScaleX(32),ScaleY(16),ScaleX(177),ScaleY(17));
Caption := 'Добавить в контекстное меню';
Checked := True;
OnClick := @CheckBoxClickCheck2;
end;

{ CascadeMenu }
CascadeMenu := TNewCheckBox.Create(WizardForm);
with CascadeMenu do
begin
Parent := CustomPage.Surface;
SetBounds(ScaleX(32),ScaleY(40),ScaleX(177),ScaleY(17));
Checked := True;
OnClick := @CheckBoxClickCheck;
Caption := 'Вложенные пункты меню';
end;

{ AddMenuIcons }
AddMenuIcons := TNewCheckBox.Create(WizardForm);
with AddMenuIcons do
begin
Parent := CustomPage.Surface;
SetBounds(ScaleX(32),ScaleY(64),ScaleX(177),ScaleY(17));
Checked := True;
OnClick := @CheckBoxClickCheck;
Caption := 'Иконки в контекстном меню';
end;
end;
 

Nemko

Дилетант
Модератор
AlexS, не гарантирую ничего, может будет работать, но это не для слабонервных:
Код:
[Setup]
AppName=Exp
AppVersion=0.1
CreateAppDir=no
OutputDir=.
DisableWelcomePage=no

[Code]
var
  GroupCheckBox: array of TNewCheckBox;
  UpdateCheckBox: Boolean;

{ Narkomaniya o_0 }
procedure ClickGroupCheckBox(Sender: TObject);
var
  i, p, e, c: Integer;
begin
  p:=-1; e:=0; c:=0;
  if (Sender is TNewCheckBox) and not UpdateCheckBox then begin
    for i:=0 to GetArrayLength(GroupCheckBox)-1 do begin
      if TNewCheckBox(Sender).Tag = GroupCheckBox[i].Tag then begin
        if (p = -1) then p:=i else e:=e+1;
        if GroupCheckBox[i].Checked and (p <> i) then c:=c+1;
      end;
    end;
    if TNewCheckBox(Sender) = GroupCheckBox[p] then begin
      UpdateCheckBox:=True;
      for i:=p to GetArrayLength(GroupCheckBox)-1 do begin
      if TNewCheckBox(Sender).Tag = GroupCheckBox[i].Tag then begin
        case GroupCheckBox[p].State of
          cbChecked: GroupCheckBox[i].State:=cbChecked;
          cbUnchecked:  GroupCheckBox[i].State:=cbUnchecked;
        end;
      end;
      end;
      UpdateCheckBox:=False;
    end else begin
      if (p = -1) then Exit;
      if (c <> e) and (c > 0) then GroupCheckBox[p].State:=cbGrayed;
      if (c = e) then GroupCheckBox[p].State:=cbChecked;
      if (c = 0) then GroupCheckBox[p].State:=cbUnchecked;
    end;
  end;
end;

{ Create GroupCheckBox }
procedure AddGroupCheckBox(nParent: TWinControl; X, Y, W, H: Integer; nName, Text: String; Group: Byte; Check: Boolean);
var
  Ind, Count: Integer;
begin
  { Set Array }
  Ind:=GetArrayLength(GroupCheckBox);
  SetArrayLength(GroupCheckBox, Ind+1);
  { Create CheckBox }
  GroupCheckBox[Ind]:=TNewCheckBox.Create(nil);
  with GroupCheckBox[Ind] do begin
    SetBounds(ScaleX(X), ScaleY(Y),ScaleX(W), ScaleY(H));
    Parent:=nParent;
    Checked:=Check;
    Caption:=Text;
    Name:=nName;
    Tag:=Group
    { Set Evet }
    OnClick:=@ClickGroupCheckBox;
  end;
end;

{ Get Checked }
function GetCheckedGroupCheckBox(Name: String): Boolean;
var
  i: Integer;
begin
  for i:=0 to GetArrayLength(GroupCheckBox)-1 do begin
    if (Lowercase(GroupCheckBox[i].Name) = Lowercase(Name)) then begin
      Result:=GroupCheckBox[i].Checked;
      Break;
    end;
 end;
end;

function NextButtonClick(CurPageID: Integer): Boolean;
begin
  if GetCheckedGroupCheckBox('Child_01') then MsgBox('ДЕЙСТВИЕ_01 - выбран', mbError, MB_OK)
  else MsgBox('ДЕЙСТВИЕ_01 - НЕ выбран', mbError, MB_OK);
  Result:=False;
end;

procedure CurPageChanged(CurPageID: Integer);
begin
  with WizardForm do begin
    OuterNotebook.Hide; NextButton.Caption:='- Check -';
    { Create Group №1 }
    AddGroupCheckBox(WizardForm, 30, 020, 177, 17, 'Parent_1', 'Заголовок_1', 1, True);
    AddGroupCheckBox(WizardForm, 50, 040, 177, 17, 'Child_01', 'ДЕЙСТВИЕ_01', 1, True);
    AddGroupCheckBox(WizardForm, 50, 060, 177, 17, 'Child_02', 'Действие_02', 1, True);

    { Create Group №2 }
    AddGroupCheckBox(WizardForm, 30, 090, 177, 17, 'Parent_2', 'Заголовок_2', 2, True);
    AddGroupCheckBox(WizardForm, 50, 110, 177, 17, 'Child_03', 'Действие_03', 2, True);
    AddGroupCheckBox(WizardForm, 50, 130, 177, 17, 'Child_04', 'Действие_04', 2, True);
    AddGroupCheckBox(WizardForm, 50, 150, 177, 17, 'Child_05', 'Действие_05', 2, True);
    AddGroupCheckBox(WizardForm, 50, 170, 177, 17, 'Child_06', 'Действие_06', 2, True);
  end;
end;
 

AlexS

Новичок
Я выкрутился так...
Код:
[Setup]
AppName=My Program
AppVersion=1.5
CreateAppDir=no
DisableWelcomePage=yes
OutputDir=.

[Registry]
Root: HKCR; SubKey: .002; ValueType: string ; ValueName: Menu; ValueData: "Пункт меню"; Check: MnuCheck or MnuCheck3; Flags: uninsdeletevalue uninsdeletekeyifempty
Root: HKCR; SubKey: .002; ValueType: string; ValueName: SubMenu; ValueData: "1"; Check: CascMnuCheck; Flags: uninsdeletevalue uninsdeletekeyifempty
Root: HKCR; SubKey: .002; ValueType: string; ValueName: Icon; ValueData: "{app}\MyApp.exe"; Check: IconsMnuCheck; Flags: uninsdeletevalue uninsdeletekeyifempty

[Languages]                                                                               
Name: "default"; MessagesFile: "compiler:Default.isl"

[Code]
var
CustomPage: TWizardPage;
AddToMenu, CascadeMenu, AddMenuIcons: TNewCheckBox;


function MnuCheck3: Boolean;
begin
  if AddToMenu.State = cbGrayed then
  Result := true;
end;

function MnuCheck: Boolean; begin Result := AddToMenu.Checked; end;
function CascMnuCheck: Boolean; begin Result := CascadeMenu.Checked; end;
function IconsMnuCheck: Boolean; begin Result := AddMenuIcons.Checked; end;

procedure CheckBoxClickCheck2(Sender: TObject);
begin
  case AddToMenu.State of
    cbUnchecked: begin
      CascadeMenu.Checked := False;
      AddMenuIcons.Checked := False;
      end;
    cbChecked: begin
      CascadeMenu.Checked := True;
      AddMenuIcons.Checked := True;
      end;
    cbGrayed: begin
      if CascadeMenu.Checked and not AddMenuIcons.Checked or
      not CascadeMenu.Checked and AddMenuIcons.Checked
      then begin AddToMenu.State := cbGrayed; end;
      end;
  end;
end;

procedure CheckBoxClickCheck(Sender: TObject);
begin
  if CascadeMenu.Checked and AddMenuIcons.Checked then
  begin
     AddToMenu.State := cbChecked;
  end;
  if not CascadeMenu.Checked and not AddMenuIcons.Checked then
  begin
     AddToMenu.State := cbUnchecked;
  end;
  if CascadeMenu.Checked and not AddMenuIcons.Checked then
  begin
     AddToMenu.State := cbGrayed;
  end;
  if not CascadeMenu.Checked and AddMenuIcons.Checked then
  begin
     AddToMenu.State := cbGrayed;
  end;
end;

procedure InitializeWizard();
begin
{ Creates custom wizard page }
CustomPage := CreateCustomPage(wpWelcome, 'CustomPage_Caption', 'CustomPage_Description');

{ AddToMenu }
AddToMenu := TNewCheckBox.Create(WizardForm);
with AddToMenu do
begin
Parent := CustomPage.Surface;
SetBounds(ScaleX(32),ScaleY(16),ScaleX(177),ScaleY(17));
Caption := 'Добавить в контекстное меню';
Checked := True;
OnClick := @CheckBoxClickCheck2;
end;

{ CascadeMenu }
CascadeMenu := TNewCheckBox.Create(WizardForm);
with CascadeMenu do
begin
Parent := CustomPage.Surface;
SetBounds(ScaleX(32),ScaleY(40),ScaleX(177),ScaleY(17));
Checked := True;
OnClick := @CheckBoxClickCheck;
Caption := 'Вложенные пункты меню';
end;

{ AddMenuIcons }
AddMenuIcons := TNewCheckBox.Create(WizardForm);
with AddMenuIcons do
begin
Parent := CustomPage.Surface;
SetBounds(ScaleX(32),ScaleY(64),ScaleX(177),ScaleY(17));
Checked := True;
OnClick := @CheckBoxClickCheck;
Caption := 'Иконки в контекстном меню';
end;
end;

Nemko, потестим... На первый взгляд всё хорошо.
 

AlexS

Новичок
не гарантирую ничего, может будет работать
Работает хорошо, глюков не замечено. Вот только уже два часа жую этот код. Как изменить родителя? Пытаюсь перекинуть на кастомную страницу - пока что одни ошибки...
 

ZVSRus

Участник
@Nemko, Что-то, где-то не так, при снятии галки с 2 или 3 чекбокса, 1 чекбокс становится не выбран, ну и естественно из под него ничего не устанавливается.

PS: Не буду утверждать, может эта строка if (c <> e) and (c > 0) then GroupCheckBox[p].State:=cbGrayed; так как заметил что .State:=cbGrayed не ассоциируется с выбранным чеком
 

Nemko

Дилетант
Модератор
Что-то, где-то не так, при снятии галки с 2 или 3 чекбокса, 1 чекбокс становится не выбран, ну и естественно из под него ничего не устанавливается.
ZVSRus, ну да, это указатель на группу, если в группе ничего не выбрано, то зачем прикреплять к нему компонент и привязывать его к группе, может лучше создать отдельный checkbox. Да код перед Вами, можете настроить под себя, я представил задачу себе так, соответственно и реализовал так.
Как изменить родителя? Пытаюсь перекинуть на кастомную страницу - пока что одни ошибки...
AlexS, AddGroupCheckBox(Parent, ...). Обратите внимание, что я создал компоненты в CurPageChanged, а не через InitializeWizard, может ошибки из-за этого.
 

ZVSRus

Участник
@Nemko, Извиняюсь, но вы меня не правильно поняли. 1 чекбокс - это указатель на группу, он должен быть не выбран только когда не выброны 2 и 3 чекбоксы, это у вас правильно. Но если снята галка со 2 чекбокса, то тогда должны установится компоненты с 1 и 3 чекбокса, и наоборот снимаешь галку с 3 чекбокса, должны установится компоненты с 1 и 2 чекбоксов.
У вас при снятии одно чекбокса (2 или 3) 1 чекбокс (указатель на группу) становится не активен.
Не буду утверждать, но кажется что параметр .State:=cbGrayed, и при этом чтобы чекбокс был отмечен, работает только с чеклистом,
ну если кто-то не напишет программный код, чтобы параметр .State:=cbGrayed ассоциировался с отмеченным чекбоксом (костомным).
 
Последнее редактирование:

Nemko

Дилетант
Модератор
ZVSRus, теперь я "въехал", не лишенное смысла замечание, думаю нужно поправить GetCheckedGroupCheckBox и будет работать:
Код:
function GetCheckedGroupCheckBox(Name: String): Boolean;
var
  i: Integer;
begin
  for i:=0 to GetArrayLength(GroupCheckBox)-1 do begin
    if (Lowercase(GroupCheckBox.Name) = Lowercase(Name)) then begin
      if GroupCheckBox.State = cbGrayed then Result:=True
      else Result:=GroupCheckBox.Checked;
      Break;
    end;
end;
end;
 

AlexS

Новичок
AddGroupCheckBox(Parent, ...)
Это решило все проблемы с родителем...
поправить GetCheckedGroupCheckBox и будет работать
Ругается... У меня сработало так...
Код:
function GetCheckedGroupCheckBox(Name: String): Boolean;
var
  i: Integer;
begin
  for i:=0 to GetArrayLength(GroupCheckBox)-1 do begin
    if (Lowercase(GroupCheckBox[i].Name) = Lowercase(Name)) then begin
      if GroupCheckBox[i].State = cbGrayed then Result:=True
      else Result:=GroupCheckBox[i].Checked;
      Break;
    end;
end;
end;
 

ZVSRus

Участник
@Nemko, @AlexS, Не катит, ни чего не изменилось, при снятии флажка с одного чекбокса (2 или 3) 1 чекбокс не отмечен.
 

AlexS

Новичок
1 чекбокс не отмечен
Он становится в положение cbGrayed, а оно имеет отличие от Checked.
В общем я переделал под себя, чтобы возможно было отметить только первый чекбокс(он становится cbGrayed) и он при этом выполнял свою задачу... Сыровато конечно, требует испытаний, но... Держи, может я тебя правильно понял и ты тоже ищешь именно это...

Код:
[Setup]
AppName=Exp
AppVersion=0.1
CreateAppDir=no
OutputDir=.
DisableWelcomePage=yes

[Registry]
Root: HKCR; SubKey: .002; ValueType: string ; ValueName: Menu; ValueData: "Пункт меню"; Check: MnuCheck; Flags: uninsdeletevalue uninsdeletekeyifempty
Root: HKCR; SubKey: .002; ValueType: string; ValueName: SubMenu; ValueData: "1"; Check: CascMnuCheck; Flags: uninsdeletevalue uninsdeletekeyifempty
Root: HKCR; SubKey: .002; ValueType: string; ValueName: Icon; ValueData: "MyApp.exe"; Check: IconsMnuCheck; Flags: uninsdeletevalue uninsdeletekeyifempty

[ Code]
var
  CustomPage: TWizardPage;
  GroupCheckBox: array of TNewCheckBox;
  UpdateCheckBox: Boolean;
  i: Integer;

{ Narkomaniya o_0 }
procedure ClickGroupCheckBox(Sender: TObject);
var
  i, p, e, c: Integer;
begin
  p:=-1; e:=0; c:=0;
  if (Sender is TNewCheckBox) and not UpdateCheckBox then begin
    for i:=0 to GetArrayLength(GroupCheckBox)-1 do begin
      if TNewCheckBox(Sender).Tag = GroupCheckBox[i].Tag then begin
        if (p = -1) then p:=i else e:=e+1;
        if GroupCheckBox[i].Checked and (p <> i) then c:=c+1;
      end;
    end;
    if TNewCheckBox(Sender) = GroupCheckBox[p] then begin
      UpdateCheckBox:=True;
      for i:=p to GetArrayLength(GroupCheckBox)-1 do begin
      if TNewCheckBox(Sender).Tag = GroupCheckBox[i].Tag then begin
        case GroupCheckBox[p].State of
          cbChecked: GroupCheckBox[i].State:=cbChecked;
          cbUnchecked:  GroupCheckBox[i].State:=cbUnchecked;
        end;
      end;
      end;
      UpdateCheckBox:=False;
    end else begin
      if (p = -1) then Exit;
      if (c <> e) and (c > 0) then GroupCheckBox[p].State:=cbGrayed;
      if (c = e) then GroupCheckBox[p].State:=cbChecked;
      if (c = 0) then GroupCheckBox[p].State:=cbUnchecked;
    end;
  end;
end;

{ Create GroupCheckBox }
procedure AddGroupCheckBox(nParent: TWinControl; X, Y, W, H: Integer; nName, Text: String; Group: Byte; Check: Boolean);
var
  Ind, Count: Integer;
begin
  { Set Array }
  Ind:=GetArrayLength(GroupCheckBox);
  SetArrayLength(GroupCheckBox, Ind+1);
  { Create CheckBox }
  GroupCheckBox[Ind]:=TNewCheckBox.Create(nil);
  with GroupCheckBox[Ind] do begin
    SetBounds(ScaleX(X), ScaleY(Y),ScaleX(W), ScaleY(H));
    Parent:=nParent;
    Checked:=Check;
    Caption:=Text;
    Name:=nName;
    Tag:=Group
    { Set Evet }
    OnClick:=@ClickGroupCheckBox;
  end;
end;

function GetCheckedGroupCheckBox(Name: String): Boolean;
var
  i: Integer;
begin
  for i:=0 to GetArrayLength(GroupCheckBox)-1 do begin
    if (Lowercase(GroupCheckBox[i].Name) = Lowercase(Name)) then begin
      if GroupCheckBox[i].State = cbGrayed then Result:=True
      else Result:=GroupCheckBox[i].Checked;
      Break;
    end;
end;
end;

function MnuCheck: Boolean; begin Result := GetCheckedGroupCheckBox('Parent_1'); end;
function CascMnuCheck: Boolean; begin Result := GetCheckedGroupCheckBox('Child_01'); end;
function IconsMnuCheck: Boolean; begin Result := GetCheckedGroupCheckBox('Child_02'); end;


procedure InitializeWizard();
begin
    { Creates custom wizard page }
  CustomPage := CreateCustomPage(wpWelcome, 'ISCustomPage1_Caption', 'ISCustomPage1_Description');
  begin
    AddGroupCheckBox(CustomPage.Surface, 30, 020, 177, 17, 'Parent_1', 'Добавить в контекстное меню', 1, True);
    AddGroupCheckBox(CustomPage.Surface, 50, 040, 177, 17, 'Child_01', 'Вложенные пункты меню', 1, True);
    AddGroupCheckBox(CustomPage.Surface, 50, 060, 177, 17, 'Child_02', 'Иконки в контекстном меню', 1, True);
  end;
end;

procedure CurPageChanged(CurPageID: Integer);
begin
case CurPageID of
 CustomPage.ID: begin
   if (GroupCheckBox[i].Name) = 'Parent_1' then GroupCheckBox[0].AllowGrayed := True;
  end;
 end;
end;
 

AlexS

Новичок
А ещё можно сделать так:
Код:
procedure ClickGroupCheckBox(Sender: TObject);
...
if (c = 0) then GroupCheckBox[p].State:=cbGrayed;
 

ZVSRus

Участник
@AlexS, Извиняюсь, но данное художество не заинтересовало.
Он становится в положение cbGrayed, а оно имеет отличие от Checked.
Это я давно понял, и выше описывал что cbGrayed не ассоциируется с отмеченным чекбоксом (кроме чекбоксов что находятся на чеклисте.)
Сыровато конечно, требует испытаний, но...
Нет это не сыровато, это далеко от идеала. По первым вашим постам я понял что вам нужны чекбоксы работующие именно так как на чеклисте, на данный момент вы отклонились от первоначальной задумки, и теперь я уже не понимаю смысл ваших маневров.
Хотя понял одно,что вам очень нравится скрытость 1 чекбокса (.State:=cbGrayed), хоть он и не работает.
Держи, может я тебя правильно понял и ты тоже ищешь именно это...
Нет, спасибо, я бы применил чеклистбокс, и скрипт маленький, и работает как надо.
 
Сверху