vb@rchiv
VB Classic
VB.NET
ADO.NET
VBA
C#
TOP-Angebot: 17 bzw. 24 Entwickler-Vollversionen zum unschlagbaren Preis!  
 vb@rchiv Quick-Search: Suche startenErweiterte Suche starten   RSS-Feeds  | Newsletter  | Impressum  | Datenschutz  | vb@rchiv CD Vol.6  | Shop Copyright ©2000-2017
 
zurück
Rubrik: Forms/Controls   |   VB-Versionen: VB5, VB601.07.04
MDI-Projekt und das Verwalten von MDIChild-Formen

In diesem Workshop erfahren Sie, wie man MDIChild-Formen in einer MDI-Anwendung gekonnt verwalten kann und jederzeit Zugriff auf eine ganz bestimmtes ChildForm hat. Als Beispiel für diesen Workshop soll eine WebBrowser-Anwendung mit beleibig vielen Browser-Fenstern erstellt werden.

Autor:  Dieter OtterBewertung:     [ Jetzt bewerten ]Views:  35.311 

In diesem Workshop erfahren Sie, wie man MDIChild-Formen in einer MDI-Anwendung gekonnt verwalten kann und jederzeit Zugriff auf eine ganz bestimmtes ChildForm hat. Als Beispiel für diesen Workshop soll eine WebBrowser-Anwendung mit beleibig vielen Browser-Fenstern erstellt werden.

MDI-Projekte werden immer dann besonders gern verwendet, wenn man mehrere "gleiche" Child-Windows innerhalb eines Hauptfensters anzeigen möchte. Ein klassisches Beispiel hierfür wäre eine eigene Browser-Anwendung mit der Möglichkeit mehrere Browser-Fenster gleichzeitig innerhalb der Haupt-Anwendung zu öffnen. Das ist eigentlich auch alles überhaupt kein Problem, wie nachfolgender 2-Zeiler verdeutlicht:

' Neues Browser-Fenster öffnen und anzeigen
Dim oForm As New frmBrowser
oForm.Show

Probleme gibt es erst dann, wenn man bspw. prüfen möchte, ob überhaupt ein Browser-Fenster (ChildForm) geöffnet ist. Ein beliebter Code hierfür ist das "Durchlaufen" aller Forms und gleichzeitiger Prüfung, ob es sich um das gesuchte Child-Form handelt:

Dim oForm As Form
 
For Each oForm In VB.Forms
  If Not TypeName(oForm) = "MDIForm" Then
    If oForm.Name = "frmBrowser" Then
      ' Es gibt mind. 1 geöffnetes Browser-Fenster
      ' ...
    End If
  End If
Next

Ok... mit diesem Code könnte man zunächst "leben". Was aber, wenn man alle geöffneten Browser-Fenster bspw. in einer ComboBox in der Haupt-Form anzeigen möchte? Natürlich sollte dann auch immer das aktive Browser-Fenster in der ComboBox markiert sein. Und wird ein Browser-Fenster geschlossen, muss dieses natürlich auch aus der ComboBox entfernt werden. Weiterhin sollte beim Klick auf einen ComboBox-Eintrag das dazugehörige Child-Fenster aktiviert und in den Vordergrund geholt werden.

Das alles lässt sich mit einem Collection-Objekt mit relativ wenig Aufwand verwalten! Wie? Das erfahren Sie auf den nachfolgenden Seiten.

Aufbau unseres MDI-Browsers

Starten Sie ein neues Projekt, benennen Form1 in frmBrowser um und setzen die Eigenschaft MDIChild auf den Wert True. Platzieren Sie auf die Form eine TextBox (txtURL) für die Eingabe einer Internetadresse und zusätzlich noch ein WebBrowser-Control (WebBrowser1). Die Anordnung spielt hierbei keine Rolle - das erledigen wir zur Laufzeit mit nachfolgendem Code:

Private Sub Form_Resize()
  ' Controls anordnen
  If Me.WindowState <> vbMinimized Then
    txtURL.Move 105, 105, Me.ScaleWidth - 210
    With WebBrowser1
      .Move 105, txtURL.Top + txtURL.Height + 105, Me.ScaleWidth - 210
      .Height = Me.ScaleHeight - .Top - 105
    End With
  End If
End Sub

Wird eine URL in der TextBox angegeben soll die Webseite im WebBrowser-Control angezeigt werden:

Private Sub txtURL_GotFocus()
  ' Bei Focuserhalt, Inhalt der TextBox markieren
  txtURL.SelStart = 0
  txtURL.SelLength = 999
End Sub
Private Sub txtURL_KeyPress(KeyAscii As Integer)
  ' Seite beim Drücken von ENTER im WebBrowser anzeigen
  If KeyAscii = 13 Then
    KeyAscii = 0
    WebBrowser1.Navigate txtURL.Text
  End If
End Sub

frmBrowser
Abb 1.: frmBrowser (MDIChild)

Die MDI-Hauptanwendung: MDIForm1

Fügen Sie dem Projekt ein MDI-Formular hinzu (MDIForm1) - unser Hauptfenster. Auf der MDIForm benötigen wir lediglich eine PictureBox mit nachfolgenden Eigenschaften, sowie eine ComboBox (Combo1) und einen CommandButton (cmdNew).

Align1 - oben ausrichten
BorderStyle0 - kein Rahmen
Height435
TabStopFalse

Die ComboBox, in der später alle geöffneten Browser-Fenster aufgelistet werden sollen, platzieren Sie bitte auf die PictureBox, wie nachfolgende Abbildung zeigt und setzen die Style-Eigenschaft auf "2 - Dropdown-Liste". Den CommandButton platzieren Sie dann rechts neben die ComboBox.

MDIForm1
Abb. 2: Das Haupt-Formular: MDIForm1

Das Collection-Objekt zur Verwaltung der Child-Formen

Kommen wir jetzt endlich zum Dreh- und Angelpunkt dieses Workshops: das Collection-Objekt.
Ein Collection-Objekt kann man sich als "Sammelbehälter" für die verschiedensten Datentypen und Objekte vorstellen. Über die AddItem-Methode fügt man dem "Behälter" ein neues Objekt hinzu, wobei man diesem sogar einen eindeutigen Key (Schlüsselwert) zuweisen kann. Mittels der RemoveItem-Methode lässt sich ein vorhandenes Objekt schnell und einfach löschen - entweder durch Angabe des Key-Wertes oder durch Angabe der Position innerhalb der Collection. Um auf ein Objekt zuzugreifen verwendet man die Items-Auflistung, die gleichzeitig die Standard-Eigenschaft des Collection-Objekts darstellt. Der Items-Auflistung muss man hierbei entweder den Key-Wert des Objekts übergeben oder die Position des Objekts innerhalb der Collection.

In unserem Fall verwenden wir das Collection-Objekt als Sammelbehälter für unsere einzelnen Browser-Fenster (MDIChild-Formen).

Das Collection-Objekt selbst wird hierbei in der Hauptanwendung, unserer MDIForm, verwaltet. Fügen Sie daherfolgende Deklaration in den Allgemein-Teil der MDIForm ein:

Option Explicit
 
' "Sammelbehälter" für unsere Child-Formen
Dim oChilds As New Collection

Speichern einer neuen Child-Form im Collection-Objekt
Wird eine neue Child-Form erstellt, speichern wir eine Referenz auf die Form in unserem Collection-Objekt. Als Key-Wert (Schlüsselwert) verwenden wir hierbei eine fortlaufendeNummerierung, die wir gleichzeitig auch in der Tag-Eigenschaft der Child-Form speichern. Somit können wir dann später anhand der ID (laufendeNummerierung) bequem auf die Child-Form zugreifen.

Public Sub ChildAdd(oForm As Form)
  ' Child-Window der Collection hinzufügen
  ' als Key-Wert verwenden wir eine fortlaufende 
  ' Nummerierung, die wir zusätzlich noch in der 
  ' Tag-Eigenschaft der Child-Form speichern
  Static nID As Long
 
  ' fortlaufende Nummer erzeugen  
  nID = nID + 1
 
  ' Child-Form der Collection hinzufügen
  oChilds.Add oForm, "k" & CStr(nID)
 
  ' ID-Wert zusätzlich in der Tag-Eigenschaft
  ' der Child-Form speichern
  oForm.Tag = nID
 
  ' Form-Caption in die ComboBox eintragen
  With Combo1
    .AddItem oForm.Caption
    .ItemData(.NewIndex) = nID
    .Enabled = True
  End With
End Sub

Hinweis:
Der Key-Wert eines Collection-Eintrags muss immer alphanumerisch beginnen. Aus diesem Grund setzen wir einfach den Buchstaben k vor unsere laufendeNummerierung.

Frage: Wann muss die ChildAdd-Prozedur aufgerufen werden?
Genau! Immer dann, wenn eine neue Child-Form erstellt wurde. Fügen wir also folgenden Aufruf in das Form_Load-Ereignis der Child-Form (frmBrowser) ein:

Private Sub Form_Load()
  ' Hauptanwendung mitteilen, dass eine neue
  ' Child-Form geladen wurde
  Me.Caption = "Neues Browser-Fenster"
  MDIForm1.ChildAdd Me
End Sub

Prüfen, ob eine Child-Form geladen ist
Wenn Sie innerhalb der Hauptanwendung (MDIForm) prüfen möchten, ob überhaupt ein Browser-Fenster geöffnet ist, geht das jetzt unter Einbeziehung des Collection-Objekts wesentlich einfacher und eleganter:

If oChild.Count = 0 Then
  ' kein Child-Form geladen
  Combo1.ListIndex = -1
  Combo1.Enabled = False
End Sub

Entfernen einer Child-Form aus dem Collection-Objekt
Wird eine Child-Form geschlossen, muss die jeweilige Form-Referenz aus dem Collection-Objekt entfernt werden. Hierfür benötigen wir die laufende Nummer der Child-Form, die wir ja glücklicherweise auch kennen (Tag-Eigenschaft der Form!).

Public Sub ChildRemove(oForm As Form)
  ' ChildForm aus Collection entfernen
  Dim nID As Long
  Dim i As Long
 
  ' laufende Nummer der Form  
  nID = oForm.Tag
 
  ' Eintrag aus der ComboBox entfernen  
  With Combo1
    For i = 0 To .ListCount - 1
      If .ItemData(i) = nID Then
        .RemoveItem i
        Exit For
      End If
    Next i
  End With
 
  ' Form-Referenz aus dem Collection-Objekt entfernen  
  oChilds.Remove "k" & CStr(nID)
 
  ' ComboBox deaktivieren, falls keine Child-Form
  ' mehr geöffnet
  If oChilds.Count = 0 Then Combo1.Enabled = False
End Sub

Frage: Wann muss die ChildRemove-Prozedur aufgerufen werden?
Genau! Immer dann, wenn eine Child-Form geschlossen wird. Fügen wir also folgenden Aufruf in das Form_Unload-Ereignis der Child-Form (frmBrowser) ein:

Private Sub Form_Unload(Cancel As Integer)
  ' Hauptanwendung mitteilen, dass eine 
  ' Child-Form geschlossen wurde
  MDIForm1.ChildRemove Me
End Sub

Aktivieren einer bestimmten Child-Form
Nachdem nun alle geöffneten Child-Formen in der ComboBox angezeigt werden, soll natürlich immer die aktive Child-Form in der ComboBox selektiert sein. Ebenso soll bei Auswahl einer anderen Child-Form diese in den Vordergrund gebracht werden und den Fokus erhalten.

Erweitern wir also den Code unserer MDIForm um folgende neue Prozedur:

Public Sub ChildActivate(ByVal nID As Long)
  ' bestimmte ChildForm aktivieren und in
  ' den Vordergrund bringen
  oChilds("k" & CStr(nID)).SetFocus
 
  ' aktive Form in der ComboBox anzeigen  
  Dim i As Long
  With Combo1
    For i = 0 To .ListCount - 1
      If .ItemData(i) = nID Then
        If .ListIndex <> i Then .ListIndex = i
        Exit For
      End If
    Next i
  End With
End Sub

Frage: Wann muss die ChildActivate-Prozedur aufgerufen werden?
Genau! Immer dann, wenn eine Child-Form durch den Anwender aktiviert wurde und natürlich auch dann, wenn der Anwender eine bestimmte Child-Form aus der ComboBox-Liste ausgewählt hat. Fügen wir also folgenden Code in das Form_Activate-Ereignis der Child-Form (frmBrowser) ein:

Private Sub Form_Activate()
  ' Hauptanwendung mitteilen, welche Child-Form
  ' aktiviert wurde
  MDIForm1.ChildActivate Me.Tag
End Sub

Und jetzt noch nachfolgenden Code in den Codeteil der MDIForm einfügen:

Private Sub Combo1_Click()
  ' ChildForm aktivieren und in den Vordergrund bringen
  ChildActivate Combo1.ItemData(Combo1.ListIndex)
End Sub

Neues Browser-Fenster öffnen
Beim Klick auf den CommandButton (cmdNew) soll ein neues Browser-Fenster geöffnet und angezeigt werden. Das neue Fenster soll natürlich auch in der ComboBox erscheinen. Alles, was wir hierfür brauchen, ist folgender 2-Zeiler:

Private Sub cmdNew_Click()
  ' Neues Browser-Fenster öffnen
  Dim oForm As New frmBrowser
  oForm.Show
End Sub

Nicht mehr und nicht weniger. Das neue Child-Window wird autom. dem Collection-Objekt hinzugefügt, da im Form_Load-Ereignis die Prozedur ChildAdd autom. ausgeführt wird.

Ändern der Titelzeile einer Child-Form
Beim Laden einer Webseite sollte in der Titelzeile der Form nicht "frmBrowser" angezeigt werden, sondern vielmehr der Titel der Webseite. Die Titelzeile der Webseite lässt sich wie folgt ermitteln:

Private Sub WebBrowser1_TitleChange(ByVal Text As String)
  ' Titel der Webseite in der Titelzeile der Form anzeigen
  Me.Caption = Text
  MDIForm1.ChildRename Me.Tag
End Sub

Natürlich muss jetzt auch der entsprechende Eintrag in der ComboBox der MDIForm geändert werden. Dies erledigt die Prozedur ChildRename innerhalb der MDIForm:

Public Sub ChildRename(ByVal nID As Long)
  ' Titelzeile der ChildForm auslesen und
  ' den dazugehörigen ComboBox-Eintrag ändern
  Dim i As Long
 
  With Combo1
    ' alle Einträge durchlaufen...
    For i = 0 To .ListCount - 1
      ' ... und mit "nID" vergleichen
      If .ItemData(i) = nID Then
        ' Titelzeile der Form aus der Collection auslesen
        .List(i) = oChilds("k" & CStr(nID)).Caption
      End If
    Next i
  End With
End Sub

Schließen aller Child-Formen
Um alle geöffneten Child-Formen zu schließen, müssen wir lediglich das Collection-Objekt "durchlaufen" und die einzelnen enthaltenen Objekte (Childs) entladen:

Public Sub ChildCloseAll()
  ' Alle ChildForms schließen
  Do While oChilds.Count > 0
    Unload oChilds(oChilds.Count)
  Loop
End Sub

Fazit:
Wie aus dem Workshop ersichtlich, lassen sich die Child-Formen einer MDI-Anwendung mit Hilfe eines Collection-Objekts sehr einfach verwalten. Die Möglichkeit jedem einzelnen Element des Collection-Objekts einen eindeutigen Key-Wert zuordnen zu können, mit dessen Hilfe man auf ein Objekt zugreifen kann, macht das Collection-Objekt nicht nur in Zusammenhang mit dem Speichern von Form-Objekt-Referenzen zu einer äußerst interessanten Angelegenheit.

In diesem Sinne: Let's go collecting Childforms
 

Dieser Workshop wurde bereits 35.311 mal aufgerufen.

Über diesen Workshop im Forum diskutieren
Haben Sie Fragen oder Anregungen zu diesem Workshop, können Sie gerne mit anderen darüber in unserem Forum diskutieren.

Neue Diskussion eröffnen

nach obenzurück


Anzeige

Kauftipp Unser Dauerbrenner!Diesen und auch alle anderen Workshops finden Sie auch auf unserer aktuellen vb@rchiv  Vol.6
(einschl. Beispielprojekt!)

Ein absolutes Muss - Geballtes Wissen aus mehr als 8 Jahren vb@rchiv!
- nahezu alle Tipps & Tricks und Workshops mit Beispielprojekten
- Symbol-Galerie mit mehr als 3.200 Icons im modernen Look
Weitere Infos - 4 Entwickler-Vollversionen (u.a. sevFTP für .NET), Online-Update-Funktion u.v.m.
 
   

Druckansicht Druckansicht Copyright ©2000-2017 vb@rchiv Dieter Otter
Alle Rechte vorbehalten.
Microsoft, Windows und Visual Basic sind entweder eingetragene Marken oder Marken der Microsoft Corporation in den USA und/oder anderen Ländern. Weitere auf dieser Homepage aufgeführten Produkt- und Firmennamen können geschützte Marken ihrer jeweiligen Inhaber sein.

Diese Seiten wurden optimiert für eine Bildschirmauflösung von mind. 1280x1024 Pixel