Die Community zu .NET und Classic VB.
Menü

Tipp-Upload: VB.NET 0181: MDI-Variationen

 von 

Über den Tipp  

Dieser Tippvorschlag wird übernommen.

Der Vorschlag ist in den folgenden Kategorien zu finden:

  • Fenster
  • Menüs

Dem Tippvorschlag wurden folgende Schlüsselwörter zugeordnet:
MDI,addhandler,combobox

Der Vorschlag wurde erstellt am: 24.01.2008 06:08.
Die letzte Aktualisierung erfolgte am 05.03.2008 10:40.

Zurück zur Übersicht

Beschreibung  

Bei MDI-Anwendungen können sich Probleme ergeben, wenn die MDIChildren vom User weggeklickt werden.
Hier 2 Varianten des Umgangs damit:
1) Die Controlbox wird ausgeblendet, sodaß die Schaltfläche weg ist. Leider ist dann auch der Maximieren-Button weg, samt seiner 2 Brüder. Die Aktivierung der Children übernimmt ein MenuStripItem, welches im Designer dazu bestimmt wird.
2) Die Verwaltung der Children liegt bei einer ToolstripCombobox, die entweder ein Child-Exemplar, oder ein Type-Objekt des Childs enthält. Weggeklickte Children können anhand des Type-Objektes neu instanziert werden.

Insgesamt ist bei derartigen MDI-Workarounds zu überlegen ob die Funktionalität etwa des TabControls nicht besser geeignet ist.

Schwierigkeitsgrad

Schwierigkeitsgrad 2

Verwendete API-Aufrufe:

Download:

Download des Beispielprojektes [28,50 KB]

' Dieser Source stammt von http://www.activevb.de
' und kann frei verwendet werden. Für eventuelle Schäden
' wird nicht gehaftet.

' Um Fehler oder Fragen zu klären, nutzen Sie bitte unser Forum.
' Ansonsten viel Spaß und Erfolg mit diesem Source!
'
' Beachten Sie, das vom Designer generierter Code hier ausgeblendet wird.
' In den Zip-Dateien ist er jedoch zu finden.

' --------------- Anfang Projektgruppe MDI.sln ---------------
' -------------- Anfang Projektdatei MDI.vbproj --------------
' --------------- Anfang Datei frmChildTyp2.vb ---------------
Public Class frmChildTyp2

End Class

' ---------------- Ende Datei frmChildTyp2.vb ----------------
' --------------- Anfang Datei frmChildTyp3.vb ---------------
Public Class frmChildTyp3

End Class

' ---------------- Ende Datei frmChildTyp3.vb ----------------
' ----------------- Anfang Datei frmMain.vb  -----------------
Public Class frmMain

    Private Sub btMDIParent1_Click(ByVal sender As Object, ByVal e As EventArgs) _
                Handles btMDIParent1.Click

        Call (New frmMDIParent1).Show()

    End Sub

    Private Sub btMDIParent2_Click(ByVal sender As Object, ByVal e As EventArgs) _
                Handles btMDIParent2.Click

        Call (New frmMDIParent2).Show()

    End Sub

End Class

' ------------------ Ende Datei frmMain.vb  ------------------
' -------------- Anfang Datei frmMDIParent2.vb  --------------
Imports System.Reflection

Public Class frmMDIParent2

    ' Aufwändige Variante: Controlboxen der MDIChildren bleiben funktionstüchtig, Children werden
    ' erst auf Anforderung instanziert.
    ' Die Menustrip.MdiWindowList - Property ist hier nicht verwendbar, da sie nur geöffnete
    ' Children verwaltet, und weggeklickte nicht wieder herstellen kann.
    ' Also verwalte ich die Children in einer ToolstripCombobox.
    ' Ein gewisser Hack liegt darin, daß ausgenutzt wird, daß sowohl System.Reflection.Type als
    ' auch System.Windows.Forms.Form über eine "Name"-Property verfügen.
    ' In der Combobox wird entweder der Type des Childs, oder ein instanziertes Exemplar selbst
    ' geführt.
    ' Wird ein Index gewählt, so wird entweder das Exemplar aktiviert, oder es wird erst noch
    ' erzeugt, anhand der Type-Information
    ' Den Einträgen der Combo ist nicht anzusehen, ob sie einen Type-Namen oder den Namen eines
    ' ChildForm-Exemplars wiedergeben.

    Private Sub frmMDIParent_Load(ByVal sender As Object, ByVal e As EventArgs) Handles MyBase.Load

        With Me.MDIChildCombo

            .Items.AddRange(New Type() { GetType(frmChildTyp1), GetType(frmChildTyp2), _
                GetType(frmChildTyp3)})

            .ComboBox.DisplayMember = "Name"
            AddHandler .SelectedIndexChanged, AddressOf MDIChildCombo_SelectedIndexChanged
            .SelectedIndex = 0
        End With

    End Sub

    Private Sub MDIChildCombo_SelectedIndexChanged(ByVal sender As Object, ByVal e As EventArgs)

        If Me.MDIChildCombo.SelectedItem Is Nothing Then Return

        ' SelectedItem ist entweder ein Form oder ein Type
        Dim Frm As Form = TryCast(Me.MDIChildCombo.SelectedItem, Form)

        If Frm Is Nothing Then

            ' Type-Eintrag in der Combo durch neu erzeugtes Exemplar ersetzen
            Dim tpForm As Type = DirectCast(Me.MDIChildCombo.SelectedItem, Type)

            Frm = DirectCast(Activator.CreateInstance(tpForm), Form)

            With Me.MDIChildCombo
                RemoveHandler .SelectedIndexChanged, AddressOf MDIChildCombo_SelectedIndexChanged
                .Items(.SelectedIndex) = Frm
                AddHandler .SelectedIndexChanged, AddressOf MDIChildCombo_SelectedIndexChanged
            End With

            With Frm
                .MdiParent = Me
                AddHandler .FormClosed, AddressOf frmChild_FormClosed
                .Show()
            End With

        Else

            With Frm

                If .WindowState = FormWindowState.Minimized Then
                    .WindowState = Me.ActiveMdiChild.WindowState
                End If

                .BringToFront()
            End With

        End If

    End Sub

    Private Sub frmMDIParent_MdiChildActivate(ByVal sender As Object, ByVal e As EventArgs) _
                Handles Me.MdiChildActivate

        With Me.MDIChildCombo

            If .SelectedItem Is Me.ActiveMdiChild Then Return
            RemoveHandler .SelectedIndexChanged, AddressOf MDIChildCombo_SelectedIndexChanged
            .SelectedItem = Me.ActiveMdiChild
            AddHandler .SelectedIndexChanged, AddressOf MDIChildCombo_SelectedIndexChanged
        End With

    End Sub

    Private Sub frmChild_FormClosed(ByVal sender As Object, ByVal e As FormClosedEventArgs)

        ' Form-Eintrag in der Combo durch Type-Information ersetzen
        Dim Frm As Form = DirectCast(sender, Form)

        With MDIChildCombo
            RemoveHandler .SelectedIndexChanged, AddressOf MDIChildCombo_SelectedIndexChanged
            .Items(.FindStringExact(Frm.Name)) = Frm.GetType
            AddHandler .SelectedIndexChanged, AddressOf MDIChildCombo_SelectedIndexChanged
        End With

    End Sub

End Class

' --------------- Ende Datei frmMDIParent2.vb  ---------------
' --------------- Anfang Datei frmChildTyp1.vb ---------------
Public Class frmChildTyp1

    Private Sub TestToolStripMenuItem_Click(ByVal sender As Object, ByVal e As EventArgs) _
              Handles TestToolStripMenuItem.Click

        MsgBox(String.Join(Environment.NewLine, New String() { "Halloo!!", "", "Ich bin " & _
            "ein MenuItem vom Menu von frmChildTyp1", "Mein Name ist:", _
            TestToolStripMenuItem.Name}))

    End Sub

End Class

' ---------------- Ende Datei frmChildTyp1.vb ----------------
' -------------- Anfang Datei frmMDIParent1.vb  --------------
Public Class frmMDIParent1

    ' einfachste Lsg: Mini/Maxi-mieren/Schließen-Buttons ausblenden
    ' im Designer die Menustrip.MdiWindowListItem - Property auf ein MenuItem einstellen

    Private Sub frmMDIParent2_Load(ByVal sender As Object, ByVal e As EventArgs) Handles MyBase.Load

        For Each Frm As Form In New Form() {New frmChildTyp1, New frmChildTyp2, New frmChildTyp3}

            With Frm
                .MdiParent = Me
                .ControlBox = False
                .WindowState = FormWindowState.Maximized
                .Show()
            End With

        Next

    End Sub

End Class

' --------------- Ende Datei frmMDIParent1.vb  ---------------
' --------------- Ende Projektdatei MDI.vbproj ---------------
' ---------------- Ende Projektgruppe MDI.sln ----------------

	

Diskussion  

Diese Funktion ermöglicht es, Fragen, die die Veröffentlichung des Tipps betreffen, zu klären, oder Anregungen und Verbesserungsvorschläge einzubringen. Nach der Veröffentlichung des Tipps werden diese Beiträge nicht weiter verlinkt. Allgemeine Fragen zum Inhalt sollten daher hier nicht geklärt werden.

Um eine Diskussion eröffnen zu können, müssen sie angemeldet sein.