First we'll look at creating a thumbnail custom control for use in our application. Of course this control will also be usable in any other application.
Why Create a Custom Control?
You may be wondering "why create a custom control?" Well, whilst the range of controls available in the .NET framework is extensive, at present it does not include a thumbnail control. Using one of the existing controls, like a PictureBox, would work but would also be be less than ideal - for our Photo Browser I would like to display both the thumbnail and the name of the file it represents. We could use both a PictureBox and Label to do this, but it could make tasks like re-arranging the thumbnails unnecessarily complicated as we'll have two controls to move instead of one. Furthermore a custom control can take on all the work involved in generating the thumbnail, displaying the filename and redrawing the thumbnail when resized.
Creating a User Control
Creating a custom control may seem daunting, but it is pretty straightforward if you use the built in UserControl as a base. You create a user control in much the same way that you design a form; you can add any of controls in your toolbox onto your control, arrange them and set their properties.
Start by adding a new user control called "Thumbnail" to a Windows Forms project (File->Add New Item… then select "User Control"). You will be presented with your new blank control - which looks a lot like a borderless form. Start by setting the new controls size to 120x120, which will be the default size of our thumbnail control.
Laying Out Our Control
We'll use the Dock property of control in the .NET framework to ensure that the controls we add always fill our thumbnail control and resize automatically. First add a Panel to your control and set its Dock property to "Fill" and its border style to "Fixed3D". Next add a label to the panel, set its name to "lblFilename", Dock property to "Bottom" and TextAlign property to "MiddleCenter". Finally add a PictureBox to your panel, set its name to "picThumbnail", Dock property to "Fill" and SizeMode property to "CenterImage" (don't worry that you can't see the border of the PictureBox, this is intentional). Your thumbnail control should now look something like this:
Drawing the Thumbnails
The DrawThumbnail function will generate and display the thumbnail image, so that when you use the control all you have to do is specify the filename of the picture to view. First we'll declare a private variable to store the filename of the thumbnail. Add the following declaration at class level:
Private strFileName As String = ""
Now we'll create a function called DrawThumbnail which will generate and display a thumbnail from the file whose name is in the variable "strFileName". Add the following function to your code:
Private Sub DrawThumbNail()
Dim dAspectRatio As Double
Dim bm As Bitmap
Dim iTNHeight As Integer, iTNWidth As Integer
' Display the filename on the label
lblFileName.Text = IO.Path.GetFileName(strFileName)
' Check that the variable strFileName contains something
If strFileName <> "" Then
' Load the photo into a bitmap
bm = New Bitmap(strFileName)
' Calculate the aspect ration of the image
dAspectRatio = bm.Width / bm.Height
' Calculate the width and height of the thumbnail to be created
If dAspectRatio > 1 Then
' If the image is wider than it is tall, set it's width to be the width of the
' picturebox and calculate it's height using the aspect ratio
iTNWidth = picThumbnail.Width
iTNHeight = CInt(iTNWidth / dAspectRatio)
' If the image is taller than it is wide, set it's height to be the height of the
' picturebox and calculate it's width using the aspect ratio
iTNHeight = picThumbnail.Height
iTNWidth = CInt(iTNHeight * dAspectRatio)
' Check we have valid heights and widths
If iTNHeight > 0 And iTNWidth > 0 Then
' Generate the thumbnail
picThumbnail.Image = bm.GetThumbnailImage(iTNWidth, iTNHeight, Nothing, IntPtr.Zero)
' Dispose of the bitmap
' Tf strFileName is empty, clear the picturebox
picThumbnail.Image = Nothing
Catch ex As Exception
MsgBox("An exception occured when trying to render the thumbnail for the image '" & _
strFileName & "' with the message:" & vbCrLf & vbCrLf & ex.ToString, _
This function is declared as Private because we don't want it to be available to users of the control; we just use it inside the control to generate and draw the thumbnail image as required. The DrawThumbnail function first assigns the Label's Text property to "strFileName" and loads the whole picture into an off-screen bitmap. The function calculates the aspect ratio (ratio of width to height) of the image and then calculates the best size of the thumbnail to fill the PictureBox preserving the aspect ratio of the original image. Our thumbnail will always appear in the centre of the PictureBox because the PictureBox's SizeMode is set to "CenterImage". Assuming the function manages to calculate a valid size for the thumbnail it then generates the thumbnail image using the GetThumbnailImage method of the Bitmap holding the complete image we created earlier. This thumbnail image is assigned to the PictureBox's Image property and finally the bitmap is disposed of, clearing the whole picture from memory leaving only the much smaller thumbnail. If "strFileName" contains an empty string the picture box will be cleared.