Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Virtual Photo Album

0.00/5 (No votes)
25 Apr 2010 1  
Make albums from your photos anywhere on your HD and/or on network combined
VisualPhotoAlbum

See It In Action. Flash Video Clip

Before I start my third article, let me thank to Chandana Subasinghe for his article about the TreeView. I was looking to create my application using drive and file controls, but because I found his code, and it was easy to understand, I took it and enhanced it and implemented into my application. After all, I think we should do that often to learn new things.

Introduction

This application is called "Virtual Photo Album". I didn't use any third party components, so it should be easy for you to download the code and play with it. I will try not to use any third party components while I am learning C#.

Features

  • Locate and create separate album files of any images in your computer or combination of network computers
  • Rotate and save images
  • Start Slideshows for any album you selected

The idea of this program is that if you do have many photos and just want to show a few from here and a few from there to your friends and families... you don't have to move them into one folder, instead you can make a list of the images you want to show to different people. It creates different files with ".vpa" extension (Visual Photo Album) which are text files that go into "data" folder, which also sits in the application folder. Even if your photos are organized very well, it's just to make things easier if you want to combine a few photos from separate locations.

Background

There are no databases but only files to keep the path of the images. Each is named differently and can be accessed through the drop down in the menu bar. Even though I showed some basic code in my past articles, I would like to refresh some of them here. Since this is the beginner section, there is no harm in repeating stuff.

Using the Code

This program has less items in it. Only one form and a class module.

  • Form1 (Main Form)
  • FileExplorer.cs (Class module that does TreeView loading) I kept its original name from Chandana Subasinghe's article

Since the entire code is available for download, I will start with some simple stuff, and probably keep it simple in this entire article. Please feel free to play with the code, and see if you can come up with something better.

private void FileListCheck()
{
    if (Directory.Exists(@"data") == false) // Create data folder if not exist yet
    {
        Directory.CreateDirectory(@"data");
        WriteReadmeText(); // Create 'Readme' file.
    }
    else
    {
        if (File.Exists(@"data\\readme.txt") == false) {
            WriteReadmeText(); }
    }
    string[] MyFiles = Directory.GetFiles(@"data","*.vpa"); // Check the folder if any
                                            	// 'vpa' files exist 
					//(Virtual Photo Album file)

    if (MyFiles.Length > 0) // check if any files int he directory
    {
        char Splitchr = (char)92; // Slash character
        string[] SplitText;
        TSFiles.Items.Clear();

        foreach (string ReadFiles in MyFiles)
        {
            SplitText = ReadFiles.Split(Splitchr);
            TSFiles.Items.Add(SplitText.GetValue(SplitText.GetUpperBound(0)));
        }
    }
}

'Directory.Exists' and 'File.Exists' here from System.IO namespace check if my folder and file already exist. In my past applications, I used SystemFile object to do that, I honestly didn't know System.IO was available for me.
You can also see how 'Split' is done and how I actually used 'GetUpperBound' of the 'Split' method to fill my ListView's 'Name' field.

private void WriteReadmeText() // Create 'ReadMe text file'
{
    StreamWriter ReadMeFile;
    ReadMeFile = new StreamWriter(@"data\\readme.txt");
    ReadMeFile.WriteLine("Please do not delete files in this folder.");
    ReadMeFile.WriteLine("This folder used by 'Virtual Photo Album' - Copyrights (2010)");
    ReadMeFile.WriteLine("If you'd like more information about the 
			software and/or its author,");
    ReadMeFile.WriteLine("please contact 'Leo Koach' or click on 
			'help' button on the program.");
    ReadMeFile.Close();
}

This is a very simple 'File Write' method. Here I am creating my 'Readme.txt' file. Sometimes, we should leave some sort of clues to people what the files are in our application folders, so they won't play with them and break the program.

private void fleExp_AfterSelect(object sender, TreeViewEventArgs e)
{
    picBox.ImageLocation = "";
    if (fleExp.SelectedNode.ImageIndex == 3) {
        picBox.ImageLocation = fleExp.SelectedNode.FullPath; }
}

Here I used (cheat) 'ImageIndex' to find out my images in TreeView to show them on the PictureBox. All image files that I can show in the PictureBox get the same icon, which is #3 here. 'fleExp.SelectedNode.FullPath' gets me the whole path for the file.

private void ImgRotation(string IRotateValue, string ICurrentImagePath)
{
    try
    {
        if (picBox.ImageLocation == @"missing.png") {
            MessageBox.Show("Can not rotate default image", "Invalid Image",
                MessageBoxButtons.OK, MessageBoxIcon.Information);
            return; } // 'missing.png' is a default image can't be modified
        else {
            Bitmap Rotate_Bitmap = new Bitmap(ICurrentImagePath);

            switch (IRotateValue) {
                case "0": // Reset
                    Rotate_Bitmap.RotateFlip(RotateFlipType.RotateNoneFlipNone);
                    break;
                case "1": // 90 right
                    Rotate_Bitmap.RotateFlip(RotateFlipType.Rotate90FlipNone);
                    break;
                case "2": // 90 left
                    Rotate_Bitmap.RotateFlip(RotateFlipType.Rotate270FlipNone);
                    break;
                case "3": // Flip
                    Rotate_Bitmap.RotateFlip(RotateFlipType.Rotate180FlipNone);
                    break; }
            picBox.Image = Rotate_Bitmap; }
    }
    catch
    {
        MessageBox.Show("There is no image on the viewer", "Empty Viewer",
                        MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
    }
}

This method does the image rotation which is called from the menu buttons. If you look at it, it's very simple, even for a PictureBox... but, everything is easy after we learn it. ;) 'RotateFlipType' has other properties that you might want to try for your own codes.

private void TSFiles_SelectedIndexChanged(object sender, EventArgs e)
{
    // Open selected Album file and show its list in the Album List
    lstView.Items.Clear();
    StreamReader OpenAfile = new StreamReader(@"data\\" + TSFiles.Text.Trim());

    char Splitchr = (char)92;
    string[] SplitText;
    string LineData;
    while (OpenAfile.EndOfStream != true)
    {
        LineData = OpenAfile.ReadLine();
        ListViewItem s_Items;
        s_Items = lstView.Items.Add(Convert.ToString(LineData));
        SplitText = Convert.ToString(LineData).Split(Splitchr);
        s_Items.SubItems.Add(Convert.ToString
		(SplitText.GetValue(SplitText.GetUpperBound(0))));
    }
    picBox.ImageLocation = ""; // Clear the picture box
    SSLabel.Text = "Album Images : " + Convert.ToString(lstView.Items.Count);
}

Since I am repeating things in this article, this method has Split, once again, and how to enter data into ListView columns (in detailed mode). If you read my other two articles, you'd know how much I love to work with ListView control. I can keep many things in there that saves me tons of coding and probably memory too. Here I kept the full path of the image in the first column, with its width set to '0' so you can't see it, and the file name for the second column... the only thing visible in the Album list.

private void TSSaveimage_Click(object sender, EventArgs e)
{
    // Save images after rotated. This section should be fixed. It saves the
    // images although somehow changes image size.
    string[] SplitText;
    SplitText = picBox.ImageLocation.Split('.');
    switch (Convert.ToString(SplitText.GetValue(SplitText.GetUpperBound(0))).ToLower())
    {
        case "jpg":
            picBox.Image.Save(picBox.ImageLocation, 
		System.Drawing.Imaging.ImageFormat.Jpeg);
            break;
        case "tif":
            picBox.Image.Save(picBox.ImageLocation, 
		System.Drawing.Imaging.ImageFormat.Tiff);
            break;
        case "gif":
            picBox.Image.Save(picBox.ImageLocation, 
		System.Drawing.Imaging.ImageFormat.Gif);
            break;
        case "png":
            picBox.Image.Save(picBox.ImageLocation, 
		System.Drawing.Imaging.ImageFormat.Png);
            break;
    }

This is something new. If you do work or would like to work with PictureBoxes, here is how you can save the files in the PictureBox after some work done. In my case, rotation is the work. There is 'file size' problem though. It compresses the file when saved. I didn't want to spend much more time for this, I will let you find out the solution. :)

private void TSDeleteFile_Click(object sender, EventArgs e)
{
    // Deletes entire Album file.
    if (TSFiles.Text == "Select/Enter Album") {
        MessageBox.Show("select a file first!", "Selection missing",
            MessageBoxButtons.OK, MessageBoxIcon.Exclamation); return; }
    if (MessageBox.Show("Are you sure?", "Delete File", MessageBoxButtons.YesNo,
        MessageBoxIcon.Question) == DialogResult.No) { return; }

    lstView.Items.Clear();
    picBox.ImageLocation = "";
    File.Delete(@"data\\" + TSFiles.Text);
    FileListCheck(); TSFiles.Text = "Select/Enter Album";
    SSLabel.Text = "Album Images : 0";
}

This is how to delete a file. Obviously very simple 'File.Delete(FilPath)' but, I also wanted to show you my indentations, which is more compact if you see the entire code.

private void EnableDisableControls(bool StartStop)
{
    // When SlideShow starts, most of the controls should be Disabled
    // and Enabled back when it's stopped
    TSNewFile.Enabled = StartStop;
    TSDeleteFile.Enabled = StartStop;
    TSPlay.Enabled = StartStop;
    TSStop.Enabled = !StartStop;
    TSRotLeft.Enabled = StartStop;
    TSRotRight.Enabled = StartStop;
    TSFlip.Enabled = StartStop;
    TSReload.Enabled = StartStop;
    TSFit.Enabled = StartStop;
    TSSaveimage.Enabled = StartStop;
    TSEnterImage.Enabled = StartStop;
    TSRemoveImage.Enabled = StartStop;
    TSFiles.Enabled = StartStop;
    fleExp.Enabled = StartStop;
    lstView.Enabled = StartStop;
}

When the slideshow starts, most of the controls need to be disabled and enabled back when stopped. Now, I wrote this method to save tons of lines, but check out the  'TSStop.Enabled = !StartStop'... boolean switches from 'true' to 'false' or from 'false' to 'true' because I need that control disabled and enabled opposite from the other controls. :)

vpa_icons.jpg
int icons = 0;

    foreach (FileInfo file in rootDir.GetFiles())
    {
        TreeNode node = new TreeNode();
        node.Text = file.Name;
        // Set File icons. This portion can be larger depending on how many
        // files you want to have different icons for
        switch (file.Extension.ToLower())
        {
            case ".jpg": case ".gif": case ".tif": case ".png": // 4 image files
                icons = 3;
                break;
            case ".txt": case ".rtf":
                icons = 7;
                break;
            case ".pdf":
                icons = 8;
                break;
            case ".doc": case ".docx":
                icons = 4;
                break;
            case ".mdb": case ".accdb":
                icons = 5;
                break;
            case ".exe": case ".dll":
                icons = 9;
                break;
            case ".zip": case ".rar":
                icons = 10;
                break;
            case ".bmp":
                icons = 12;
                break;
            default:
                icons = 11;
                break;
        }
        node.ImageIndex = icons;
        node.SelectedImageIndex = icons;
        parentNode.Nodes.Add(node);
    }
}

Please see the whole code for TreeView creation. I only would like to show this portion which sets the icons of the items in the TreeView. As I mentioned at the beginning of the article, I kind of cheated to find out which files are images so I can show them in PictureBox... #3 icon for all the image files which can be loaded into the PictureBox control. There might be other files too, but 4 format is enough for this program. 'node.SelectedImageIndex = icons'  is the key here. If you don't put that line of code, you would end up having different icons showing on the clicked items of the TreeView.

private void TSExit_Click(object sender, EventArgs e)
{
    // Exit the program
    if (Application.MessageLoop)
    {
        // Use this since we are a WinForms app
        Application.Exit();
    }
    else
    {
        // Use this since we are a console app
        Environment.Exit(1);
    }
}

And this is my application exit routine. I saw it somewhere and made sense to me to use it all together like this.

Last Few Words

Try to close anything you open in your code. Try to use Exception catchers (Try...catch) to make your code stronger. Comment your code whenever you have time and organize your code when you think your brain is getting slower... Commenting and organizing your code while relaxing your brain helps you go through all the code once again and keeps you fresh with the whole code... and sometimes helps you to find bugs before you actually run the code.

Points of Interest

C# is one of the more fun languages (my second, so this is the best one after VB). I enjoy each moment of my programs when it actually works (well, hell yeah)... but I also enjoy trying to find the answers for my problems. These articles are so far only for beginners just like me. I will be starting a bit more better coding, some more difficult coding. I hope you follow me and take advantage of my code to enhance yours, like I did with this one... or, just let me know what else I can do to make my code better. ;)

Download the entire code and test it. If you like the idea, enhance it and make it your own. There are many other functions and controls that can be put into this application, or just have the idea and write your code from scratch.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here