Home » Tutorials » VCL » Komponenten entwicklen

Komponenten entwicklen

Eigenschaftstypen

In diesem Kapitel erkläre ich die verschiedenen Eigenschaftstypen. Schau Dir doch mal den Objektinspektor an! Du wirst dort nicht nur so einfache Eigenschaften finden, wie Du sie in den vorherigen Kapiteln kennen gelernt hast. Die weiteren Beispiele beziehen sich nicht auf die Komponenten aus den Vorgänger-Kapiteln.

Eigenschaften von Aufzählungstypen

Aufzählungstypen sind Typen, die nur einen Wert den vorgegebenen Werten zulassen.
Die Eigenschaft „Position“ ist ein Aufzählungstyp:

Um so eine Eigenschaft erstellen zu können, musst du erst einen eigenen Typ definieren.

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

type
  TTreffpunkt = (tpBahnhof, tpBushalteStelle, tpZOB, tpTaxiStand);

type
  TBeispielComp = class(TComponent)
  private
  { Private-Deklarationen }
  protected
  { Protected-Deklarationen }
  public
  { Public-Deklarationen }
  published
  { Published-Deklarationen }
end;

Vereinbarungsgemäß stellt man zwei „Erkennungsbuchstaben“ vor solchen Aufzählungen, wie z.B. auch bei der Eigenschaft „Color“: cl oder „Position“: po.
Und nun wird das Property wie gewohnt erstellt:

private
  FOrt: TTreffpunkt;
  { Private-Deklarationen }
protected
  { Protected-Deklarationen }
public
  { Public-Deklarationen }
published
  property Ort: TTreffpunkt read FOrt write FOrt;
  { Published-Deklarationen }

Das war es schon.

Eigenschaften von Mengentypen

Mengentypen gestatten die Auswahl von keiner, einer oder mehreren Optionen. Die einzelnen Mengentypen können aber nur die Werte „True“ und „False“ annehmen.

Wie schon beim Aufzählungstypen, ist es notwendig alle zulässigen Optionen festzulegen.

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

type
  TTreffpunkt = set of (tpBahnhof, tpBushalteStelle, tpZOB, tpTaxiStand);

type
  TBeispielComp = class(TComponent)
  private
  { Private-Deklarationen }
  protected
  { Protected-Deklarationen }
  public
  { Public-Deklarationen }
  published
  { Published-Deklarationen }
end;

Auch hier werden wieder Erkennungsbuchstaben vorangestellt. Und jetzt muss die Eigenschaft natürlich wieder im Published-Block festgelegt werden:

private
  FOrt: TTreffpunkt;
  { Private-Deklarationen }
protected
  { Protected-Deklarationen }
public
  { Public-Deklarationen }
published
  property Ort: TTreffpunkt read FOrt write FOrt;
  { Published-Deklarationen }

Der Teil ist identisch mit dem Teil des Aufzählungstypen.

Komponenten-Eigenschaften

Komponenten-Eigenschaften werden verwendet, um z.B. den Anwender ein Zielobjekt auswählen zu lassen.

Es soll z.B. ein Ergebnis in einem Edit-Feld ausgewählt werden, welches der Programmierer vorher im Objektinspektor einstellen festlegen kann.

private
  FEdit: TEdit;
  { Private-Deklarationen }
protected
  { Protected-Deklarationen }
public
  { Public-Deklarationen }
published
  property Edit: TEdit read FEdit write FEdit;
  { Published-Deklarationen }

In der Komponente selbst kann dann, z.B. die Text Eigenschaft des ausgewählten Edit-Feldes geändert werden:

procedure TBeispielComp.ChangeText;
begin
  FEdit.Text := 'Text wurde geändert';
end;

Hier kann es allerdings zu Problemen kommen, wenn die verknüpfte Komponente destroyed wird. Das muss natürlich noch abgefangen werden. Da die Komponente davon aber benachrichtigt wird, kann man FEdit rechtzeitig auf nil setzen. Dies geschieht über die Notification-Methode. Sie wird bei Änderungen von Komponenten (z.B. beim Erzeugen oder Löschen) aufgerufen. Die Deklaration der Methode sieht folgendermaßen aus:

protected
  procedure Notification(AComponent: TComponent; Operation: TOperation); override;

Die Implementierung ist ebenfalls recht simpel. Zuerst werden durch den Aufruf der Anweisung inherited, die bisherigen Methodenimplementationen aufgerufen. Die If-Anwesung überprüft, ob die Komponente, die mit der Eigenschaft Edit verknüpft ist, entfernt wurde. Ist dies der Fall wird die entsprechende Eigenschaft auf nil gesetzt. Die komplette Implementierung sieht so aus:

procedure TBeispiel.Notification(AComponent: TComponent; Operation: TOperation);
begin
  inherited Notification(AComponent, Operation);
  if (Operation=opRemove) and
     (FEdit<>nil) and
     (AComponent=Edit) then
    Edit:=nil;
end;

Objekt-Eigenschaften

Bei Objekt-Eigenschaften werden ganze Objekte im Objektinspektor angezeigt. Ein oft benutzes Objekt ist das TFont-Objekt, welches in jeder von TControl abgeleiteten Komponente zu finden ist.
Im Großen und Ganzen funktioniert das Einbinden eines Objekts in eine Komponente wie das normale Hinzufügen einer Eigenschaft.

type
  TBeispielComp = class(TComponent)
  private
    FFont: TFont;
    { Private-Deklarationen }
  protected
    { Protected-Deklarationen }
  public
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
    { Public-Deklarationen }
  published
    property Font: TFont read FFont write FFont;
    { Published-Deklarationen }
  end;

Bekannterweise kann man auf Klassen und Objekte erst zugreifen, wenn sie initialisiert wurden. Dies geschieht im Constructor Create, in dem eine Instanz von TFont erstellt wird. Da die Zuweisung Speicher belegt, muss dieser später auch wieder freigegeben werden. Dies geschieht im Destructor Destroy. Der Quelltext der Constructor bzw. Destructor-Procedure sieht folgendermaßen aus:

constructor TBeispielComp.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);
  FFont:=TFont.Create;
end;

destructor TBeispielComp.Destroy;
begin
  FFont.Free;
  inherited Destroy;
end;

Der Constructor wird aufgerufen, wenn die Komponente initialisiert wird, der Destructor beim Entfernen.
Beispielprogramm: Download (1 KB)