Click here to Skip to main content
13,198,727 members (41,180 online)
Click here to Skip to main content
Add your own
alternative version


93 bookmarked
Posted 6 Dec 2008

Crystal Image Toolkit: thumbnail image control and picture viewing.

, 11 May 2011
Rate this:
Please Sign up or sign in to vote.
Thumbnail and image viewing controls for Windows Forms, using C#.



Back in 2006, I started working on Windows Forms applications in C#. I encountered a series of projects where I needed to display thumbnail images in a form control, but I needed to make the background, border, and text elements customizable. I developed a series of controls called the Crystal Image Toolkit that has allowed me to build applications that display both thumbnails and full images.

I probably shouldn't have named this Crystal, as people wrongly associate it with Crystal Reports. I had chosen the name because of a Marvel comics character. I was also thinking of Crystal Clear images, or maybe that song, Crystal Blue Persuasion. Or maybe, I'm just a nut!

Using the code

I will show you how to quickly add an image thumbnail control to your Windows Forms application.

First of all, download the Crystal Image Toolkit from the link above. Compile the code using the solution that I provided, which takes care of the toolkit and all the demo examples.

Create a new Windows Forms application in Visual Studio. In the Visual Studio toolbox, add a new tab called Crystal Image Toolkit (to separate it from Crystal Reports), and add the controls found in CrystalToolkit.dll.


Select the control called “CrystalImageGridView”. This is the control that displays the thumbnail images. Drag this control onto your new Form.


Now, go to the Properties window, with “crystalImageGridView1” selected. Change the Dock property to Fill. Change the Orientation property to Vertical.


After you set the properties, the image grid control should look like this:


The blue borders simply give you an idea of what the image items will look like in the selected state. The broken image bitmap is just a placeholder. At runtime, your images will be placed inside this blue rectangle. Yes, you can change many other properties, including the border color, background color, and so on. But for now, let’s accept the defaults.

Let’s write a little bit of code. Go to the Events tab, double click on Load, and generate the event on the Form. Now that you are in Form1.cs, let’s add this field at the top of the Form class:

/// <summary>
/// CrystalCollector object, assists in retrieving image files in a specified folder.
/// </summary>
private CrystalCollector _theCollector = null;

The CrystalCollector object is the controller in this framework.

The collector works with the CrystalImageGridView and the CrystalImageGridModel. It finds image files set in the ImageLocation property, creates objects to mirror those files as CrystalImageItem objects, and places those within the model. The collector spawns a background thread to start thumb-nailing the image items; this thread sends events to the view to tell it when an image thumbnail is available. That is what happens behind the scenes, but here in this simple example, you only need to add this method to your Form:

private void InitCollector()
     _theCollector =
     // Add the CrystalImageGridView object to the collector.
     // The collector will work with the view to draw the images.
     // Optional:
     // Set an initial folder to collect images.
     // If no folder is set, collector starts at MyPictures 
     // in WinXP or Pictures folder in Vista
         //("c:\\myImages", _theCollector);
     // Tell CrystalFileCollector to collect the images in the 
     // ImageLocation folder.
private void Form1_Load(object sender, EventArgs e)
protected override void OnFormClosing(FormClosingEventArgs e)
     if (_theCollector != null)

InitCollector creates the collector object using a factory. The type it chooses is a file-based collector. You could just create a new CrystalFileCollector yourself, but it is better to use the Factory. This can be used to track down objects getting created/destroyed later.

Once the collector has been created, we call SetupView, passing in the CrystalImageGridView object that we dropped onto the Form. This must be done before we gather any images. The collector creates a CrystalImageGridModel object and links up the view to it. The model must know about certain view properties, which affects how the image items will be displayed.

CollectImages is called at the end, which tells the collector to look at the ImageLocation and start gathering data about the images found there. In this case, we did not set the ImageLocation—the default is set to your Pictures folder (on Vista) or MyPictures folder (in WinXP). If you want to initialize another ImageLocation, use the code I commented out above the call to CollectImages.

Form1_Load calls InitCollector. But, there’s also the override to OnFormClosing, which calls the StopCollector method on the collector object. This call will stop any background threads going on to thumbnail the images.

After you compile this code and execute, you should see the thumbnails for whatever images are in your Pictures folder. Hopefully, they will be images of friends, family, and pets, instead of comic book images!


Play around with this form—you should see that the control responds to resizing events, making the number of image items per row grow or shrink the form. You can do Ctrl-click and Shift-click on image items for multiple selection as well.

Where are these thumbnail images stored? The CrystalThumbnailer object, which does the work of creating them, has a property called ThumbnailLocationRoot. By default, it is your AppData folder, under the name of your Company and Product name.


The collector creates a sub folder here based on the hash number of the original location. It stores the thumbnails here—the largest thumbnail size it needs to display. In these simple demos, the thumbnails will exist permanently. I’ve decided the behavior to retain or erase them is application dependent, and has left the choice up to you.

This is obviously a very simple example, but I have included many sample Form applications in the toolkit:

SimpleImageGridDemo shows a slightly more complex version of this application, by allowing you to open any folder and view the thumbnail images.

ZoomImageGrid shows you how to setup CrystalImageGridView to zoom the thumbnail size up or down. It's a bit of a hack; the thumbnails are stored in their largest possible size, and scaled down according to a property named ZoomFactor.

WaitFormPictureShow demonstrates how to use the CrystalMemoryCollector to load up images directly without having to scan a folder.

HeaderImageGridDemo explains how to put a list of CrystalImageItem objects into a CrystalGroupItem. Group items can be inserted into the model with a special header display that can be collapsed/expanded. Unfortunately, I haven't tested this with ZoomFactor.


PictureShowControllerDemo (above) shows you how to create a more realistic picture viewing application. A split container is used to hold the CrystalImageGridView in Horizontal orientation on the bottom pane. The top pane contains the CrystalPictureShow control, which is used to display images, magnify them, and present slideshows. There’s also a panning window that appears whenever the image is displayed in a non-fit mode.

ComicShowControllerDemo is a specialized image viewer that operates on comic-book files formatted for the CDisplay viewer, with a .CBR or .CBZ extension. You probably have never heard of these, but they are becoming the MP3-like standard for sharing comic books. CBR is really just a RAR file, and CBZ is a ZIP file. The factory will invoke specialized crystal collectors for these formats, unpack the images, and display them.

Points of interest

After I wrote the CrystalImageGridView, naturally, I needed to display a full image, but the PictureBox control wasn't enough. I needed to zoom\magnify the image, add a gradient background effect, get it to work with a panning window, and even do slideshows. I synthesized a lot of code from various articles here on CodeProject, but also from Bob Powell, who has contributed a lot of .NET GDI+ code in various forums. I've tried to credit him in the code for CrystalPictureBox and CrystalPictureShow, wherever possible.

If you run the PictureShowControllerDemo and hit the Slideshow button, you'll see these effects: Fade, Iris, Spin, and Slide.

I've learned a lot by writing this toolkit, but it's far from perfect. The collector only supports one view; I made a serious mistake early on by putting the rectangles for view display inside the model rather than have a separate data structure that the view would access. To fix this, I would have to rewrite a lot of code, but I'm ready to move on to a new project. I'm hoping my source code will benefit other people down the line.

Another improvement that I would have liked to make is to have the background thumbnailer thread be directed by the view. Currently, it thumbnails the images in the sorted order they are displayed in; it would be nicer to behave like Windows Photo Gallery and thumbnail the images viewed at the current scroll location.

There are some other controls here, such as a track bar, gradient panel, etc. I'm not supporting these, but I've left them in the toolkit because the samples make use of them.


  • Crystal Image Toolkit 1.0.0 - Dec 6, 2008.
  • Crystal Image Toolkit 1.0.1 - May 11, 2011: Source has been updated to Visual Studio 2010 and .NET Framework 4.0.


This article, along with any associated source code and files, is licensed under The GNU Lesser General Public License (LGPLv3)


About the Author

Richard Guion
Software Developer (Senior)
United States United States
Richard has been working with Windows software since 1991. He has worked for Borland, Microsoft, Oracle, and various startup companies such as Livescribe. Currently he is developing projects in C#, Windows Forms, and Net Framework. Visit his blog Attilan ( to learn more about his tools, projects and discoveries.

You may also be interested in...


Comments and Discussions

GeneralMy vote of 5 Pin
PierSilvio13-May-15 4:39
memberPierSilvio13-May-15 4:39 
QuestionDragging CrystalImageItem onto any user control Pin
Member 35068351-Aug-14 2:22
memberMember 35068351-Aug-14 2:22 
Question_picController.InitCollector(folderBrowserDialog1.SelectedPath, 0); Pin
Member 77325379-Jun-13 21:47
memberMember 77325379-Jun-13 21:47 
AnswerRe: _picController.InitCollector(folderBrowserDialog1.SelectedPath, 0); Pin
Richard Guion10-Jun-13 18:11
memberRichard Guion10-Jun-13 18:11 
QuestionRegister Component? Pin
kjward9-Jan-12 4:49
memberkjward9-Jan-12 4:49 
AnswerRe: Register Component? Pin
Richard Guion22-Mar-12 14:05
memberRichard Guion22-Mar-12 14:05 
Questionseveral groupItems Pin
computermorabbi@yahoo.com19-Aug-11 3:23
membercomputermorabbi@yahoo.com19-Aug-11 3:23 
AnswerRe: several groupItems Pin
Richard Guion31-Aug-11 10:57
memberRichard Guion31-Aug-11 10:57 
Questionplease help me Pin
computermorabbi@yahoo.com18-Aug-11 17:14
membercomputermorabbi@yahoo.com18-Aug-11 17:14 
AnswerRe: please help me Pin
Richard Guion18-Aug-11 19:01
memberRichard Guion18-Aug-11 19:01 
QuestionWPF? Pin
sbartlett00712-May-10 10:35
membersbartlett00712-May-10 10:35 
AnswerRe: WPF? Pin
Richard Guion14-May-10 8:38
memberRichard Guion14-May-10 8:38 
GeneralChange image sort by drag & drop Pin
ab-tools22-Apr-10 1:32
memberab-tools22-Apr-10 1:32 
GeneralRe: Change image sort by drag & drop Pin
Richard Guion14-May-10 8:39
memberRichard Guion14-May-10 8:39 
SuggestionRe: Change image sort by drag & drop Pin
ingbabic30-Jan-13 22:53
memberingbabic30-Jan-13 22:53 
SuggestionChange image sort by drag & drop Pin
Jaypalsinh31-Jul-15 2:57
memberJaypalsinh31-Jul-15 2:57 
QuestionDetect Scrolling? Pin
sbartlett00722-Jan-10 10:07
membersbartlett00722-Jan-10 10:07 
AnswerRe: Detect Scrolling? Pin
Richard Guion4-Feb-10 9:58
memberRichard Guion4-Feb-10 9:58 
GeneralRe: Detect Scrolling? Pin
sbartlett0075-Feb-10 2:27
membersbartlett0075-Feb-10 2:27 
GeneralIs it possible to choice images Pin
lualperi30-Nov-09 12:21
memberlualperi30-Nov-09 12:21 
GeneralRe: Is it possible to choice images Pin
Richard Guion1-Dec-09 8:56
memberRichard Guion1-Dec-09 8:56 
GeneralRe: Is it possible to choice images Pin
lualperi2-Dec-09 4:17
memberlualperi2-Dec-09 4:17 
GeneralCollection of selected images Pin
brandyrde6-Jul-09 13:27
memberbrandyrde6-Jul-09 13:27 
GeneralRe: Collection of selected images Pin
Richard Guion6-Jul-09 19:22
memberRichard Guion6-Jul-09 19:22 
GeneralLoad Images from Database Pin
mikeleeson22-May-09 2:09
membermikeleeson22-May-09 2:09 
GeneralRe: Load Images from Database Pin
Richard Guion26-May-09 11:55
memberRichard Guion26-May-09 11:55 
QuestionNeed help.. Pin
arison11821-May-09 20:36
memberarison11821-May-09 20:36 
AnswerRe: Need help.. Pin
Richard Guion26-May-09 11:42
memberRichard Guion26-May-09 11:42 
GeneralQuestion Pin
flakzeus25-Mar-09 7:09
memberflakzeus25-Mar-09 7:09 
GeneralRe: Question Pin
Richard Guion26-Mar-09 17:14
memberRichard Guion26-Mar-09 17:14 
GeneralVista Problem Pin
Daniel Hopper27-Jan-09 6:47
memberDaniel Hopper27-Jan-09 6:47 
GeneralRe: Vista Problem Pin
Richard Guion26-Mar-09 17:15
memberRichard Guion26-Mar-09 17:15 
GeneralOne trouble Pin
Wertugo5558-Dec-08 22:08
memberWertugo5558-Dec-08 22:08 
AnswerRe: One trouble Pin
Richard Guion9-Dec-08 10:01
memberRichard Guion9-Dec-08 10:01 
GeneralMy vote of 1 Pin
Wertugo5558-Dec-08 22:06
memberWertugo5558-Dec-08 22:06 
GeneralQuite cool Pin
Sacha Barber6-Dec-08 21:36
mvpSacha Barber6-Dec-08 21:36 
GeneralRe: Quite cool Pin
Richard Guion7-Dec-08 7:17
memberRichard Guion7-Dec-08 7:17 
GeneralRe: Quite cool Pin
Sacha Barber7-Dec-08 7:33
mvpSacha Barber7-Dec-08 7:33 

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.

Permalink | Advertise | Privacy | Terms of Use | Mobile
Web01 | 2.8.171020.1 | Last Updated 11 May 2011
Article Copyright 2008 by Richard Guion
Everything else Copyright © CodeProject, 1999-2017
Layout: fixed | fluid