Eigenschaft einer unbekannten Klasse ändern

Hallo!
Ich weis nicht genau wie ich mein Problem erklären soll,
aber ich versuche es mal.

Nehmen wir einmal an ich habe ein Formular mit 3 Komponenten (Label1,Panel1,Memo1).

Nun möchte ich zB auf folgende Art die Eigenschaft verändern:


procedure TForm1.objClick(Sender: TObject)
begin
with Sender do Alignment := taLeftJustify;
end;

Wenn ich nun hingehe und weiss um welche Klasse es sich handelt ist das alles kein Problem … zB:


with Sender as TLabel do Aligment := taLeftJustify;

-> Das bringt mir aber nicht viel, da ich sehr viele unterschiedliche Komponenten verschiedener Klassen benutzte.

folgende Idee kam mir schon:


with Sender as Sender.ClassType do Aligment := taLeftJustify;

fazit: Ich bin verzweifelt, normalerweise hab ich bis jetzt noch alles selbst herausgefunden.

… also helft mir :wink:

Harald

Hi Harald,

Nehmen wir einmal an ich habe ein Formular mit 3 Komponenten
(Label1,Panel1,Memo1).

Nun möchte ich zB auf folgende Art die Eigenschaft verändern:


procedure TForm1.objClick(Sender: TObject)
begin
with Sender do Alignment := taLeftJustify;
end;

Das geht nicht, da der Sender vom Typ TObject ist, und die Klasse TObject mit der Eigenschaft Alignment überhaupt nix am Hut hat.

Wenn ich nun hingehe und weiss um welche Klasse es sich
handelt ist das alles kein Problem … zB:


with Sender as TLabel do Aligment := taLeftJustify;

Das ist die erste Möglichkeit. Bei „Sender AS TLabel“ wird noch überprüft, ob Sender wirklich vom Typ TLabel ist. Wenn dies nicht der Fall ist, wird friedlich eine Exception ausgelöst.

Die zweite Möglichkeit ist „TLabel(Sender).Alignment := …“. Das nennt man Typecasting. Es geschieht direkt und „roh“, d. h. ohne Sicherheitsabfrage. Falls Sender gar nicht vom Typ TLabel ist, sind die Folgen unabsehbar (Programm-Absturz). Diese Methode sollte man daher nur anwenden, wenn absolut sichergestellt ist, daß der Sender auch wirklich den entsprechenden Typ hat.

-> Das bringt mir aber nicht viel, da ich sehr viele
unterschiedliche Komponenten verschiedener Klassen benutzte.

Wo genau ist Dein Problem?

folgende Idee kam mir schon:


with Sender as Sender.ClassType do Aligment := taLeftJustify;

Vielleicht so:

IF (Sender=Memo1) THEN Memo1 .Alignment := …
IF (Sender=Panel3) THEN Panel3.Alignment := …
IF (Sender=Memo5) THEN Memo5 .Alignment := …

Nein, das kann man leider nicht weiter kompaktifizieren.

Etwas anderes wäre es, wenn Du z. B. die Eigenschaft „Tag“ abfragen wolltest. Tag ist bereits in TComponent definiert. Deshalb bräuchtest Du nicht zu schreiben

IF (Sender=Memo1) THEN Memo1 .Tag := …
IF (Sender=Panel3) THEN Panel3.Tag := …
IF (Sender=Memo5) THEN Memo5 .Tag := …

sondern könntest die Sache erledigen mit

IF (Sender IS TComponent) THEN TComponent(Sender).Tag := …

oder

(Sender AS TComponent).Tag := …

oder direkt typegecastet

TComponent(Sender).Tag := …

Das funktioniert, weil jedes Memo automatisch auch vom Typ TComponent ist, ebenso jedes Edit, jedes Panel, jeder Button etc.

Hat Dir das geholfen?

Mit freundlichem Gruß
Martin

Hallo,

IF (Sender=Memo1) THEN Memo1 .Alignment := …
IF (Sender=Panel3) THEN Panel3.Alignment := …
IF (Sender=Memo5) THEN Memo5 .Alignment := …

Nein, das kann man leider nicht weiter kompaktifizieren.

aber verallgemeinern:

if Sender is TMemo then TMemo(Sender).Lines.add('blabla');
if Sender is TPanel then TPanel(Sender).Text := 'bloblo';

Gruss, Niels

Hallo Harald,

ich wüsste nur folgende Möglichkeit (dabei musst du eventuell noch weitere Klassentypen hinzufügen, die du verwendest, und die über die Eigenschaft Alignment verfügen.

procedure TForm1.ObjectClick(Sender: TObject);
begin
try
with Sender as TLabel do Alignment := taLeftJustify;
except
end;
try
with Sender as TMemo do Alignment := taLeftJustify;
except
end;
try
with Sender as TPanel do Alignment := taLeftJustify;
except
end;
end;

Du kannst natürlich auch über Abfragen herausfinden, welchen Typen das Objekt hat, aber dann funktioniert es nicht ohne weiteres mit abgeleiteten Objekten…

Hallo … vielen Dank für die schnellen Antworten,
allerdings hilft mir das nicht weiter,
denn soweit war ich auch schon.

Man stelle sich vor ich würde den Objektinspektor von Delphi nachbauen, der mit fast allen Komponenten der VCL auch zur Laufzeit zurechtkommt.

Das wäre halt ein sehr sehr großer Aufwand mit
if Objekt = TLabel then TLabel(Objekt).Eigenschaft
mein Problem zu lösen.

Deshalb hab ich auf eine einfachere Art der Programmierung gehofft.

Kennst sich jemand mit TPropertyEditor aus… vielleicht ist das meine Lösung.

mfg

Harald

Hallo,

Du kannst natürlich auch über Abfragen herausfinden, welchen
Typen das Objekt hat, aber dann funktioniert es nicht ohne
weiteres mit abgeleiteten Objekten…

der is-Operator erfasst das sehr wohl. Z.B. Die Abfrage

 if Sender is TWinControl then ...

wird ausgeführt, wenn Sender ein TWinControl oder ein Nachfahre davon ist (zB ein TButton o.ä.)

Gruss, Niels

Hallo,

Man stelle sich vor ich würde den Objektinspektor von Delphi
nachbauen, der mit fast allen Komponenten der VCL auch zur
Laufzeit zurechtkommt.

Das wäre halt ein sehr sehr großer Aufwand mit
if Objekt = TLabel then TLabel(Objekt).Eigenschaft
mein Problem zu lösen.

Deshalb hab ich auf eine einfachere Art der Programmierung
gehofft.

Kennst sich jemand mit TPropertyEditor aus… vielleicht ist
das meine Lösung.

TPropertyEditor selbst ist nur die Basisklasse. Von ihr sind alle Eigenschaftseditoren abgeleitet, die der Objektinspektor benutzt. So zeigt er zB einen Listeneditor, wenn eine Stringlist (TMemo.Lines, TRadioGroup.Items etc) editiert werden muss. Jeder dieser Eigenschaftseditoren besitzt eine Register-Prozedur, über die der Objektinspektor diesen Editor einbinden kann. Es existieren eine Menge solcher Editoren: Einfachere zB für Strings, kompliziertere für die oben genannten Stringlisten oder gar DB-Feldeditoren. Wenn du also TPropertyEditor im Programm verwenden willst, müsstest du für jede Eigenschaft, die du im Programm ändern willst, einen neuen Editor als Nachfahre von TPropertyEditor schreiben (die originalen kannst du nicht verwenden, da es sich um visuelle Editoren handelt). Außerdem müsstest du eine Schnittstelle zur Register-Prozedur schreiben, damit dein Prog die Editoren überhaupt erkennt.

Deshalb mein Tipp:

Überleg dir, welche Komponenten und welche Eigenschaften für dein Programm in Frage kommen. Dann schau nach, in welchem Vorfahren die Eigenschaft zuerst auftaucht und benutze dann den is -Operator:

 if Sender is TCustomEdit then TCustomEdit(Sender).MaxLenght := 20;

Viele Grüße,
Niels

Wieder was gelernt! Danke!

[Bei dieser Antwort wurde das Vollzitat nachträglich automatisiert entfernt]