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 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 named differently and can be accessed through the
drop down in the menu bar. Even though I showed some basic codes
in my past articles, I would like to refresh some of them here.
Since this is the beginner section, there is no harm to repeat
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 whole code is available for download, I will start
with some simple stuff, and probably stay simple in this entire
article. Please feel free to play with the code, and see if you
can come up 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 checks 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
'[email protected]' or click on 'help' button on the program.");
ReadMeFile.Close();
}
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 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 them ;) '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 red 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,
which 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 saves. I didn't want to spend much more time for this,
I 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 also wanted to show you my indentations. Which is more
compact if you see the whole code.
private
void EnableDisableControls(bool
StartStop)
{
// When SlideShow starts, most of the
controls should be Disabled
// and Enabled back when its stoped
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 slideshow starts, most of the controls need to be
disabled and abled 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 apposite from
the other controls :)
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 fo 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 altogether like this.
Last few words
Try to close anything you open in your code. Try to use
Exception catchers (Try..catch) to make your codes 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 al 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
actually works (well, hell yeah)... but I also enjoy trying to
find the answers for my problems as well. These articles so far
only for beginners just like me. I will be starting bit more
better coding, some more difficult coding. I hope you follow me
and take advantage of my codes to enhance yours, like I did with
this one... or, just let me know what else I can do to make my
codes better ;)
Download the whole code, and test it. If you like the idea,
enhance it and make it your own. There are many other functions
and controls can be put into this application, or just have the
idea and write your code from scratch.