Entwickler-Ecke

Visual Component Library (VCL) - ...Zustand von TCheckBox setzen, ohne OnClick auszulösen?


Narses - Fr 17.04.09 13:45
Titel: ...Zustand von TCheckBox setzen, ohne OnClick auszulösen?
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: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. :nixweiss: 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. :idea:

Vorgehensweise (für D7(pro)):Hier die Änderungen:

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:
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;

// -----------------------------------------------------------------------------
// TClickFreeStateCheckBox

function TClickFreeStateCheckBox.GetMyState: TCheckBoxState;
begin
  Result := inherited State;
end;

procedure TClickFreeStateCheckBox.SetMyState(const Value: TCheckBoxState);
begin
  ClicksDisabled := TRUE; // leider ist diese Eigenschaft protected deklariert... :-(
  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


BenBE - Fr 17.04.09 13:50

Warum nicht einfach die besagte Eigenschaft in der Klasse gleich mit public setzen?


Narses - Fr 17.04.09 18:08

Moin!

user profile iconBenBE hat folgendes geschrieben Zum zitierten Posting springen:
Warum nicht einfach die besagte Eigenschaft in der Klasse gleich mit public setzen?
Tja, könnte man tun. :nixweiss: (ich halte ja keinen davon ab ;))

Ich denke allerdings, dass das Grundkonzept der Eigenschaft .Checked gar nicht erst änderbar sein sollte. Das würde die verfügbar gemachte Eigenschaft aber erlauben. :? Mein Kritikpunkt ist ja das Verhalten von .State, (nur) hier ist meiner Meinung nach ein logischer Bruch drin, warum sonst löst nur cbChecked ein OnClick aus? Ich weiß nicht, was sich die Delphi-Entwickler dabei gedacht haben, aber ich halte das Verhalten von TCheckBox in Bezug auf .State-Beschreiben für unbrauchbar. Fazit: so wenig wie möglich vom Standard abweichen.

cu
Narses