Frame mit Funktion erweitern und aufrufen
-
Ich habe in meiner TForm1 eine Variable *TFrame MyFrame; hinzugefügt und wenn ich ein Frame auf meienr TForm1 integriere setze ich den Pointer darauf.
So das klappt auch alles super, jetzt habe ich jedoch der TFrame Klasse weitere Funktionen hinzugefügt, aller meiner TFrames die selbe, aber unterschiedlichen Inhalts.
Problem ist nun das diese Funktionen keine Member der Klasse TFrame sind und natürlich ein Aufruf ala MyFrame->newFunc(); mit Fehler quittiert wird, obwohl Frame1->newFunc(); sehr wohl existiert.
Anwendungsbeispiel wäre hier das ich eine Anwendung schaffe mit vielen Frames und einer Sprachauswahl und nicht eine switch bzw if-else System schaffen möchte um das aktuelle gewählte Frame die Sprache zu updaten, sondern direkt nur die dafür zuständige Funktion aufrufen möchte.
Puh, kam das irgendwie verständlich durch? Das einfügen in die TForm1 mach ich bereits über ein Template, womit dies allgemein passiert, dort sind aber auch keine nicht TFrame Funktionen von belang.
Ich habe jetzt eine ComboBox welche die Form1->UpdateSprache() aufruft und in dieser Funktion soll quasi ebenfalls die Funktion UpdateSprache() des aktuell gewählten TFrames aufgerufen werden. Quasi eben MyFrame->UpdateSprache(); was so ja nun nicht funktioniert.
-
Hallo
Du hast da erstmal ein Grundsätzliches Problem : kannst du die einzelnen von außen zugänglichen Eigenschaften/Methoden der Frames so verallgemeinen das du eine Basisklasse herausbekommst? Wenn die Frames sich nicht in ein Interface packen lassen hast du keine andere Wahl als entweder den allgemeinen TFrame-Zeiger jedesmal zu casten bzw. für jeden Frame-Typ einen eigenen Zeiger zu definieren von denen aber immer nur einer gültig (d.h. nicht 0) ist.
Wenn du die einzelnen Frames in ein Interface packen kannst must du überlegen wie du das umsetzt. Wenn du nicht auf die Bearbeitung der Frames zur Entwurfszeit mit Objektinspektor angewiesen bist sondern alles mit Quellcode machen kannst könntest du die ganzen Frames manuell im Quellcode definieren. Der Vorteil : Nun kannst du erstmal eine Basisklasse von TFrame ableiten die alle polymorphen Methoden bekommt die von außen her anzusprechen sind. Von dieser Basisklasse leistest du nun jedesmal die konkreten Frames ab. Nun reicht ein Zeiger auf die Basisklasse um alle Frametypen zu verwalten.
bis bald
akari
-
Bin auf den Objektinspektor angewiesen, da die Frames sehr komplex sind. Soll quasi ein Pluginsystem sein. Ich binde Frames in mein Projekt ein und brauch nur eine Zeile Code(neben der include) um diese in das MainMenu aufrufbar einzubinden und nutzbar zu machen. Das ist auch soweit fertig.
Problem ist nun wie richtig erkannt hast der Zugriff auf Funktionen die keine Member der TFrame sind und da es verdammt viele Frames sind (~20) finde ich die Lösung doof alle Frames direkt abzufragen.
*grübel*
-
Ich habe es mal nach deinem anraten probiert
#ifndef Unit2H #define Unit2H //--------------------------------------------------------------------------- #include <Classes.hpp> #include <Controls.hpp> #include <StdCtrls.hpp> #include <Forms.hpp> //--------------------------------------------------------------------------- class TFrame2 : public TFrame { __published: TButton *Button1; private: public: __fastcall TFrame2(TComponent* Owner); }; //--------------------------------------------------------------------------- // Fertiges Frame in diese Klasse übergeben und damit in Form1 dann arbeiten class TMyFrame2 : public TFrame2 { private: public: void __fastcall myFunc(); }; //--------------------------------------------------------------------------- extern PACKAGE TFrame2 *Frame2; extern PACKAGE TMyFrame2 *MyFrame2; //--------------------------------------------------------------------------- #endifTFrame2 *Frame2; TMyFrame2 *MyFrame2; //--------------------------------------------------------------------------- __fastcall TFrame2::TFrame2(TComponent* Owner) : TFrame(Owner) { } //--------------------------------------------------------------------------- // Hier kann ich ja nun auf alle Funktionen und Komponenten von Frame2 zugreifen void __fastcall TMyFrame2::myFunc() { // Button1 ist ursprünglich aus TFrame2 Button1->Caption = "Test"; }TForm1 *Form1; //--------------------------------------------------------------------------- __fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner) { } //--------------------------------------------------------------------------- void __fastcall TForm1::Button1Click(TObject *Sender) { TMyFrame2* Modul = new TMyFrame2(this); // FEHLERZEILE }Leider mit diesem Ergebnis
E2125 Compiler konnte Standardkonstruktor nicht für die Klasse 'TMyFrame2' generieren.
Versteh ich leider nicht.

-
Hallo
Die Fehlermeldung ist doch eindeutig : Bei TMyFrame2 fehlt ein Konstruktor. Du brauchst wie bei TFrame2 einen mit dem Owner-Parameter.
bis bald
akari
-
Autsch! Ja klar und es funktioniert nun auch. Ich kann das Frame einfügen und auf die selbstdefinierte Funktion zugreifen. leider funktioniert dies nur mit einem(eins) Frame im Projekt.
Ich habe die TFrame1, TFrame2, TFrame3... und benutze diese dann in TMyFrame1, TMyFrame2, TMyFrame3... und habe somit keine einheitliche Basisklasse und kann mit MyFrame nicht darauf allgemein zugreifen. Dumm gelaufen

-
Hallo
Du must die Basisklasse die im Beispiel TFrame2 heißt ja auch in eine eigene Unit auslagern (Include-Guards nicht vergessen), und diese Unit von allen Frame-Headern aus einbinden. Dann kannst du alle Frames von der selben Basisklasse ableiten.
bis bald
akari
-
Ich denke nicht das dies klappt. Ich setze ja zur Entwicklungszeit die Komponenten und fülle diese mit Leben für jedes Frame. Da kann man leider nichts verallgemeinern, bzw ich missverstehe was du meinst.
Ich glaube aber die Lösung geht wesentlich einfacher. Das Problem ist ja in meiner Header von TForm1 worauf ich auf die Frames zgreifen möchte das "TFrame *MyFrame".
wenn ich das jetzt stattdessen auf "void *MyFrame" setze, müsste ich dieses void doch mit jedem Frame füllen können. Das war mal so mein Gedanke.
So binde ich mein Frame ein
InsertFrame<TFrame1>(); template<typename T> void __fastcall TForm1::InsertFrame() { if (MyFrame!=NULL) delete MyFrame; T* Modul = new T(this); Modul->Parent = this; Modul->Left = 0; Modul->Top = 0; MyFrame = Modul; // definiert als void *MyFrame }funktioniert auch mit void*. yatta! Aber wenn ich jetzt "MyFrame->myFunc();" aufrufe, erhalte ich
E2294 Auf linker Seite der Struktur ist . oder .* erforderlich.
bzw
E2288 Zeiger auf Struktur auf linker Seite von -> oder von ->* erforderlich
Irgendwas fehlt mir oder es ist ein Holzweg.
-
Hallo
Fabi4n schrieb:
Ich denke nicht das dies klappt. Ich setze ja zur Entwicklungszeit die Komponenten und fülle diese mit Leben für jedes Frame. Da kann man leider nichts verallgemeinern, bzw ich missverstehe was du meinst.
Ich weiß nicht ob das Ändern der Basisklasse bei generierten Frames funktioniert, so etwas habe ich noch nicht gebraucht. Ein Versuch wärs auf jedenfalls Wert.
Ansonsten must du das Interface noch zwischen Frame und Form schalten, siehe Adapter-Pattern.Ich glaube aber die Lösung geht wesentlich einfacher. Das Problem ist ja in meiner Header von TForm1 worauf ich auf die Frames zgreifen möchte das "TFrame *MyFrame".
wenn ich das jetzt stattdessen auf "void MyFrame" setze, müsste ich dieses void doch mit jedem Frame füllen können. Das war mal so mein Gedanke.
...
funktioniert auch mit void. yatta! Aber wenn ich jetzt "MyFrame->myFunc();" aufrufe, erhalte ichE2294 Auf linker Seite der Struktur ist . oder .* erforderlich.
bzw
E2288 Zeiger auf Struktur auf linker Seite von -> oder von ->* erforderlich
Irgendwas fehlt mir oder es ist ein Holzweg.
Ja das wird nichts. void* ist ein vollkommen Typloser Zeiger. Du kannst zwar alles reinstecken aber weist dann nicht mehr was drin ist. Damit must du wieder manuell casten und wieder beim Ausgangsproblem.
bis bald
akari
-
Habs hinbekommen. Vielen Dank für deine großartige Hilfe!!!
Habe von TFrame eine leere Klasse erstellt mit der gemeinsamen Funktion und diese als Basisklasse dann für die Komponente geändert. Habs mit zwei Frames getestet und läuft. Danke nochmal!