[VB.NET]MDI子視窗清單的實作

最近在撰寫MDI程式,碰到很多很麻煩的問題,尤其是在MDI子視窗清單功能的部分,個人覺得特別難處理。其中最麻煩的莫過於When close is cancelled on MDI Child Window and it is hidden, MDI parent’s window never shows it again.這篇所提到的問題。

雖然MenuStrip內建的MDIWindowListItem十分好用,但要自行擋住為數眾多的問題,最後還是決定自己實作MDI子視窗清單的功能,好在實作這樣的功能並不困難,只要處理MenuItem的DropDownOpening與DropDownClosed事件即可,這邊簡單的紀錄一下:

    Private Sub WindowsMenu_DropDownClosed(ByVal sender As Object, ByVal e As System.EventArgs) Handles WindowsMenu.DropDownClosed
Dim separators() As ToolStripItem = WindowsMenu.DropDownItems.Find(“MdiWindowListSeperator”, False)
If separators.Count = 0 Then
Return
End If
Dim spIdx As Integer = WindowsMenu.DropDownItems.IndexOf(separators(0))
For idx As Integer = WindowsMenu.DropDownItems.Count - 1 To spIdx Step -1
WindowsMenu.DropDownItems.RemoveAt(idx)
Next
End Sub

Private Sub WindowsMenu_DropDownOpening(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles WindowsMenu.DropDownOpening
If ActiveMdiChild Is Nothing Then
Return
End If
Dim sp As New ToolStripSeparator
sp.Name = “MdiWindowListSeperator”
WindowsMenu.DropDownItems.Add(sp)
For Each f As Form In MdiChildren
If Not f.Visible Then
Continue For
End If
WindowsMenu.DropDownItems.Add(New ToolStripMenuItem(f.Text, Nothing, AddressOf MDIChildren_Click) With {.Checked = ActiveMdiChild Is f, .Tag = f})
Next
End Sub

Private Sub MDIChildren_Click(ByVal sender As Object, ByVal e As EventArgs)
DirectCast(DirectCast(sender, ToolStripMenuItem).Tag, Form).Activate()
End Sub


也可以只處理MenuItem的DropDownOpening事件:

    Private Sub WindowToolStripMenuItem_DropDownOpening(ByVal sender As System.Object, ByVal e As System.EventArgs)
Const seperatorKey As String = “MdiWindowListSeperator”
Dim dropDownItems As ToolStripItemCollection = _ideForm.WindowToolStripMenuItem.DropDownItems
If dropDownItems.ContainsKey(seperatorKey) Then
Dim spIdx As Integer = dropDownItems.IndexOf(dropDownItems.Find(seperatorKey, False)(0))
For idx As Integer = dropDownItems.Count - 1 To spIdx Step -1
dropDownItems.RemoveAt(idx)
Next
End If

Dim linq = From f In _ideForm.MdiChildren Where f.Visible Select f
If linq.Count = 0 Then
Return
End If
Dim sp As New ToolStripSeparator
sp.Name = seperatorKey
dropDownItems.Add(sp)
For Each f As Form In linq
dropDownItems.Add(New ToolStripMenuItem(f.Text, Nothing, AddressOf MDIChildren_Click) With {.Checked = _ideForm.ActiveMdiChild Is f, .Tag = f})
Next
End Sub