Click here to Skip to main content
15,878,959 members
Articles / Desktop Programming / Windows Forms
Article

Filmstrip control for Windows Forms

Rate me:
Please Sign up or sign in to vote.
4.73/5 (30 votes)
27 Jun 2008CPOL9 min read 84.4K   4.9K   96   29
An article describing a C# Filmstrip control designed for Windows forms
Filmstrip control

Contents

Introduction

Whilst there seems to be a number of feature-rich filmstrip controls available for web applications, there are precious few for normal windows forms applications. I did read rahulparthe's article but that did not provide the required functionality. So my effort here has been developed from the ground up with no other inspiration.


Using the Code

The control is built into it's own dll, Filmstrip.dll, and uses the Filmstrip namespace. You can add a reference to the compiled dll or you can directly copy the source files to a folder on your project. The code is currently designed so you can just copy the source files, it doesn't need any extra resources. (This means displayable strings are hard-coded as constants rather than in the string table as they should be.) Once the reference has been added, ensure that it appears in the toolbox, then simply drag the control onto a form.

Features

The Filmstrip control has the following features:

  • Dynamically add one or more images.
  • Dynamically remove a single image, or clear the entire control.
  • Dynamically clear the selection in the control.
  • Automatic update of the the thumbnails displayed as the control is resized.
  • User-defined location for the thumbnails strip.
  • User-defined colour-scheme for the entire control.
  • Automatic scrolling - hovering the mouse over a navigation button causes the thumbnails to scroll in the appropriate direction after a configurable delay time.
  • Tooltips - Each thumbnail displays it's description and it's index into the collection.
  • Editable description - double-clicking on the main image will display a simple form that allows it's description to be amended.
  • Full keyboard access - As each thumbnail is a button, users can tab between each thumb and select using the Space key. The Home, End, PageUp and PageDown keys are also supported. The accelerator combination to display the edit description form is also customisable.
  • Feedback on control activity via events for when the selection, or the description of the selected image, changes.
  • Add custom images to the navigation buttons.
  • Design-time support.

Quick-start

  • Add a reference to the Filmstrip.dll to your project.
  • Drag the FilmstripControl onto a form.
  • Set the required control properties in the designer.
  • Add the images required in the form's OnLoad handler, or elsewhere, as required. (Note that all images have to be associated with a numeric id value.) The sample application displays the 3 different ways of doing this...
    C#
    // Using the AddImage overloads
    filmstripControl.AddImage(
        new FilmstripImage(Properties.Resources.Zugspitze as Image, 
                 "Zugspitze, Germany"));
    filmstripControl.AddImage(Properties.Resources.ChobeSunset as Image, 
                "Sunset at Chobe National Park, Zambia");
    
    // Or adding many images, chosen from an OpenFileDialog...
    if (DialogResult.OK == openFileDialog.ShowDialog())
    {
        List<FilmstripImage> images = new List<FilmstripImage>();
        foreach (String file in openFileDialog.FileNames)
        {
            Image thisImage = Image.FromFile(file);
            FilmstripImage newImageObject = 
                new FilmstripImage(thisImage, file);
            images.Add(newImageObject);
        }
        filmstripControl.AddImageRange(images.ToArray());
    }
  • Implement any specific functionality required for using the image selected in the Filmstrip control by using the event handlers and appropriate properties.
  • Err..... that's it.

Public properties

The Filmstrip control has a number of public properties. These can be categorised into 2 areas: visual and functional.

The visual properties are used to modify/customise the visual look and feel of the control. It is possibly to change the background colour of the entire control (and also the colour of the selected hightlight), to replace the left and right navigational buttons with custom images and to specify where the thumbnail strip is displayed among other things.

PropertyRead only?Description
ControlBackgroundNoSpecifies the background colour of all items on the filmstrip control. Default value is 'Control'.
EditDescriptionAcceleratorNoSets the accelerator key combination to display the edit description form for the currently selected image. Default is Ctrl+D.
ImageNavLeftNoSpecifies the image to be used for the left navigation button. If no image is specified the button text will have '<'.
ImageNavLeftLayoutNoSpecifies the image layout used for the left navigation button image, if an image is present. Default value is 'Stretch'.
ImageNavRightNoSpecifies the image to be used for the right navigation button. If no image is specified the button text will have '>'.
ImageNavRightLayoutNoSpecifies the image layout used for the right navigation button image, if an image is present. Default value is 'Stretch'.
MainImageLayoutNoSpecifies the image layout for the image selected into the main viewing area. Default value is 'Center'.
ScrollHoverDelayNoSpecifies the delay interval (in milliseconds) used before scolling the thumbnail view whenever the mouse hovers over a navigation button. Default value is 500ms.
SelectedHighlightNoSpecifies the colour of the highlight surrounding the selected thumbnail image. Default value is 'DarkBlue'.
ThumbsStripLocationNoSpecifies the location of the strip of thumbnail images, either 'Top' or 'Bottom'. Default value is 'Bottom'.

The functional properties relate to the data used by the control:

PropertyRead only?Description
ImagesCollectionNoThe images collection. Setting this property will remove any images currently in the collection.
SelectedImageYesThe image currently selected in the control.
SelectedImageDescriptionNoThe description of the image currently selected in the control.
SelectedImageIDNoSpecifies the image id of the image currently selected in the control.

Public methods

The control has only a few public methods. These were kept to a minimum in order to retain simplicitiy and ease of use:

AddImageThis method adds a single image to the control. The new image is added at the end of the control's internal collection. (3 overloads.)
AddImageRangeThis method adds multiple images to the control. The new images are added at the end of the control's internal collection.
ClearAllImagesThis method removes all images from the control.
ClearSelectionThis method removes any selection from the control so that no image is selected.
EnsureThumbIsVisibleThis method ensures that the thumb for the specified image is visible in the thumnbails strip. It does not affect the current selection.
RemoveImageThis method removes the specified image from the control.

Note: At present, AddImage (all overloads), AddImageRange and RemoveImage all cause the entire thumbnails list to be repopulated, which does cause a slight flicker. It is advised that when adding many images after the control has been initially displayed (i.e. not in the OnLoad handler) use the AddImageRange method, as this will only cause the thumbnails list to be repopulated once.

Public events

The control fires 2 different events:

SelectionChangedThis event is fired when the selected image in the control changes.
SelectedImageDescriptionChangedThis event is fired when the description of the selected image changes within the control.

Control internals

The Filmstrip.dll assembly contains the following public 'objects':

FilmstripControlThe actual filmstrip control.
FilmstripControl.StripLocationA simple enum used to specify the position of the thumbnails strip on the control. It currently only has values for 'Top' and 'Bottom'.
FilmstripImageA simple class to encapsulate an image inside the control.

Control architecture

Each image added to the control is stored internally as a FilmstripImage object in standard Dictionary. Each FilmstripImage has it's own ID - this is required and is a whole number. If an image id is not specified then one is generated during the AddImage call and returned to the caller. The only invalid value for an image id is -1: this is specified by the static class member NO_SELECTION_ID.

The most challenging aspect of developing the control has been ensuring that the collection of thumbnails is constructed, populated and rendered correctly, especially when the control is being resized.

The strip of thumbnails is dynamicaly created depending on the the number of images in the control's collection and the current size of the control. The entire strip, including navigation buttons, is contained on a panel so that it can be moved to the desired location on the control. On the strip itself the thumbnails themselves are located on another panel that is sandwiched between the 2 navigation buttons. The navigation buttons are of fixed size and position - i.e. they maintain their position relative to the sides of the control. In this way the panel containing the thumbnails grows or shrinks with the control. The control maintains a collection of all thumbnail Button objects currently in use - the thumbnailControls member.

Thumbnails panel design

Given that each thumbnail panel and button are a fixed size, it is possible to calculate the number of thumbnails that can fit into the parent panel at any time. Whenever the control width alters it checks to see if it is displaying the full number of thumbnails possible, and then adds or removes thumbnails as necessary. In either case we have to account for the fact that window hosting the form may have been maximised or 'un-maximised' so we may have to add or remove more than one thumbnail at a time. This is all done in the AdjustThumbnails function. So when the control gets bigger:

C#
// Did we get bigger, and we have't yet created thumbs for all the images we have?
while ((thumbnailControls.Count < ThumbsForWidth()) 
            && (thumbnailControls.Count < imagesCollection.Count))
{
    // Get the image id of the current last one
    int imageIDOfLast = -1;
    if (thumbnailControls.Count > 0)
    {
        imageIDOfLast = 
            Convert.ToInt32(thumbnailControls[thumbnailControls.Count - 1].Tag.ToString());
    }
    
    // Add a new one
    int newIndex = PushThumbnail();
    
    // If we're already at the right hand end, we need to shift all the images across
    // (as if the left navigation button was clicked)
    if ((imageIDOfLast > -1) && (keys[keys.Count - 1] == imageIDOfLast))
    {
        MoveThumbnailsLeft();
    }
    else
    {
        // Set the image on this new thumb
        PopulateThumbnail(newIndex);
    }
}    

But thankfully when the control gets smaller the code is much simpler:

C#
while (thumbnailControls.Count > ThumbsForWidth())
{
    PopThumbnail();
}    

Sample application

Filmstrip control sample application

The sample application provided demonstrates how the Filmstrip control can be easily integrated onto a form. It provides the following functionality:

  • How to add images (at load-time and dynamically after loading).
  • How to remove images.
  • How to clear the control.
  • It allows for dynamic changing of many (but not all) of the visual properties.
  • It displays details of the image currently selected in the control using only the information provided by the control.
  • How to set the control selection.
  • How to update the description of the selected image.

There are a few things of note in the sample application:

  1. The default images are built into the sample application and their initial descriptions are hard-coded.
  2. There is an internal counter for the image id. This starts at 1 and is incremented with every new image added.
  3. When adding new images using the 'Add..' button. The full filename is set as the description to each image.
  4. The application uses a 3rd-party control for the colour picker combos. This control is located in the OfficePickers.dll assembly, details of which can be found in the article: Office 2003 Color Picker.

Techinical note

All code was developed using Visual Studio 2005 Professional and Express editions on Windows XP (Home & Professional). It has not been fully tested using any other versions of Visual Studio, the .Net framework or on other operating systems, as I do not have access to them. (Although limited testing on earlier versions was done on Windows 2000 and Windows 2003 Server.)

Revision history

  • 17/06/2008 - v.1.0 - Initial public release.
  • 18/06/2008 - v.1.1
    • Corrected namespace usage internally.
    • Added Toolbox image.
    • Minor change to the naming of the public events (removed the 'On' at the start).
    • Added design-time support.
    • Made EnsureThumbIsVisible method public.
  • 27/06/2008 - v.1.2
    • Some code re-organisation and refactoring.
    • Added keyboard handling for use of Home, End, PageUp and PageDown keys.
    • SelectedImageDescription property now writeable.
    • Modified usage of image ids. These can now be omitted when adding images and an image id is assigned internally. As a result a new AddImage overload has been created, along with a new overloaded constructor for the FilmstripImage class. Additionally all AddImage methods now return the image id of the image added. If required, image ids can now be negative. The only value invalid value is -1, which is specified by the static member NO_SELECTION_ID.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
United Kingdom United Kingdom
After studying to be a historian at Corpus Christi College, Oxford I discovered the fact that there really _isn't_ any money in studying 17th liturgical theology. I sort of fell into a programming job and am still here more than 10 years later.

Comments and Discussions

 
GeneralRe: tab control Pin
callisthenes30-Mar-09 11:57
callisthenes30-Mar-09 11:57 
GeneralRe: tab control Pin
Geepster30-Mar-09 12:13
Geepster30-Mar-09 12:13 
GeneralAddImage Pin
tomi_224-Jun-08 10:58
tomi_224-Jun-08 10:58 
GeneralRe: AddImage [modified] Pin
callisthenes24-Jun-08 22:40
callisthenes24-Jun-08 22:40 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.