[VB.NET]MDI Thumbnail Preview

[VB.NET]MDI Thumbnail Preview

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

要為MDI視窗加上Thumbnail Preview功能,必須知道如何透過複寫ProcessCmdKey把Ctrl+Tab切換MDI子視窗的動作給過濾掉,就像下面這樣:


        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對話盒最後選取的子視窗,像是下面這樣:


        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切換子視窗選項的功能,簡單的範例如下:



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

 

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

image 

 

Download

MDIThumbnailPreview.zip