Dyamische Menüs zur Laufzeit



  • Guten Morgen,

    ich möchte zur Laufzeit unterschiedliche Menüpunkte zu einem MenuItem hinzufügen und auch wieder entfernen. Die dynamischen Menüpunkte sind die Titel der aktuellen MDI Kindfenster eine MDI Anwendung.
    Das Ganze soll in etwa so aussehen

    Datei Bearbeiten Ansicht Fenster // 
                             - Horizontal anordnen
                             - Vertikal anordnen
                             -----------------------
                             - MDI Kindfenster 1 (dynamisch)
                             - MDI Kindfenster 2 (dynamisch)
    

    Ansatz 1:
    Ich habe mir überlegt, eine Action für das MenuItem "Fenster" zu definieren und in dessen OnUpdate Event die Untermenüpunkte neu aufzubauen. Leider funktioniert das nicht so, wie gedacht, da jede Änderung am Menüpunkt ein weiteres Update Event nach sich zieht und in einer Endlosschleife endet.

    Ansatz 2:
    Da das OnUpdate Event nur aufgerfuen wird, wenn ein Menüpunkt angezeigt wird lasse ich das Menü im OnUpdate Event Handler des Menüpunktes "Horizontal anordnen" aufbauen. Leider klappt das auch nicht, da die Anzahl der Untermenüpunkte des Menüeintrags "Fenster" nicht durch das Aktualisieren eines seiner Untermenüs verändert werden darf.

    Ansatz 3:
    Jedes Mal, wenn ein neues MDI Fenster erzeugt oder zerstört wird fügt es einen Menüeintrag zum Menü "Fenster" hinzu bzw. entfernt diesen wieder. Da ich aber einige unterschiedliche Kindfenstertypen habe und es keinen Event Handler für die entsprechenden Ereignisse gibt (zB. OnMDIChildCreated/Destroyed) müsste ich jede Fensterklasse anfassen, um die Funktionalität zu implementieren, und das will ich mir eigentlich sparen.



  • Eigentlich müsste doch die TForm Eigenschaft WindowMenu genau das machen was du möchtest.
    Als Beispiel erstell mal ein neues Projekt MDI-Anwendung da ist schon die Funktionsweise vorhanden.



  • Zum ersten Ansatz. Hast Du mal versucht einen Schalter (bool) einzufügen der dir das Update nach dem ersten Aufruf sperrt? Das ist wahrscheinlich nicht unbedingt elegant, sollte aber funktionieren.



  • @vergisses:
    Hab mir mal eine Testanwendung gebastelt und das WindowMenu ausprobiert. Irgendwie passiert da bei mir nix, wahrscheinlich muss man noch irgendwo irgendein Attribut setzen. Laut Hilfe soll es aber genau das machen, was du beschrieben hast, Danke.

    @Hundeman
    Etwas Ähnliches habe ich bereits versucht, indem ich das OnUpdate NotifyEvent der Action während der Anpassung des Menüs auf NULL und hinterher wiederhergestellt habe. Die Nofitications scheinen aber über die Windows Message Queue zu laufen und werden nach Verlassen des OnUpdate Handlers bearbeitet, wo das NotifyEvent bereits wiederhergestellt ist.

    Ich habe jetzt eine kleine utility Klasse gebaut, die sich auf das Activate/Deactivate Event des MDI Kindfensters regstrieren und eine Nachricht an das MDI Hauptfenster schicken. Jetzt kann ich auf Create/Destroy Events reagieren und das Menü entsprechend anpassen.



  • DocShoe schrieb:

    @vergisses:
    Hab mir mal eine Testanwendung gebastelt und das WindowMenu ausprobiert. Irgendwie passiert da bei mir nix, wahrscheinlich muss man noch irgendwo irgendein Attribut setzen. Laut Hilfe soll es aber genau das machen, was du beschrieben hast, Danke.

    Schonmal den MDI-Anwendungs-Wizard ausprobiert? Der setzt alle nötigen Einstellungen.

    Wenn es dir nur um das Window-Menu geht, sollte es reichen, die WindowMenu-Eigenschaft des MDI-Formulares auf das "Window"-Menu-Item zu setzen (nicht für die MDI-Childs). Falls du auch die restlichen Menueinträge dynamisch zusammenfügen willst, erstelle auf den MDI-Child-Formularen einfach auch ein TMainMenu. Mithilfe von TMenuItem::GroupIndex kannst du dann festlegen, wo die Menueinträge landen. Wenn du z.B. für "Datei" und "Bearbeiten" GroupIndex auf 0, für "Fenster" und "Hilfe" auf 2 und für alle Toplevel-Menu-Items des MDI-Childs auf 1 setzt, dann werden die Menueinträge des Child-Formulars zwischen "Bearbeiten" und "Fenster" eingefügt.



  • DocShoe schrieb:

    @Hundeman
    Etwas Ähnliches habe ich bereits versucht, indem ich das OnUpdate NotifyEvent der Action während der Anpassung des Menüs auf NULL und hinterher wiederhergestellt habe. Die Nofitications scheinen aber über die Windows Message Queue zu laufen und werden nach Verlassen des OnUpdate Handlers bearbeitet, wo das NotifyEvent bereits wiederhergestellt ist.

    Ich dachte da an etwas anderes. Du hüllst den ganzen Code innerhalb der On Update methode in eine if-Bedingung. Diese kannst du mit einer bool Variable ein und ausschalten. Ausgeschaltet wird die innerhalb der bedingung und wieder eingehschaltet im else Zweig. Somit lässt sich die Anweisung dann nur alle zwei Aufrufe ausführen.


Anmelden zum Antworten