Autor Beitrag
raiguen
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 374

WIN 2000prof, WIN XP prof
D7EP, MSSQL, ABSDB
BeitragVerfasst: Fr 19.05.06 13:01 
Mehrere Checkboxen voneinander abhängig machen

Es gibt durchaus CheckBox-Gruppierungen, wo diese sich, in Kombination, gegenseitig ausschließen. Dann wäre ein Verhalten, wie in einer RadioGroup doch ganz angenehm für den Anwender. Dieses 'RadioGroup-Verhalten' lässt sich beispielsweise so realisieren:

Einfache Lösung (bis zu 3 CheckBoxen):
ausblenden volle Höhe Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
unit Unit1;

interface

uses

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls;

type
  TForm1 = class(TForm)
    GroupBox1: TGroupBox;
    CheckBox1: TCheckBox;
    CheckBox2: TCheckBox;
    CheckBox3: TCheckBox;
    CheckBox4: TCheckBox;
    CheckBox5: TCheckBox;
    procedure FormCreate(Sender: TObject);
  private
    { Private-Deklarationen }
    procedure CheckBoxXYZStatus(BoxNr: Integer);
    procedure CheckBoxXYZMouseDown(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    procedure CheckBoxXYZKeyDown(Sender: TObject; var Key: Word;
      Shift: TShiftState);
  public
    { Public-Deklarationen }
  end;

var
  Form1: TForm1;

implementation

{$R *.DFM}

procedure TForm1.FormCreate(Sender: TObject);
var i: integer;
begin
  for i := 0 to GroupBox1.ControlCount-1 do
    with TCheckBox(GroupBox1.Controls[i]) do
      begin
      Tag := i;
      OnMouseUp := CheckBoxXYZMouseDown;
      OnKeyUp := CheckBoxXYZKeyDown;
      end;
  TCheckBox(GroupBox1.Controls[0]).State := cbchecked;//bei Bedarf, erste CheckBox checked setzen.
end;

procedure TForm1.CheckBoxXYZMouseDown(Sender: TObject; Button: TMouseButton;  
  Shift: TShiftState; X, Y: Integer);
begin  
   CheckBoxXYZStatus((Sender as TCheckBox).Tag);
end;

procedure TForm1.CheckBoxXYZKeyDown(Sender: TObject; var Key: Word;  
  Shift: TShiftState);
begin  
  if Key = ORD(#32then
    CheckBoxXYZStatus((Sender as TCheckBox).Tag);
end;
 
procedure TForm1.CheckBoxXYZStatus(BoxNr: Integer);
var i: Integer;
begin
  for i := 0 to GroupBox1.ControlCount-1 do
    if i <> BoxNr then
      TCheckBox(GroupBox1.Controls[i]).State := cbUnchecked;
end;

end.


Bei mehr als 3 CheckBoxen wird es zu umfangreich; also bietet sich u.a. folgende Lösung an:
Beispiel 2
ausblenden volle Höhe Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  ExtCtrls, StdCtrls;

type
  TForm1 = class(TForm)
    GroupBox1: TGroupBox;
    procedure FormCreate(Sender: TObject);
  private
    { Private-Deklarationen }
    aCheckBox: array[1..5of TCheckBox;
    procedure CheckBoxXYZStatus(BoxNr: Integer);
    procedure CheckBoxXYZMouseDown(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    procedure CheckBoxXYZKeyDown(Sender: TObject; var Key: Word;
      Shift: TShiftState);
  public
    { Public-Deklarationen }
  end;

var
  Form1: TForm1;

implementation

{$R *.DFM}

procedure TForm1.FormCreate(Sender: TObject);
var i: integer;
begin
  for i := Low(aCheckBox) to High(aCheckBox) do
    begin
      aCheckBox[i] := TCheckBox.Create(Self);    
      with aCheckBox[i] do
        begin
           Parent := GroupBox1; //--nur als Beispiel
           Top := 10 + i * 30;
           Left := 10;
           Tag := i;
           Caption := 'CheckBoxG'+IntToStr(i+10); //--nur als Beispiel
           OnMouseUp := CheckBoxXYZMouseDown;
           OnKeyUp := CheckBoxXYZKeyDown;
      end;
  end;
  //--hier die entsprechenden 'aussagekräftigen' Bezeichnungen der Checkboxen setzen
  aCheckBox[1].Caption := '...';
end;

procedure TForm1.CheckBoxXYZMouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin
   CheckBoxXYZStatus((Sender as TCheckBox).Tag);
end;

procedure TForm1.CheckBoxXYZKeyDown(Sender: TObject; var Key: Word;
  Shift: TShiftState);
begin
  if Key = ORD(#32then 
    CheckBoxXYZStatus((Sender as TCheckBox).Tag);
end;

procedure TForm1.CheckBoxXYZStatus(BoxNr: Integer);
var i: Integer;
begin
  for i := Low(aCheckBox) to High(aCheckBox) do
    if i <> BoxNr then
      aCheckBox[i].State := cbUnchecked;
end;
end.


Beispiel 3 Die Checkboxen sind zur Entwicklungszeit in eine GroupBox eingefügt:
ausblenden volle Höhe Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls;

type
  TForm1 = class(TForm)
    GroupBox1: TGroupBox;
    CheckBox1: TCheckBox;
    CheckBox2: TCheckBox;
    CheckBox3: TCheckBox;
    CheckBox4: TCheckBox;
    CheckBox5: TCheckBox;
    procedure FormCreate(Sender: TObject);
  private
    { Private-Deklarationen }
    procedure CheckBoxXYZStatus(BoxNr: Integer);
    procedure CheckBoxXYZMouseDown(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    procedure CheckBoxXYZKeyDown(Sender: TObject; var Key: Word;
      Shift: TShiftState);
  public
    { Public-Deklarationen }
  end;

var
  Form1: TForm1;

implementation

{$R *.DFM}

procedure TForm1.FormCreate(Sender: TObject);
var i: integer;
begin
  for i := 0 to GroupBox1.ControlCount-1 do
    with TCheckBox(GroupBox1.Controls[i]) do
      begin
      Tag := i;
      OnMouseUp := CheckBoxXYZMouseDown;
      OnKeyUp := CheckBoxXYZKeyDown;
      end;
  TCheckBox(GroupBox1.Controls[0]).State := cbchecked;//bei Bedarf, erste CheckBox checked setzen.
end;

procedure TForm1.CheckBoxXYZMouseDown(Sender: TObject; Button: TMouseButton;  
  Shift: TShiftState; X, Y: Integer);
begin  
   CheckBoxXYZStatus((Sender as TCheckBox).Tag);
end;

procedure TForm1.CheckBoxXYZKeyDown(Sender: TObject; var Key: Word;  
  Shift: TShiftState);
begin  
  if Key = ORD(#32then
    CheckBoxXYZStatus((Sender as TCheckBox).Tag);
end;
 
procedure TForm1.CheckBoxXYZStatus(BoxNr: Integer);
var i: Integer;
begin
  for i := 0 to GroupBox1.ControlCount-1 do
    if i <> BoxNr then
      TCheckBox(GroupBox1.Controls[i]).State := cbUnchecked;
end;

end.


Der 'Trick' bei allen Lösungen ist der, dass das OnMouseUp-Ereignis und das OnKeyUp-Ereignis zusammen mit der Methode CheckboxXYZ.State zur Statusänderung benutzt wird. In beiden Ereignissen wird die Prozedur CheckboxXYZStatus zur entsprechenden Statusänderung aufgerufen.

Bei den Beispielen 2 und 3 wird die Eigenschaft .Tag genutzt, um diese als Parameter an die Prozedur CheckBoxXYZStatus zu übergeben.
Bei der 2.Lösung werden die Checkboxen zur Laufzeit in einem Array erstellt, während im Beispiel 3 die CheckBoxen zur Designzeit in eine GroupBox eingefügt sind und bei der TGroupBox die Eigenschaft Controls genutzt wird (Anregung von user profile iconLannes).

Beachte: Jede Statusänderung einer Checkbox löst das Ereignis OnClick() aus :!: Werden Statusänderungen anderer Checkboxen in diesem Ereignis angestossen, kann das zu unerwünschten Symptomen bzw sich gegenseitigen Aufschaukeln führen.
OnMouseUp() bzw OnKeyUp() sind deshalb die geeigneten Ereignisse, weil der Status der Checkbox zu diesem Zeitpunkt schon eindeutig ist, d.h. der Status ist gesetzt.

Danke an user profile iconNarses, user profile iconLannes, user profile iconjasocul für Anregungen/Kritik etc...

Moderiert von user profile iconTh69: Fehler im 3. Code-Beispiel behoben (CheckboxStatus -> CheckboxXYZStatus).
Moderiert von user profile iconTh69: Kleinere Rechtschreibfehler korrigiert.