最近試著把MDI視窗加上Thumbnail Preview功能,找來找去找不到相關的技術文件,只好硬幹處理,這邊簡單記錄一下簡陋的作法。

要為MDI視窗加上Thumbnail Preview功能,必須知道如何透過複寫ProcessCmdKey把Ctrl+Tab切換MDI子視窗的動作給過濾掉,就像下面這樣: Protected Overrides Function ProcessCmdKey(ByRef msg As System.Windows.Forms.Message, ByVal keyData As System.Windows.Forms.Keys) As Boolean If keyData = (Keys.Control Or Keys.Tab) Then Return True End If Return MyBase.ProcessCmdKey(msg, keyData) End Function

了解如何過濾掉預設的切換動作後,我們必須改寫讓系統先彈出Thumbnail Preview對話盒,把對話盒放至中間,在Thumbnail Preview對話盒關閉時,把子視窗切至Thumbnail Preview對話盒最後選取的子視窗,像是下面這樣:

Protected Overrides Function ProcessCmdKey(ByRef msg As System.Windows.Forms.Message, ByVal keyData As System.Windows.Forms.Keys) As Boolean
    If keyData = (Keys.Control Or Keys.Tab) Then
        Dim thumbnailDlg As New ThumbnailDialog(Me)
        thumbnailDlg.ShowInTaskbar = False
        thumbnailDlg.Location = New Point(Me.Width / 2 - thumbnailDlg.Width / 2, Me.Height / 2 - thumbnailDlg.Height / 2)
        If thumbnailDlg.ShowDialog() = DialogResult.Cancel Then
            Return MyBase.ProcessCmdKey(msg, keyData)
        End If
        thumbnailDlg.SelectedChildForm.Activate()
        Return True
    End If
    Return MyBase.ProcessCmdKey(msg, keyData)
End Function

至於Thumbnail Preview對話盒則必須要做到放開Ctrl就關閉,與按下Ctrl + Tab切換子視窗選項的功能,簡單的範例如下:

Imports System.Windows.Forms

Public Class ThumbnailDialog

Private _mdiParent As Form
Private _thumbnailPool As Dictionary(Of Form, Image)

Private Property m_MDIParent As Form
    Get
        Return _mdiParent
    End Get
    Set(ByVal value As Form)
        _mdiParent = value
    End Set
End Property

Private ReadOnly Property m_ThumbnailPool As Dictionary(Of Form, Image)
    Get
        If _thumbnailPool Is Nothing Then
            _thumbnailPool = New Dictionary(Of Form, Image)
        End If
        Return _thumbnailPool
    End Get
End Property

Public ReadOnly Property SelectedChildForm As Form
    Get
        Return If(ListBox1.SelectedIndex = -1, Nothing, m_MDIParent.MdiChildren(ListBox1.SelectedIndex))
    End Get
End Property

Private Sub ThumbnailDialog_KeyUp(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyEventArgs) Handles Me.KeyUp
    If Not e.Control Then
        DialogResult = If(ListBox1.SelectedIndex = -1, DialogResult.Cancel, DialogResult.OK)
        Me.Close()
    End If
End Sub

Protected Overrides Function ProcessCmdKey(ByRef msg As System.Windows.Forms.Message, ByVal keyData As System.Windows.Forms.Keys) As Boolean
    If keyData = (Keys.Control Or Keys.Tab) Then
        If ListBox1.Items.Count > 1 Then
            ListBox1.SelectedIndex = (ListBox1.SelectedIndex + 1) Mod ListBox1.Items.Count
        End If
        Return True
    End If
    Return MyBase.ProcessCmdKey(msg, keyData)
End Function

Private Sub ThumbnailDialog_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
    Me.KeyPreview = True
    ListBox1.DisplayMember = "Text"
    ListBox1.DataSource = m_MDIParent.MdiChildren
    Dim childForm As Form = m_MDIParent.ActiveMdiChild
    If childForm Is Nothing Then
        Return
    End If
    ListBox1.SelectedItem = childForm
End Sub

Public Sub New(ByVal mdiParent As Form)

    ' This call is required by the designer.
    InitializeComponent()

    ' Add any initialization after the InitializeComponent() call.
    m_MDIParent = mdiParent
    PictureBox1.SizeMode = PictureBoxSizeMode.Zoom
End Sub

Private Sub ListBox1_SelectedIndexChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles ListBox1.SelectedIndexChanged
    Dim childForm As Form = m_MDIParent.MdiChildren(ListBox1.SelectedIndex)
    Dim thumbnailImage As Image = If(m_ThumbnailPool.ContainsKey(childForm), m_ThumbnailPool(childForm), Nothing)
    If thumbnailImage Is Nothing Then
        thumbnailImage = New Bitmap(childForm.Width, childForm.Height)
        m_ThumbnailPool.Add(childForm, thumbnailImage)
        childForm.DrawToBitmap(thumbnailImage, New Rectangle(0, 0, thumbnailImage.Width, thumbnailImage.Height))
    End If
    PictureBox1.Image = thumbnailImage
End Sub

End Class

下面是醜醜的執行範例圖(美工部分請自行補強):

Download

MDIThumbnailPreview.zip