Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Checkbox: Status in OnKeyUp ermitteln

10 views
Skip to first unread message

Holger Schieferdecker

unread,
Feb 23, 2021, 10:53:31 AM2/23/21
to
Hallo,

in einem kleinen Programm (D4) habe ich mehrere Checkboxen, von denen
nur eine oder keine gleichzeitig angehakt sein soll. Dazu habe ich im
OnMouseUp (gleiche Routine für alle Checkboxen) folgendes stehen:

procedure TForm1.CheckBoxFunctionMouseUp(Sender: TObject;
Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
if Sender is TCheckBox then begin
if TCheckBox(Sender).Checked then begin
ClearFunctionCheckboxes(Sender);
end;
StringGrid1.Repaint;
end;
end;

ClearFunctionCheckboxes(Sender) setzt bei allen Checked:=false, nur bei
der des Sender nicht.

procedure TForm1.ClearFunctionCheckboxes(aCBtoTrue:TObject=NIL);
begin
CheckboxReplace.Checked:=false;
CheckBoxDelete.Checked:=false;
CheckBoxInsert.Checked:=false;
CheckBoxEnumerate.Checked:=false;
CheckBoxCorrectNumbering.Checked:=false;
CheckBoxDeleteSep.Checked:=false;
if aCBtoTrue is TCheckBox then begin
(aCBtoTrue as TCheckBox).Checked:=true;
end;
end;

Das klappt auch soweit. Nun ist mir aufgefallen, daß man ja auch mit der
Leertaste das Häkchen einer mittels TAB angesteuerten Checkbox setzen
oder löschen kann. Also habe ich etwas ähnliches mit OnKeyUp gemacht:

procedure TForm1.CheckBoxFunctionKeyUp(Sender: TObject; var Key: Word;
Shift: TShiftState);
begin
if (Sender is TCheckBox) and (Key=VK_SPACE) then begin
// showmessage('Hallo');
if TCheckBox(Sender).Checked then begin
ClearFunctionCheckboxes(Sender);
end;
StringGrid1.Repaint;
end;
end;

Damit klappt es aber nur, wenn ich den Kommentar bei showmessage
entferne. Ohne showmessage sehe ich im Debugger, daß
TCheckBox(Sender).Checked=false ist, obwohl anschließend das Häkchen
gesetzt wird. Was könnte showmessage da noch machen, daß in dem Fall
bereits true gefunden wird? Ist das eine Timing-Geschichte?
Application.ProcessMessages bringt übrigens nichts.

Da das nur ein kleines Programm für den Eigenbedarf ist, ist das kein
echtes Problem, aber mich interessiert, woher der Unterschied kommt. Wie
könnte ich dem auf die Spur kommen? Oder wie könnte ich das anders lösen?

Ja, natürlich könnte ich das ganze auf eine Radiogroup umbauen, dann
bräuchte ich eben ein zusätzliches Item für den Fall, daß keine Funktion
gewünscht ist.

Holger

Jens Kallup

unread,
Feb 24, 2021, 8:05:05 AM2/24/21
to
Hallo Holger,

versuche mal, ob Du die Ojekte in eine
TGroupBox unterbringen kannst.

Jens

Sieghard Schicktanz

unread,
Feb 24, 2021, 2:13:06 PM2/24/21
to
Hallo Holger,

Du schriebst am Tue, 23 Feb 2021 16:48:32 +0100:

> in einem kleinen Programm (D4) habe ich mehrere Checkboxen, von denen
> nur eine oder keine gleichzeitig angehakt sein soll. Dazu habe ich im
...
> Ja, natürlich könnte ich das ganze auf eine Radiogroup umbauen, dann
> bräuchte ich eben ein zusätzliches Item für den Fall, daß keine Funktion
> gewünscht ist.

Gibt's da nicht auch eine Option à la "all_up" oder so ähnlich? Irgendwo in
der Umgebung ist mir sowas schonmal untergekommen, und das sollte doch
wenigstens dieses "Problem" mit der "Radiogroup" lösen?

--
--
(Weitergabe von Adressdaten, Telefonnummern u.ä. ohne Zustimmung
nicht gestattet, ebenso Zusendung von Werbung oder ähnlichem)
-----------------------------------------------------------
Mit freundlichen Grüßen, S. Schicktanz
-----------------------------------------------------------

Holger Schieferdecker

unread,
Feb 26, 2021, 3:05:45 AM2/26/21
to
Hallo Jens,
Du meinst damit die Checkboxen? Das habe ich versucht, ändert aber nichts.

Mir scheint, im OnKeyUp einer Checkbox ist es nicht möglich, den neuen
Zustand schon abzufragen, das .Checked wird wohl erst danach gesetzt.
Ich habe es auch mal mit Lazarus versucht, dort ist das Verhalten
ebenso. Mich wundert eben, daß es mit OnMouseUp klappt. Noch mehr
wundert mich, daß ein eingestreutes showmessage das Verhalten ändert.

Ich muß vielleicht mal den Quelltext einer Checkbox genauer anschauen,
auch wenn ich auf den ersten Blick nichts gesehen habe, wo da auf die
Leertaste reagiert wird.

Holger

Holger Schieferdecker

unread,
Feb 26, 2021, 3:12:46 AM2/26/21
to
Am 24.02.2021 um 19:44 schrieb Sieghard Schicktanz:
> Hallo Holger,
>
> Du schriebst am Tue, 23 Feb 2021 16:48:32 +0100:
>
>> in einem kleinen Programm (D4) habe ich mehrere Checkboxen, von denen
>> nur eine oder keine gleichzeitig angehakt sein soll. Dazu habe ich im
> ....
>> Ja, natürlich könnte ich das ganze auf eine Radiogroup umbauen, dann
>> bräuchte ich eben ein zusätzliches Item für den Fall, daß keine Funktion
>> gewünscht ist.
>
> Gibt's da nicht auch eine Option à la "all_up" oder so ähnlich? Irgendwo in
> der Umgebung ist mir sowas schonmal untergekommen, und das sollte doch
> wenigstens dieses "Problem" mit der "Radiogroup" lösen?

Man kann ItemIndex:=-1 setzen, dann ist kein Radiobutton aktiv. Aber
soweit ich das sehe geht das nur aus dem Code heraus, nicht per
Mausklick oder Tastendruck. Wäre auch ein unübliches Verhalten für eine
Radiogroup.

Ich müßte sowieso statt einer Radiogroup eine Groupbox oder ein Panel
nehmen, da ich die Radiobuttons manuell positionieren will. Da gibt es
dann wiederum kein ItemIndex, ergo käme sowieso ein zusätzlicher
Radiobutton mit 'None' oder so hinzu.

Holger

Heiko Rost

unread,
Feb 26, 2021, 4:17:14 AM2/26/21
to
Holger Schieferdecker schrieb:

> Mir scheint, im OnKeyUp einer Checkbox ist es nicht möglich, den neuen
> Zustand schon abzufragen, das .Checked wird wohl erst danach gesetzt.

Ich habe hier nur D7 zum Testen, und dort gibt es das OnClick-Ereignis.
Damit dürfte das unten angehängte Testprogramm genau das von Dir
gewünschte Verhalten zeigen. Im Unterschied zu Deiner Lösung reagiert es
auf jede Änderung, z. B. auch bei einem zugewiesenen Tastenkürzel.
Deshalb auch das aktiv-Flag, weil das .Checked:=false innerhalb des
OnClick-Ereignisses wieder ain OnClick auslösen kann.

Gruß Heiko

-------------------- hier abschneiden --------------------------------

unit KlickUnit;

interface

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

type
TForm1 = class(TForm)
CheckBox1: TCheckBox;
CheckBox2: TCheckBox;
CheckBox3: TCheckBox;
CheckBox4: TCheckBox;
procedure FormCreate(Sender: TObject);
procedure CheckBoxClick(Sender: TObject);
private
{ Private-Deklarationen }
public
{ Public-Deklarationen }
end;

var
Form1: TForm1;
Aktiv : Boolean;

implementation

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);

begin
Aktiv := false;
end;

procedure TForm1.CheckBoxClick(Sender: TObject);
begin
if not aktiv then begin
aktiv:=true;
if sender is tCheckBox then begin
if (sender as tCheckBox).Checked then begin
if sender is tCheckBox then begin
checkbox1.Checked:=false;
checkbox2.Checked:=false;
checkbox3.Checked:=false;
checkbox4.Checked:=false;
(sender as tCheckBox).Checked:=true;
end;
end;
end;
aktiv:=false;
end;
end;

end.
--
Der Mensch ist gut, nur die Nerven sind schlecht.
Mose Ya'aqob Ben-Gavriêl

Jens Kallup

unread,
Feb 26, 2021, 8:14:17 AM2/26/21
to
Am 26.02.2021 um 09:07 schrieb Holger Schieferdecker:

> Ich müßte sowieso statt einer Radiogroup eine Groupbox oder ein Panel
> nehmen, da ich die Radiobuttons manuell positionieren will. Da gibt es
> dann wiederum kein ItemIndex, ergo käme sowieso ein zusätzlicher
> Radiobutton mit 'None' oder so hinzu.

also mein Favorit und Vorschlag wäre, das Du einen dynamischen Array
erstellst, der eine Sub-Klasse für jede TCheckBox enthält.
Dann kannst Du per Index drauf zugreifen und hast die freie Wahl, was
die Zuordnung von Funktionen/Properties, etc.. anbelangt.

In etwa so:

type
TMyCheckBox = class(TCheckBox)
procedure MyOnClick(...);
end;

var
MyCheckers: Array of TMyCheckBox;

SetLength(MyCheckArray, 100);

dann:
for i := 0 to 20 do begin ... end;

> Holger

Jens


Holger Schieferdecker

unread,
Mar 2, 2021, 3:17:23 AM3/2/21
to
Hallo Heiko,

entschuldige die Mail neulich, hatte den falschen Antworten-Button erwischt.

Am 26.02.2021 um 10:17 schrieb Heiko Rost:
> Holger Schieferdecker schrieb:
>
>> Mir scheint, im OnKeyUp einer Checkbox ist es nicht möglich, den neuen
>> Zustand schon abzufragen, das .Checked wird wohl erst danach gesetzt.
>
> Ich habe hier nur D7 zum Testen, und dort gibt es das OnClick-Ereignis.
> Damit dürfte das unten angehängte Testprogramm genau das von Dir
> gewünschte Verhalten zeigen. Im Unterschied zu Deiner Lösung reagiert es
> auf jede Änderung, z. B. auch bei einem zugewiesenen Tastenkürzel.
> Deshalb auch das aktiv-Flag, weil das .Checked:=false innerhalb des
> OnClick-Ereignisses wieder ain OnClick auslösen kann.

Inzwischen habe Deinen Vorschlag mit dem Flag implementiert, das klappt
wie gewünscht. Natürlich wäre es eleganter, nur bei den Checkboxen das
.Checked zu ändern, wo es notwendig ist. Die passenden Abfragen machen
halt den Code etwas länglicher, aber evtl. ändere ich das noch.

Als ich geschrieben hatte, OnClick würde bei mir 3 Mal ausgelöst, hatte
ich das so beobachtet, kann es jetzt aber nicht mehr reproduzieren.

Vielen Dank also für den Tip,
Holger

Christian Schmitt

unread,
Mar 8, 2021, 9:54:52 AM3/8/21
to
Holger Schieferdecker schrieb am Dienstag, 2. März 2021 um 09:17:23 UTC+1:
[...]
Natürlich wäre es eleganter, nur bei den Checkboxen das
> .Checked zu ändern, wo es notwendig ist. Die passenden Abfragen machen
> halt den Code etwas länglicher, aber evtl. ändere ich das noch.
[...]

kürzerer Code wäre z.B. (grade kein Delhpi zur Hand, meine Ausdemkopfsyntax kann etwas vom original abweichen :-) ):

for I := 0 to form1.componentcount -1 do
if Form1.components[i] is TCheckbox then
TCheckbox(Form1.components[i]).checked := false;
(Sender as TCheckbox).checked := true;

Wahlweise, falls es auch noch Checkboxen gibt, die nicht resettet werden, kann man das Property Tag nutzen. Bei den zu resettenden einfach das Tag:=1 setzen und eine If-Abfrage mehr einbauen.

Gruß

Holger Schieferdecker

unread,
Mar 10, 2021, 6:46:56 AM3/10/21
to
Am 08.03.2021 um 15:54 schrieb Christian Schmitt:
> Holger Schieferdecker schrieb am Dienstag, 2. März 2021 um 09:17:23 UTC+1:
> [...]
> Natürlich wäre es eleganter, nur bei den Checkboxen das
>> .Checked zu ändern, wo es notwendig ist. Die passenden Abfragen machen
>> halt den Code etwas länglicher, aber evtl. ändere ich das noch.
> [...]
>
> kürzerer Code wäre z.B. (grade kein Delhpi zur Hand, meine Ausdemkopfsyntax kann etwas vom original abweichen :-) ):

Danke für den Hinweis, einfach alles durchzugehen, ist natürlich auch
eine Möglichkeit.

> for I := 0 to form1.componentcount -1 do
> if Form1.components[i] is TCheckbox then
> TCheckbox(Form1.components[i]).checked := false;
> (Sender as TCheckbox).checked := true;

Sieht richtig aus, abgesehen davon, daß ich self statt Form1 verwenden
würde. Das iteriert eben über alle Komponenten, die da sind. Aber die
Abfrage, ob es eine Checkbox ist, geht ja schnell.

> Wahlweise, falls es auch noch Checkboxen gibt, die nicht resettet werden, kann man das Property Tag nutzen. Bei den zu resettenden einfach das Tag:=1 setzen und eine If-Abfrage mehr einbauen.

Ob man das property Tag verwenden könnte, hatte ich auch schon überlegt.
Damit könnte man dann mehrere Gruppen von Checkboxen verwalten.

Momentan reicht mir jedoch die Lösung mit dem Flag.

Holger

0 new messages