Moin!
Problem: Der Zustand einer TCheckBox soll durch Code geändert werden,
ohne dabei ein OnClick-Ereignis auszulösen!
Für dieses Problem gibt es einige Lösungsansätze. Zunächst etwas zum Hintergrund, dann sollen zwei Ansätze konkret vorgestellt werden. Grundsätzlich ist es nicht falsch, dass beim Schreiben auf TCheckBox.Checked das Ereignis OnClick ausgelöst wird. So kann auch durch Tastaturereignisse (z.B. Ändern per Leertaste) auf Wertänderungen reagiert bzw. eine Benutzereingabe durch Code simuliert werden.
Es sind allerdings zwei grundsätzliche verschiedene Anwendungsfälle zu unterscheiden:
- Benutzerinteraktion
Hier ist das Verhalten der TCheckBox völlig OK, bei Änderung der Eigenschaft .Checked ist das OnClick-Ereignis gewünscht.
- Vorgabe eines Wertes, z.B. beim Laden von Daten
In diesem Fall möchte man eigentlich nur den Status der Checkbox per Code vorgeben, es findet zu diesem Zeitpunkt keine Benutzerinteraktion statt. Hier stört das Ereignis nun, da man üblicherweise im OnClick-Ereignis Code stehen hat, der die Änderung wieder in den Datenbestand überführen soll.
Der "einfache" Lösungsansatz sieht eine (klassen-)globale Variable vor (z.B. Boolean), in der man sich merkt, ob die Komponente(n) OnClick-Ereignisse auslösen sollen. Nachteil: globale Variable erforderlich, sowas ist immer unschön.
Vorteil: klappt immer ohne großen Aufwand.
Ich möchte aber noch eine weitere Lösung vorschlagen: die Komponente erweitern!
Beim Schreiben auf die Eigenschaft TCheckBox.State wird nur dann ein OnClick-Ereignis ausgelöst, wenn der Wert cbChecked zugewiesen wird, also schon fast das gewünschte Verhalten. Wir müssen jetzt nur noch dafür sorgen, dass beim Schreiben auf .State gar kein Ereignis mehr ausgelöst wird, dann haben wir den gewünschten Effekt und trotzdem bei Benutzerinteraktion das Ereignis.
Vorgehensweise (für D7(pro)):
- Im Menü "Komponente" -> "Neue Komponente..." auswählen
- Vorfahrtyp "TCheckBox [StdCtrls]" auswählen
- Klassenname von "TCheckBox1" z.B. in "TClickFreeStateCheckBox" ändern
- Palettenseite "Standard" auswählen
- OK anklicken
- Package-Auswahl kann einfach übernommen werden (wird dann im DefaultUser-Package abgelegt; ist OK, wenn man nicht so genau weiß, wozu das da ist)
- Code anpassen, siehe unten
- Compilieren, fertig.
Hier die Änderungen:
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:
| unit ClickFreeStateCheckBox;
interface
uses SysUtils, Classes, Controls, StdCtrls;
type TClickFreeStateCheckBox = class(TCheckBox) protected function GetMyState: TCheckBoxState; procedure SetMyState(const Value: TCheckBoxState); published property State: TCheckBoxState read GetMyState write SetMyState; end;
procedure Register;
implementation
procedure Register; begin RegisterComponents('Standard', [TClickFreeStateCheckBox]); end;
function TClickFreeStateCheckBox.GetMyState: TCheckBoxState; begin Result := inherited State; end;
procedure TClickFreeStateCheckBox.SetMyState(const Value: TCheckBoxState); begin ClicksDisabled := TRUE; inherited State := Value; ClicksDisabled := FALSE; end;
end. |
Jetzt hat man eine "neue" Checkbox, die beim Schreiben auf .State keine OnClick-Ereignisse mehr auslöst.
cu
Narses
There are 10 types of people - those who understand binary and those who don´t.