\
Skip Navigation LinksHome > eZine > Peer 2 Peer > Article\
 
 
James Acosta With 6 years experience in software QA for small to mid-size development companies, and 4 years experience finding the right product solution for clients, James is the right man for the job and a valuable resource.

[]Recent Articles
[]Browse all by this Author



 
Icon of James AcostaWednesday, July 25, 2007
Creating a Filmstrip Style User Control in VB.2005
By James Acosta
 
Shout-Back! Read Comments  |  Post A Comment

If you've ever switched to Filmstrip view in Windows Explorer (XP and Vista) or used a product similar to Adobe Bridge that displays thumbnails of the pictures in a folder horizontally at the bottom while displaying a scaled version above, then you've seen a filmstrip control. 

Filmstrip DemoIf you're developing an application that displays pictures, a filmstrip control might come in very handy; too bad Visual Studio 2005 doesn't come with one.  Fortunately, its fairly simple to create one on your own similar to the example project pictured to the left (available in the download at the bottom of the article).  Although the individual components and coding could all be included on whichever form you're opting to have the filmstrip on, creating a user control simplifies this and enables you to reuse in other projects.

Start by opening Visual Studio 2005 (VS) and creating a new Windows Control Library project, named FilmstripControl.  Rename UserControl1.vb to Filmstrip.vb.

A simple filmstrip consists of little more than a control that displays thumbnails of one or more images, a label below each image (optional, but handy), the ability to scroll horizontally when there are more images than available space, and a mechanism by which your program is alerted with the name of the thumbnail clicked.   Approaching this from the "easy direction", thumbnails are easily displayed using the PictureBox control and labels with the Label control.  Our new user control provides us with a blank working environment, but that environment may not be the best starting place.  As our filmstrip will essentially be grouping PictureBox and Label controls together, we should look at starting with one of the VS existing Container controls, such as the Panel control.  The filmstrip control needs the ability to hold more thumbnails than the user's display might make visible at one time, which means we need to have the ability to scroll as needed.  We could use the blank user control environment and a VScrollBar control hidden when not needed, but that is a lot of extra coding that the Panel control already takes care of for us.

To build on the existing Panel control, switch the Solution Explorer's view from the default view to the "Show All Files" view, using the toolbar button.  Once this view is enabled, additional files under the Filmstrip.vb control will be come visible.  Double-click Filmstrip.Designer.vb. In order to work with an existing control, we need to change where our new control inherits from.  At the top of the designer file, you will see a statement that reads Inherits System.Windows.Forms.UserControl.  Change UserControl to Panel. Before you close the file, you will notice that towards the bottom of the class definition, VS has indicated that Me.AutoScaleMode is now in error.  Because this is part of the UserControl environment and not the Panel environment, you can delete this section.  Remove the InitializeComponent subroutine including the <System...> _ line and the commented notes above it.  Switch back to the Filmstrip.vb file.  If you went into the GUI design view, you will no longer see the blank environment, but rather a notice about switching to code view.  Switch to the code view.

To facilitate adding images to the filmstrip, we need the control to expose a method (subroutine) to the designer that takes the name of the image file to add.  Next, because our control has no static images, we need to create a new PictureBox control, size it appropriately for a thumbnail, and load / size the image.  Because we also want to display the name of the image below the thumbnail, we need to also create a new label control with the text property properly set. 

Public Sub AddPicture(ByVal strFileName As String)
    Dim objFileInfo As System.IO.FileInfo objFileInfo = _
        My.Computer.FileSystem.GetFileInfo(strFileName)

    Dim NewPictureBox As New PictureBox
    NewPictureBox.Image = Image.FromFile(strFileName)
    NewPictureBox.Size = New Size(100, 100)
    NewPictureBox.SizeMode = PictureBoxSizeMode.Zoom
    NewPictureBox.Tag = strFileName

    Dim NewLabel As New Label
    NewLabel.Text = objFileInfo.Name
    NewLabel.AutoEllipsis = True
    NewLabel.AutoSize = False
    NewLabel.TextAlign = ContentAlignment.MiddleCenter
End Sub

We've made a few assumptions with our thumbnail in this code.  First, the size of the thumbnail is a maximum of 100 by 100 pixels, and to resize the picture the PictureBox control is set to zoom.  Although this is fine for our demo, a better control would resize the thumbnails as appropriate for the size of the control, and to conserve the amount of memory used, the PictureBox control would actually generate a thumbnail image instead of dynamically shrinking the full image down to fit the size of the control.  The download contains a second take on our final results that includes both these actions. The name of the original file is also stored in the Tag property so we can identify it later.

The next step is to add the new controls to the Panel control and position them properly.  In order to put them in the right spot, we need know where in the control they should be placed.  The horizontal position remains constant, a simple line-up of all the PictureBox controls.  The vertical position is derived by keeping track of the widths of all previously placed PictureBoxes plus the widths of all padding in-between and setting the Left property to this position.  This is accomplished by creating an integer variable to keep track of the offset distance.  This should be a class-level variable instead of a subroutine-level static variable as other routines will need to access the variables value.  Once our new PictureBox is added to the Panel and positioned, our new label is then added and placed directly below:

Public Class Filmstrip
    Private Offset as Integer = 5

and

    NewLabel.TextAlign = ContentAlignment.MiddleCenter

    NewPictureBox.Location = New Point(Offset, 5)
    Me.Controls.Add(NewPictureBox)

    NewLabel.Location = New Point(Offset, _
        5 + NewPictureBox.Height)
    Me.Controls.Add(NewLabel)

    Offset += NewPictureBox.Width + 5
End Sub

Because we have set the size of the thumbnail to a 100 pixel square and a label below, we need to set a minimum size for the control when placed so as to correctly display the informtion.  We also need to take into consideration that when the width of the added thumbnails exceed the visible width of the Panel control, scroll bars will appear.  This is OK for horizontal scrolling, but vertical is not expected so we need to add additional height.  Because there is no physical control we have to set default values programmatically in the controls New event:

Public Sub New()
    Me.AutoScroll = True
    Me.MinimumSize = New Size(300, 150)
End Sub

We should also add a way to remove all the thumbnails.  This is a very straightforward process - just delete all controls contained within the Panel, reset the new PictureBox location offset, then reset the scrollbars (they won't go away by themselves when you programmatically delete the contents):

Public Sub Clear()
    While Me.Controls.Count > 0
        Me.Controls.Remove(Me.Controls.Item(0))
    End While
    Offset = 5
    Me.AutoScroll = True
End Sub

Our last task is to provide the developer notice when a user selects a thumbnail.  This is a little more complicated than adding a simple method or code to an intrinsic event.  In order to provide this information we need to create a custom event.  Start by adding the general event definition to the class:

Public Class Filmstrip
    Public Event OnImageClicked( _
        ByVal sender As System.Object, ByVal e As EventArgs)

With the event defined, we need to create the routine that will generate the data we will pass to the developer when the user performs the mouse click action (at this point we haven't defined what action triggers our event).   

Private Sub Image_Click( _
    ByVal sender As Object, ByVal e As EventArgs)

    Dim pb As PictureBox = CType(sender, PictureBox)

    RaiseEvent OnImageClicked(pb.Tag.ToString, e)
End Sub

This routine doesn't look like much.  As is, the subroutine provides us with the sending object (the dynamically created PictureBox).  The Tag property contains the path to the displayed file, so all that is needed is to extract the data and pass it as an argument for the event, which we raise (the definition for our custom event uses the sender parameter as a System.Object; anything, including a string, can be passed as a System.Object.)

With our defined event linked to a routine that generates the data, our last act is to link the generation routine to the click action of our dynamically created PictureBox.  To do this we need to add a command to our AddPicture routine:

NewPictureBox.Tag = strFileName

AddHandler NewPictureBox.Click, AddressOf Image_Click

Dim NewLabel As New Label

This is all we need to complete the simple user control.  The next step is to test it out.  Add a new standard Windows application project to our current project.   Make sure you save the entire solution, as our custom control will not become available to you until the first save/build.  Once saved and built, switch over to the Form1 in the new project and you will see the Filmstrip control at the top of the toolbox.

Drag the Filmstrip control and two buttons to the form.  You will notice that the Filmstrip control defaults to the size we set.  Switch to the code view and add the following to the Form1 class:

Private Sub Button1_Click( _
    ByVal sender As System.Object, _
    ByVal e As System.EventArgs) _
    Handles Button1.Click

    Me.Filmstrip1.AddPicture("C:\Windows\Blue Lace 16.bmp")
End Sub

Private Sub Button2_Click( _
    ByVal sender As System.Object, _
    ByVal e As System.EventArgs) _
    Handles Button2.Click

    Me.Filmstrip1.Clear()
End Sub

Private Sub Filmstrip1_OnImageClicked( _
    ByVal sender As Object, _
    ByVal e As System.EventArgs) _
    Handles Filmstrip1.OnImageClicked

    MsgBox(sender.ToString)
End Sub

The code is relatively straightforward and needs very little explanation.  The program will add the same image over and over as we don't have a user-selection dialog coded in, so you need to change it to an image you desire.  Before we test it, we need to set the added project to the start up project by right-clicking the new project in the Solution Explorer window and selecting "Set as StartUp Project".

Build the solution and try out the buttons.  In very little coding you've created a simple filmstrip.  The download contains both the completed demo project, as well as a second take on the filmstrip that expands on the concept to include dynamic resizing of the control and better memory management of images.


Download Download the content mentioned in this article:
Subscriber Download   Click Here to Download the Subscriber Content
Standard Download   {No standard content associated with this article}



Comments: [0]   [Show Disclaimer]

Post a Comment
Display Name:
Comment:
(Plain text only - all HTML will be stripped)

Would you like to post your article here or have a topic you would like to see written about? We are always looking for great technology articles and ideas to share with our readers. Inquire Here.

 FAQs  |  Terms Of Use  |  Privacy Policy  |  Contact Us
Copyright © 1997 - 2010 Dx21, LLC. All rights reserved.
Dx21, LLC a Washington Limited Liability Company
Page Rendered at: 9/9/2010 12:07:42 PM for Unknown