[VB.NET]MDI Thumbnail Preview

最近試著把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

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

image

Download

MDIThumbnailPreview.zip