MDI Probleme



  • Ich möchte eine Anwendung machen mit mehreren Kindfenstern.
    Ich starte das Programm und er liest mehrere Dateien mit Daten ein, welche in Eingabefelder zum Teil dann kommen sollen.

    Wenn man im MDIChild OnShow Ereignis eine Update() Funktion aufruft die eben die Felder ausfüllen soll, dann erhält man einen Zugriffsfehler, wohl weil die Daten noch nicht komplett eingelesen sind von der Hauptform.

    Dann dachte ich, ich mach das Update() über die Hauptform ala MDIChildren[0]->Update();
    Da werd ich aber blockiert, da MDIChildren Update() nicht kennen will. Auch verständlich, aber somit auch dieser Weg versperrt.

    Auch schade find ich es, das man MDIChild nicht verbergen kann und nur ein bestimmtes anzeigen.

    Falls jemand weiss wann und wie ich meine Update() Funktion aufrufen muss, damit die geladenen Daten in des Childfensters Eingabemaske einegtragen werden können, wäre echt toll! :xmas1:

    (Eine Timer Funktion ist keine Option)



  • Wenn du deine Dateien im Konstruktor der Hauptform einliest, dann sollte das eigentlich abgeschlossen sein, bevor die Childs aufgebaut werden.
    Das "Füllen" der Childs erfolgt sinnvollerweise als letzter Schritt im OnCreateMDIChild (bezogen auf das Standard-MDI-Projekt des BCB).
    Ob hier aber tatsächlich die Ursache für deine Zugriffsverletzung liegt, lässt sich anhand der spärlichen Informationen nicht sagen.

    kampfmuffin schrieb:

    Auch schade find ich es, das man MDIChild nicht verbergen kann und nur ein bestimmtes anzeigen.

    Maximiere das Child, dann ist nur dieses sichtbar. Wenn du immer nur ein Child anzeigen willst, dann ist MDI wahrscheinlich nicht das Richtige, eine normale Form und TFrame könnte da eher passen.



  • Ich lade die Daten in TForm1::OnCreate()
    Die Update() Funktion im MDIChild in TForm2::TForm2(TComponent Owner)* und andermal auch in TForm2::OnShow() abgelegt, bei beiden bekomme ich dann in der Update() Funktion ein "ungültige Gleitkommaoperation" beim ausführen.
    Wenn ich die Update() Funktion auf einen Button lege und per Hand betättige klappt alles wunderbar.

    Ja das MDIChild mach ich momentan mit WindowState maximiert. Ich dachte nur daran das wenn man es seperat aufrufen kann, dann dort kein Fehler mehr kommen sollte.
    Eine Möglichkeit die ich noch sehen würde, wäre ein Begrüssungs MDIChild Fenster vorzuschalten und über Menü Aufruf auch erst das Update zu machen.

    Mit TFrames hatte ich noch garnichts zu tun, mal anschauen. Mehrere normale Fenster wäre nicht so ideal, da das mal 10 "MDIChild" werden sollen und jedes so gross wie die MainForm.



  • TFrame ist eine Art Container für grafische Komponenten, den du auf der Form nach Wunsch ein- oder ausblendest.

    Was die Child-Probleme angeht: sieh dir an, wie das Erzeugen und Befüllen der Fenster im bereits erwähnten Standard-MDI-Projekt gelöst ist, ggf. kannst du das auch bei deinem Programm umsetzen.



  • Gibt es dieses Beispiel auch im BCB5? Ich kann es nirgends finden. 😞



  • Datei -> Neu -> [Andere ->] Projekte -> MDI Anwendung



  • Also dieses Beispiel wirft mehr Fragen auf als Antworten. 😮

    A) Wieso sieht man beim Start nicht das MDIChild?
    😎 Wieso sind die ganzen Funktionen für Fenster nebeneinander/übereinander etc garnicht belegt, jedoch funktionieren. *doppel eek*

    Bezogen auf A, bei mir ist das MDIChild bei Programmstart bereits mit sichtbar, ich bekomme es auch nicht ausgeblendet, und wird mit Daten aufgefüllt. In dem Beispiel wird über "Neu" eine Kopie erstellt und mit Daten geladen. Das ein ganz anders gelagerter Fall. Leider.

    Bei mir wird in der MainForm global die Daten geladen, auf welche die MDIChilds zugreifen können sollen.



  • Ich habe mich mal mit Frames beschäftigt und die scheinen in der Tat "cooler" zu sein und nicht ganz so eingeschränkt wie MDIChild. Danke für den Tipp!

    Jetzt möchte ich zur Laufzeit ein Frame setzen und austauschen.
    Ich habe eine MainForm mit zwei Button. Mit dem Klick auf einen Button soll ein Frame in der MainForm angezeigt werden und ein bereits vorhandenes ausgeblendet.

    TFrame2 *Frame21 = new TFrame2(this);
    Frame21->Parent = this;

    Klappt auch super. Meine Frage wäre jetzt, wenn ich sehr viele Frames zur Auswahl habe, wie entferne ich das vorherige Frame am Besten, ohne dessen Namen zu kennen?

    Meine Lösung ginge jetzt in diese Richtung:

    TComponent *Comp;
        for (int i=0;i<ComponentCount-1;i++)
        {
            Comp = Components[i];
            if (~~Comp~~==vom Typ TFrame)
            {
                RemoveComponent(Comp);
            }
        }
    

    Allerdings weiss ich nicht, wie in der if rausbekommen soll, ob es ein TFrame ist, da die Frames "MyFrame1", "AnderesFrame" heissen.

    Ist da jemand draussen, der eventuell die Lösung kennt und mir helfen möchte? :xmas1:



  • Hallo

    grundsätzlich geht die Typüberprüfung so

    if (dynamic_cast<TMyFrame*>(Comp))
    

    (dazu muß in den Compileriptionen RTTI aktiviert sein)

    Allerdingts ist das nicht sehr effizient, besser ist es einen eigenen Pointer vom Typ TMyFrame als Member des MainForms zu deklarieren. Dort wird immer das aktuelle Frame zugewiesen, so kannst du es auch leicht wieder löschen, oder andere Manipulationen durchführen.

    bis bald
    akari



  • Danke für deinen guten Tipp.

    Wäre das also die optimalste Lösung?

    In der MainForm.h Klasse ist *TFrame TMyFrame; erklärt

    // Löschen falls vorhanden
    if (TMyFrame!=NULL) delete TMyFrame;

    // Neues TFrame eintragen
    TFrame3 *Frame3 = new TFrame3(this);
    Frame3->Parent = this;
    Frame3->Left=200;

    // aktuelles TFrame merken
    TMyFrame = Frame3;



  • Hallo

    ja das ist die optimale Lösung.
    Nur finde ich die Bezeichnung der Variable TMyFrame schlecht. Mit T sollte man nur Klassen an sich kennzeichnen, konkrete Variablen nicht (Das betrifft nur das menschliche Verständnis, dem Compiler ist es egal solange es eindeutig ist).
    Also nenn die Variable nur MyFrame und dein Code ist noch übersichtlicher.

    bis bald
    akari



  • Danke für deine Hilfe! :xmas1:


Anmelden zum Antworten