Schreibaufwand veringern
-
Ich schreibe ein Programm, bei dem alles erst beim erstellen erzeugt wird um das Programm unendlich flexibel zu designen.
Während der Laufzeit kann man die Werte ändern und speichern lassen (speichern muss ich noch schreiben)Aber es gibt ein aufwandsproblem, von dem ich hoffe es lösen zu können, sonst wirds unangenehm viel arbeit.
Ich kann verschiedene Komponenten erstellen lassen, ist ja logisch, aber da liegt der Hund begraben. Ich zeig einfach mal code, sonst ist das schwer zu verstehen:
Beispielsweise diese stelle:if (Sender->ClassName() == "TImage") { Editor->LiKant->Text = IntToStr(dynamic_cast<TImage*>(Sender)->Left); Editor->ObKant->Text = IntToStr(dynamic_cast<TImage*>(Sender)->Top); Editor->Breite->Text = IntToStr(dynamic_cast<TImage*>(Sender)->Width); Editor->Höhe->Text = IntToStr(dynamic_cast<TImage*>(Sender)->Height); Editor->Komponum->Value = StrToInt(dynamic_cast<TImage*>(Sender)->Name.SubString(Sender->ClassName().Length()+1,dynamic_cast<TImage*>(Sender)->Name.Length()-Sender->ClassName().Length())); Editor->FormsundBase->Text = dynamic_cast<TImage*>(Sender)->Parent->Name; } if (Sender->ClassName() == "TPanel") { Editor->LiKant->Text = IntToStr(dynamic_cast<TPanel*>(Sender)->Left); Editor->ObKant->Text = IntToStr(dynamic_cast<TPanel*>(Sender)->Top); Editor->Breite->Text = IntToStr(dynamic_cast<TPanel*>(Sender)->Width); Editor->Höhe->Text = IntToStr(dynamic_cast<TPanel*>(Sender)->Height); Editor->Komponum->Value = StrToInt(dynamic_cast<TPanel*>(Sender)->Name.SubString(Sender->ClassName().Length()+1,dynamic_cast<TPanel*>(Sender)->Name.Length()-Sender->ClassName().Length())); Editor->FormsundBase->Text = dynamic_cast<TPanel*>(Sender)->Parent->Name; }
Für jeden Typen müsste ich das nun erweitern, gibt es nicht eine bessere möglichkeit ? (Geschwindigkeit ist nicht wichtig - Ist ja nur ein (kleines) Hobbyprojekt
)
-
Hallo,
Wozu die vielen dynamic_cast? Einmal reicht.
TImage* image = dynamic_cast<TImage*>(Sender); TPanel* panel = dynamic_cast<TPanel*>(Sender); if (image) { Editor->LiKant->Text = image->Left; Editor->ObKant->Text = image->Top; Editor->Breite->Text =image->Width; Editor->Höhe->Text = image->Height; Editor->Komponum->Value = StrToInt(image->Name.SubString(Sender->ClassName().Length()+1,image->Name.Length()-Sender->ClassName().Length())); Editor->FormsundBase->Text = image->Parent->Name; } if( panel ) { Editor->LiKant->Text = panel ->Left; Editor->ObKant->Text = panel ->Top; Editor->Breite->Text = panel ->Width); Editor->Höhe->Text = panel ->Height; Editor->Komponum->Value = StrToInt(panel ->Name.SubString(Sender->ClassName().Length()+1,panel ->Name.Length()-Sender->ClassName().Length())); Editor->FormsundBase->Text = panel ->Parent->Name; }
-
Tim06TR schrieb:
if (Sender->ClassName() == "TImage")
Das ist nicht ganz korrekt. Besser wäre das:
if (dynamic_cast<TImage*> (Sender))
Tim06TR schrieb:
Für jeden Typen müsste ich das nun erweitern, gibt es nicht eine bessere möglichkeit ? (Geschwindigkeit ist nicht wichtig - Ist ja nur ein (kleines) Hobbyprojekt
)
Freilich gibts die. Hast du dich noch nie gefragt, wie es funktioniert, daß alle Eigenschaften, die du so im Form-Designer und Objektinspektor konfigurierst, zur Laufzeit auf deine Objekte übertragen werden?
Die Lösung heißt RTTI bzw. Reflection. Nützliche Links zum Weiterlesen:
http://www.blong.com/Conferences/BorConUK98/DelphiRTTI/CB140.htm
http://delphi.about.com/od/windowsshellapi/a/reader-writer.htm
http://blocko.blogspot.com/2005/02/delphi-stream-your-objects.html
http://www.gumpi.com/Blog/2007/10/09/DelphiLanguageDidYouKnow.aspxAlles auf Englisch und für Delphi, aber viel deutschsprachiges Material dazu gibts nicht, und für C++Builder läuft das alles analog.
-
oder dur castste gleich nach TControl, da die ja die Basisklasse beider Komponenten ist und auch alles anbietet was du abfragst.
-
audacia schrieb:
Freilich gibts die. Hast du dich noch nie gefragt, wie es funktioniert, daß alle Eigenschaften, die du so im Form-Designer und Objektinspektor konfigurierst, zur Laufzeit auf deine Objekte übertragen werden?
Die Lösung heißt RTTI bzw. Reflection. Nützliche Links zum Weiterlesen:
http://www.blong.com/Conferences/BorConUK98/DelphiRTTI/CB140.htm
http://delphi.about.com/od/windowsshellapi/a/reader-writer.htm
http://blocko.blogspot.com/2005/02/delphi-stream-your-objects.html
http://www.gumpi.com/Blog/2007/10/09/DelphiLanguageDidYouKnow.aspxAlles auf Englisch und für Delphi, aber viel deutschsprachiges Material dazu gibts nicht, und für C++Builder läuft das alles analog.
Englisch ist normalerweise kein Problem, danke für diese vertvollen Informationen.
Braunstein schrieb:
oder dur castste gleich nach TControl, da die ja die Basisklasse beider Komponenten ist und auch alles anbietet was du abfragst.
auch eine gute idee, mal sehen was sich daraus machen lässt, ich werde das wohl für die "standarteigenschaften" benutzen, und wenns komponentenspezifischer wird, ausnahmen mit if-Abfragen machen, aber bevor ich loslegen, lese ich mir die links von audacia durch.
-
der dritte und vierte Link von audacia erinnern mich an diesen FAQ Eintrag:
[url]http://www.c-plusplus.net/forum/viewtopic-var-t-is-39209.html
[/url]
der Erste ist am hilfreichsten (und am längsten).
btw:
Ich dachte, dass "Converting between enumerated type values and strings"
überhaupt nicht möglich wäre.
Das kann ich an anderen Stellen dieses Programms anwenden.&Danke
Gut das ich so früh gefragt habe (zumindest bei diesem Programm).
- so ich bau dann mal um.
-
(Triplepost - sry)
2 Fragen hab ich noch:
audacia schrieb:
Tim06TR schrieb:
if (Sender->ClassName() == "TImage")
Das ist nicht ganz korrekt. Besser wäre das:
if (dynamic_cast<TImage*> (Sender))
Warum soll ich ClassName() nicht benutzen ? (Hast du mit dieser Frage gerechnet ?
)
wenn ich eine Klasse (bzw den Pointer darauf) mit dem Konstruktor erstelle und ich den Owner angeben soll, der eigentlich immer die Form ist, was soll ich machen:
this->Owner
oder
this
und warum ? Ist es egal ?
-
Hallo
1. ClassName gibt den konkreten Klassennamen an, also ob die Instanz als TImage angelegt wurde. dynamic_cast gibt an ob die Klasse mit dem Argument über RTTI verwand ist, also ob die Instanz als TImage angelegt wurde oder eben auch mit einer Klasse die von TImage abgeleitet wurde.
Beispiel : Du hast eine Klasse TMyImage, die von TImage abgeleitet ist. Bei einer Instanz dieser Klasse würde ClassName == "TMyImage" sein und nicht "TImage", dynamic_cast liefert aber einen brauchbaren TImage-Zeiger.
Dieser Unterschied sollte berücksichtigt werden.2. Kommt drauf an was genau this in diesem Kontext ist, und ob du einen Owner verwenden willst oder nicht. Natürlich ist es meistens sinnvoll, das Form als Owner zu verwenden, denn schaden kann es nicht. Dadurch hast du sichergestellt, daß das neue Control auf jedenfall gelöscht wird, wenn das Form auch gelöscht wird. Und dynamisch erstellte Controls kannst du auch jederzeit dynamisch manuell wieder löschen, egal ob Owner oder nicht.
bis bald
akari
-
Tim06TR schrieb:
this->Owner
oder
this
Na ja, das sind zwei verschiedene Dinge. Vorausgesetzt wir befinden uns im Konstruktor eines Forms, dann ist this das Formular selbst und this->Owner ist wahrscheinlich die zu Grunde liegende TApplications-Instanz. Da die Komponenten die Du erzeugst wohl sowieso das Form als Parent haben, kannst Du das auch als Owner angeben. Nur bei Komponenten, die quasi auf Formularebene verwendet werden (so wie ein TDataModule), sollte man die TApplication-Instanz als Owner verwenden.
So hab ich mir das zumindest zusammengereimt...
-
DELETE
- Hier war mal nonsense zu lesen -
-
akari schrieb:
1. ClassName gibt den konkreten Klassennamen an, also ob die Instanz als TImage angelegt wurde. dynamic_cast gibt an ob die Klasse mit dem Argument über RTTI verwand ist, also ob die Instanz als TImage angelegt wurde oder eben auch mit einer Klasse die von TImage abgeleitet wurde.
Beispiel : Du hast eine Klasse TMyImage, die von TImage abgeleitet ist. Bei einer Instanz dieser Klasse würde ClassName == "TMyImage" sein und nicht "TImage", dynamic_cast liefert aber einen brauchbaren TImage-Zeiger.
Dieser Unterschied sollte berücksichtigt werden.Darüberhinaus garantiert die Übereinstimmung zweier Klassennamen nicht die Identität der Klassentypen selbst. Du kannst - etwa in verschiedenen Scopes - durchaus verschiedene Klassen gleichen Namens deklarieren.
-
Auch wenn es hier vielleicht keine Rolle spielt, der Test mit dynamic_cast ist um einigens schneller als über Classname (ist getestet).