65.9K
CodeProject 正在变化。 阅读更多。
Home

带预览功能的图像查看器用户控件

starIconstarIconstarIcon
emptyStarIcon
starIcon
emptyStarIcon

3.73/5 (8投票s)

2008年6月5日

CPOL

6分钟阅读

viewsIcon

63960

downloadIcon

3308

本文讨论了一个图像查看器用户控件的构建,该控件可用于显示包含图像文件集合的目录中的图像。

引言

本文讨论了一个图像查看器用户控件的构建,该控件可用于显示包含图像文件集合的目录中的图像。该控件显示文件中的上一张和下一张图像以及当前图像。可以根据用户计算机的文件关联,从用户控件中打开当前图像到用户计算机上的默认图像应用程序。图像缩略图用于提供目录中的上一张、当前张和下一张图像。如演示所示,用户控件可以添加到需要允许用户在打开图像进行查看或编辑之前预览或视觉扫描图像的应用程序中。

图 1:图像查看器用户控件加载到测试应用程序中。

图 2:将图像打开到默认图像应用程序中
(显示 Microsoft Office Picture Manager)。

入门

要开始,请解压缩包含的项目并在 Visual Studio 2008 环境中打开解决方案。解决方案包含两个项目。ImageViewerVB 是第一个项目,它是一个控件库项目,包含一个用户控件。第二个项目(TestImageViewerVB)是一个测试应用程序,显示一个用于容纳用户控件的单个窗体。

在解决方案资源管理器中,您应该会注意到这些文件

图 3:解决方案资源管理器。

图像查看器用户控件 (ImageViewerVB.vb)

图像查看器用户控件包含浏览图像文件夹和查看当前、下一张和上一张图像所需的所有内容。控件本身包含一个文本框和一个浏览按钮,用于打开文件夹浏览器对话框;当用户导航到所需文件夹并选择它时,文件夹的路径将显示在 `textbox` 控件中,并且浏览按钮的点击事件处理程序将触发收集所选文件夹中包含的所有图像文件,并开始显示图像。控件包含三个图片框,用于显示上一张、当前张和下一张图像。上一张和下一张图像旁边有两个按钮,用于在图像集合中向后和向前移动。每个图像文件的路径都包含在一个 ArrayList 中,并且一个具有类作用域的整数值用于维护该 ArrayList 中的当前位置。

如果您愿意在 IDE 中打开代码视图,您会看到代码文件以以下 using 语句开头;大多数包含项都是按默认配置的,但添加了 System.IO 以支持代码中使用的目录操作。

Imports System.IO
Imports System.Collections

在 `imports` 之后,定义了类并添加了构造函数,以及用于维护文件夹路径、图像文件路径(在 ArrayList 中)、图像列表位置和图像本身(上一张、当前张和下一张)的一组本地成员变量。我在这里的构造函数中什么也没做,但如果您愿意,例如,您可能希望将文件夹浏览器对话框指向一个默认文件夹位置。

Public Class ImageViewer

    ' private member variables
    Private mFolder As String
    Private mImageList As ArrayList
    Private mImagePosition As Integer
    Private mPreviousImage As Image
    Private mCurrentImage As Image
    Private mNextImage As Image

    ''' <summary>
    ''' Default Constructor
    ''' </summary>
    ''' <remarks></remarks>
    Public Sub New()

        ' This call is required by the Windows Form Designer.
        InitializeComponent()

        ' Add any initialization after the InitializeComponent() call.

    End Sub

接下来是用户控件的加载事件处理程序;此演示在加载事件中不执行任何操作,但您可能希望使用此处理程序在此处执行某些操作。

    ''' <summary>
    ''' Default load event handler
    ''' </summary>
    ''' <param name="sender"></param>
    ''' <param name="e"></param>
    ''' <remarks></remarks>
    Private Sub ImageViewer_Load(ByVal sender As System.Object, ByVal e As
    System.EventArgs) Handles MyBase.Load

        ' do nothing

    End Sub

代码的下一部分是浏览按钮的点击事件处理程序。在此代码部分中,处理程序打开文件夹浏览器对话框,用户可以使用该对话框设置图像文件夹的路径。文件夹设置后,处理程序会遍历该文件夹并查找所有 BMP、JPEG 和 GIF 文件;找到的任何图像文件的文件路径都会添加到 ArrayList 中(BMP、GIF 和 JPEG)。一旦 ArrayList 中填充了文件路径,点击事件处理程序将通过将列表索引位置设置为零来完成,然后调用 SetImages 方法,该方法将当前、上一张和下一张图像设置到相应的图片框中。代码已注释,应该很容易理解。

    ''' <summary>
    ''' Open the folder browse dialog and load
    ''' the initial images
    ''' </summary>
    ''' <remarks></remarks>
    Private Sub btnBrowse_Click(ByVal sender As System.Object, ByVal e As
    System.EventArgs) Handles btnBrowse.Click

        ' Label the folder browser dialog
        Me.folderBrowserDialog1.Description = "Select the image directory."

        ' disable create folder feature of folder browser
        Me.folderBrowserDialog1.ShowNewFolderButton = False

        ' display the folder browser
        Dim result As DialogResult = folderBrowserDialog1.ShowDialog()

        If result = DialogResult.OK Then

            ' on okay, set the image folder to the
            ' folder browser's selected path
            mFolder = folderBrowserDialog1.SelectedPath
            If (Not String.IsNullOrEmpty(mFolder)) Then
                txtImageDirectory.Text = mFolder
            Else
                ' exit if the user cancels
                Return
            End If

            ' initialize the image arraylist
            mImageList = New ArrayList()

            ' loop through the image directory
            ' and find all of the image files
            ' add the found files to the image
            ' list - add other image types if
            ' necessary
            Dim Dir As New DirectoryInfo(mFolder)
            Dim f As FileInfo
            For Each f In Dir.GetFiles("*.*")
                Select Case (f.Extension.ToUpper())
                    Case ".JPG"
                        mImageList.Add(f.FullName)
                    Case ".BMP"
                        mImageList.Add(f.FullName)
                    Case ".GIF"
                        mImageList.Add(f.FullName)
                    Case Else
                        ' skip file
                End Select
            Next

            ' set the starting position to 0
            ' and call the set images method
            ' to load the pictures
            mImagePosition = 0
            SetImages()

        End If

    End Sub

下一段代码是 SetImages 函数;此函数用于为每个图片框设置图像(上一张、当前张和下一张图像)。此代码创建存储在图像 ArrayList 中的文件路径的图像的缩略图,然后将图片框设置为显示缩略图而不是完整图像。代码的编写方式是在达到用于存储实际图像文件路径的 ArrayList 的限制时做出不同的响应;在限制处,上一张或下一张图像将被清空。

此外,代码会在设置图片框后清除图像,并且每次调用函数时都会调用垃圾回收来清理。我发现,如果没有垃圾回收,当一次扫描大量图像时,控件会抛出内存不足异常。同样,此代码已注释,应该很容易理解。

    ''' <summary>
    ''' This function is used to set the previous,
    ''' current, and next images into the
    ''' correct picture boxes
    ''' </summary>
    ''' <remarks></remarks>
    Private Sub SetImages()

        ' clear any existing images
        ' memory will be an issue if
        ' cycling through a large
        ' number of images
        mPreviousImage = Nothing
        mNextImage = Nothing
        mCurrentImage = Nothing

        ' set the previous image
        If mImagePosition > 0 Then

            Try

                ' set delegate
                Dim prevCallback As Image.GetThumbnailImageAbort = _
                        New Image.GetThumbnailImageAbort(AddressOf ThumbnailCallback)

                ' get the previous image
                Dim prevBmp As _
                    New Bitmap(mImageList(mImagePosition - 1).ToString())

                ' thumbnail the image to the size
                ' of the picture box
                mPreviousImage = _
                prevBmp.GetThumbnailImage(160, 100, _
                        prevCallback, IntPtr.Zero)

                ' set the picture box image
                picPreviousImage.Image = mPreviousImage

                ' clear everything out
                prevBmp = Nothing
                prevCallback = Nothing
                mPreviousImage = Nothing

            Catch

                'stall if it hangs, the user can retry

            End Try

        Else

            ' at the limit clear the
            ' image
            picPreviousImage.Image = Nothing

        End If

        ' set current image
        If mImagePosition < mImageList.Count Then

            Try

                ' set delegate
                Dim currentCallback = _
                        New Image.GetThumbnailImageAbort(AddressOf
                        ThumbnailCallback)

                ' get the current image
                Dim currentBmp As _
                        New Bitmap(mImageList(mImagePosition).ToString())

                ' thumbnail the image to the size
                ' of the picture box
                mCurrentImage = _
                currentBmp.GetThumbnailImage(320, 200, currentCallback,
                IntPtr.Zero)

                ' set the picture box image
                picCurrentImage.Image = mCurrentImage

                ' clear everything out
                currentBmp = Nothing
                mCurrentImage = Nothing
                currentCallback = Nothing

            Catch

                'stall if it hangs, the user can retry

            End Try

        End If

        ' set next image
        If mImagePosition < mImageList.Count - 1 Then

            Try

                ' set delegate
                Dim nextCallback As _
                    New Image.GetThumbnailImageAbort(AddressOf
                    ThumbnailCallback)

                ' get the next image
                Dim nextBmp As _
                    New Bitmap(mImageList(mImagePosition + 1).ToString())

                ' thumbnail the image to the size
                ' of the picture box
                mNextImage = _
                nextBmp.GetThumbnailImage(160, 100, nextCallback,
                IntPtr.Zero)

                ' set the picture box image
                picNextImage.Image = mNextImage

                ' clear everything out
                nextBmp = Nothing
                nextCallback = Nothing
                mNextImage = Nothing

            Catch

                'stall if it hangs, the user can retry

            End Try

        Else

            ' at the limit clear the
            ' image
            picNextImage.Image = Nothing

        End If

        ' call for garbage collection
        GC.Collect()

    End Sub

下一段代码是缩略图尝试中止时调用的代码;这是生成缩略图所需的方法。

    ''' <summary>
    ''' Thumbnail image abort target
    ''' </summary>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function ThumbnailCallback() As Boolean

        Return False

    End Function

上一张图像按钮的点击事件处理程序紧随其后;它用于更新 ArrayList 中的图像位置,并在更新索引位置时重新调用 SetImages 方法。

    ''' <summary>
    ''' Set the image position and reset all
    ''' of the images when the previous image
    ''' button is clicked
    ''' </summary>
    ''' <param name="sender"></param>
    ''' <param name="e"></param>
    ''' <remarks></remarks>
    Private Sub btnPreviousImage_Click(ByVal sender As System.Object, ByVal e
    As System.EventArgs) Handles btnPreviousImage.Click

        If (mImagePosition >= 0 And Not picPreviousImage.Image Is Nothing)
        Then
            mImagePosition -= 1
            SetImages()
        End If

    End Sub

下一张图像按钮的点击事件处理程序紧随其后;它用于更新 ArrayList 中的图像位置,并在更新索引位置时重新调用 SetImages 方法。

    ''' <summary>
    ''' Set the image position and reset all
    ''' of the images when the next image
    ''' button is clicked
    ''' </summary>
    ''' <param name="sender"></param>
    ''' <param name="e"></param>
    ''' <remarks></remarks>
    Private Sub btnNextImage_Click(ByVal sender As System.Object, ByVal e As
    System.EventArgs) Handles btnNextImage.Click

        If (mImagePosition <= (mImageList.Count - 2)) Then
            mImagePosition += 1
            SetImages()
        End If

    End Sub

最后一个方法是根据计算机的文件关联,将当前图像打开到默认图像查看应用程序中。此方法仅调用进程启动函数,并将当前图像文件的文件路径传递给它。

    ''' <summary>
    ''' Open the current image using the default
    ''' program per the user's file associations
    ''' </summary>
    ''' <param name="sender"></param>
    ''' <param name="e"></param>
    ''' <remarks></remarks>
    Private Sub btnOpenImage_Click(ByVal sender As System.Object, ByVal e As
    System.EventArgs) Handles btnOpenImage.Click
        System.Diagnostics.Process.Start(
          _mImageList(mImagePosition).ToString())
    End Sub

文本窗体 (Form1.vb)

测试应用程序中包含的测试窗体包含一个 Image Viewer 用户控件的实例;窗体本身没有特定代码,因此这里没有什么可以报告的。测试应用程序被设置为启动项目,并且在执行时,测试窗体打开并显示用户控件。

摘要

此解决方案提供了一个用户控件,可用于提供用户界面,如果应用程序用户需要浏览图像文件,该界面可能会有所帮助。用户控件提供了浏览包含图像的文件夹所需的控件,以及预览当前选定、上一张和下一张图像的方法。通过该控件,最终用户可以浏览文件夹中包含的所有图像文件,并在需要时将所有图像打开到新应用程序中。

历史

  • 2008年6月3日:初始版本
© . All rights reserved.