Click here to Skip to main content
15,885,985 members
Articles / Programming Languages / C#
Tip/Trick

A Simple Thumbnail Viewer Control

Rate me:
Please Sign up or sign in to vote.
3.86/5 (3 votes)
3 Jul 2014CPOL1 min read 26.2K   1.4K   10   7
A very simple Thumbnail Viewer inherited from FlowLayoutPanel for beginners

Image 1

Introduction

This control allows you to add Thumbnail by dragdrop image from desktop and preview the Image by double-clicking on Thumbnail.

Using the Code

At first, declare an "ImageExtensions" List to make sure all files added to Control are Image Type.

C#
/// <summary> Image Extensions accepted by this control
        /// </summary>
        private List<string> ImageExtensions = new List<string> 
        { ".JPG", ".JPE", ".BMP", ".GIF", ".PNG" };

The DragDrop system is just simple, use DragEnter event to set an effect when user drags files to control and DragDrop event to deal with the files.

C#
 void ThumbnailViewerControl_DragEnter(object sender, DragEventArgs e)
        {
            if (e.Data.GetDataPresent(DataFormats.FileDrop))
                e.Effect = DragDropEffects.Copy;
            else
                e.Effect = DragDropEffects.None;
        }

void ThumbnailViewerControl_DragDrop(object sender, DragEventArgs e)
        {
            if (e.Data.GetDataPresent(DataFormats.FileDrop))
            {
                string[] files = (string[])e.Data.GetData(DataFormats.FileDrop);
                AddImage(files);
            }
        }

When dropped files to control, the AddImage method will add image to List as binary and then show a thumbnail on Panel by MakeThumbnail method.

C#
public void AddImage(string[] files)
        {
            this.Cursor = Cursors.WaitCursor;

            byte[] binary;
            for (int i = 0; i < files.Count(); i++)
            {
                // Only accept Image files
                if (ImageExtensions.Contains(Path.GetExtension(files[i]).ToUpperInvariant()))
                {
                    // Convert Image File to Binary
                    binary = File.ReadAllBytes(files[i]);

                    // Add binary data to List
                    ImageList.Add(binary);

                    // Create a Thumnail of Image and add Thumbnail to Panel
                    MakeThumbnail(binary);

                    GC.GetTotalMemory(true);
                }
            }

            this.Cursor = Cursors.Default;
        }

public void MakeThumbnail(byte[] binary)
        {
            // Create a Picture Box for showing thumbnail image
            PictureBox thumb = new PictureBox();
            thumb.MaximumSize = new Size(128, 128);
            thumb.MinimumSize = new Size(128, 128);
            thumb.Size = new Size(128, 128);
            thumb.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
            thumb.SizeMode = PictureBoxSizeMode.Zoom;

            // Create a border when Mouse entered
            thumb.MouseEnter += new EventHandler(thumb_MouseEnter);

            // Clear border when Mouse leaved
            thumb.MouseLeave += new EventHandler(thumb_MouseLeave);

            // Preview image when Mouse Double Clicked
            thumb.DoubleClick += new EventHandler(thumb_DoubleClick);

            // Set thumbnail image
            MemoryStream ms = new MemoryStream();
            thumb.Image = Image.FromStream(new MemoryStream(binary))
                .GetThumbnailImage(thumb.Width - 2, thumb.Height - 2, null, new IntPtr());
            ms.Close();

            // Add to Panel
            this.Controls.Add(thumb);
        }

Now, thumbnails are added to Panel, but to make it more prettier when user moves mouse cursor over it, use MouseEnter event to draw a border around thumbnail and clear border when Mouse leaves by MouseLeave event.

C#
void thumb_MouseLeave(object sender, EventArgs e)
        {
            ((PictureBox)sender).Invalidate();
        }

void thumb_MouseEnter(object sender, EventArgs e)
        {
            var rc = ((PictureBox)sender).ClientRectangle;
            rc.Inflate(-2, -2);
            ControlPaint.DrawBorder(((PictureBox)sender).CreateGraphics()
                , ((PictureBox)sender).ClientRectangle, Color.Red, ButtonBorderStyle.Solid);
            ControlPaint.DrawBorder3D(((PictureBox)sender).CreateGraphics()
                , rc, Border3DStyle.Bump);
        }

Thumbnail is small, right? So when user wants to "preview" full size image, let's show them a preview form created on thumbnail's mouse doubleclick event.

C#
void thumb_DoubleClick(object sender, EventArgs e)
        {
            Form previewForm = new Form();
            previewForm.FormBorderStyle = FormBorderStyle.SizableToolWindow;
            previewForm.MinimizeBox = false;
            previewForm.Size = new System.Drawing.Size(800, 600);
            previewForm.StartPosition = FormStartPosition.CenterScreen;

            PictureBox view = new PictureBox();
            view.Dock = DockStyle.Fill;

            int index = this.Controls.GetChildIndex((PictureBox)sender);
            view.Image = BinaryToImage(ImageList[index]);

            view.SizeMode = PictureBoxSizeMode.Zoom;

            previewForm.Controls.Add(view);
            previewForm.ShowDialog();
        }

On the event above, when doubleclicked on thumbnail, we must convert the binary data back to an Image, this method will do that job.

C#
public static Image BinaryToImage(byte[] binaryData)
       {
           if (binaryData == null) return null;
           byte[] buffer = binaryData.ToArray();
           MemoryStream memStream = new MemoryStream();
           memStream.Write(buffer, 0, buffer.Length);
           return Image.FromStream(memStream);
       }

That's all !!! This is just a tip for beginners, I recommend you add more methods to it like:

  • Delete Image method: Delete a selecting thumbnail, be careful with Panel control index and List item index.
  • BackgroundWorker: The UI will freeze when you add a large number of images, so a backgroundworker will handle it.
  • Threading: Large size image will consuming time. Try something like Parallel looping to make the process faster.

Thanks for reading and feel free to comment.

License

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


Written By
Software Developer (Junior)
Vietnam Vietnam
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
QuestionThank you for this!! Pin
bernardlawes30-Jan-23 6:29
bernardlawes30-Jan-23 6:29 
GeneralMy vote of 1 Pin
Fabrice CARUSO4-Jul-14 6:54
Fabrice CARUSO4-Jul-14 6:54 
GeneralRe: My vote of 1 Pin
Nguyen.H.H.Dang4-Jul-14 7:31
professionalNguyen.H.H.Dang4-Jul-14 7:31 
GeneralRe: My vote of 1 Pin
Fabrice CARUSO4-Jul-14 11:06
Fabrice CARUSO4-Jul-14 11:06 
GeneralRe: My vote of 1 Pin
Nguyen.H.H.Dang4-Jul-14 11:36
professionalNguyen.H.H.Dang4-Jul-14 11:36 
Thanks so much, sir. You turn on a light in my head :P

I have a question, may you please answer me ? If i have to store Image (or another File Types) on Database, and wanna do CRUD with it, what is the best way to do that ? I think a List of Binary is a bad way to do base on your above answer Frown | :(
In code we trust !

GeneralRe: My vote of 1 Pin
Fabrice CARUSO4-Jul-14 22:20
Fabrice CARUSO4-Jul-14 22:20 
GeneralRe: My vote of 1 Pin
Nguyen.H.H.Dang4-Jul-14 23:37
professionalNguyen.H.H.Dang4-Jul-14 23:37 

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.