The program presented here allows you to build a slideshow from pictures and add background music. Everything is packed into a single executable file, so you just need to send one file to distribute your slideshow.
- Build a slideshow from pictures
- Add background music
- Save project files for future use
- Specify various options
These are the options that you can choose:
- Loop the slideshow
- Loop background music
- Stretch images to full screen or leave the original size
- Choose the background color (if the images aren't stretched)
- Disable or Enable the Escape key during the slideshow
- Advance to next slide either after a specified amount of time or on mouse click
- Specify an icon for the generated slideshow
The program builds the slideshow player program using the
CompilerParameters classes. The images and music that the user has chosen are added as embedded resources. In order to pass options from slideshow builder to slideshow maker, I have created a special class called
Settings, which stores information about the options that are chosen. The class is marked as
Serializable and it is serialized to an XML file using the
XmlSerializer class. The serialized file is also added as an embedded resource in the player application. When it is launched, the player application deserializes it and retrieves the options.
I will talk more below about the source code of the slideshow player application, which is compiled at run time, but I want to mention one important point here: Regardless of the number of pictures and options that the user has chosen, the source code that is compiled is always the same. It gets all the information from the
Settings class at runtime.
When you launch the program, it associates the *.ssb extension with the program. The project files that you save will have the *.ssb extension, so when you double click them, the SlideShowBuilder will be launched showing the content of the file you have double clicked. The project files have an icon associated with them, too. A command is associated with double click and it passes the name of the file as an argument to the program. All this is accomplished with the code presented below:
private void registerextension()
RegistryKey RegKey = Registry.ClassesRoot.CreateSubKey(".ssb");
RegKey.SetValue("", "ssb files");
RegKey = Registry.ClassesRoot.CreateSubKey("ssb files");
RegKey.SetValue("", "Slide Show Maker Files");
RegKey = Registry.ClassesRoot.CreateSubKey("ssb files" + "\\" + "Shell"
+ "\\" + "Open");
RegKey = RegKey.CreateSubKey("Command");
"\"" + Application.ExecutablePath + "\"" + " \"%L\"");
RegKey = Registry.ClassesRoot.CreateSubKey("ssb files" + "\\"
When you double click the file, the program gets the path of the file as a command line argument. Then the program opens the file that was double clicked.
static void Main(string args)
Form1 parent = new Form1();
if (args.Length == 1)
In order to save project files for future use, I used serialization again, but this time I used Binary Serialization. The reason is that it is faster and produces smaller files than other serialization techniques. To store information about the project, I have created a class called
ssbfile. This class keeps information about the location of all files in the project and various options that have been selected. After you have created an instance of a serializable class, saving it to a file is very easy. Just create an instance of the
BinaryFormatter class and call the
public void save(string path)
Stream str = File.Open(path, FileMode.Create, FileAccess.Write,
BinaryFormatter formatter = new BinaryFormatter();
isdirty = false;
Deserializing is even easier. You only need to remember to cast the result to a proper type.
Stream str = File.Open(path, FileMode.Open);
ssbfile file = null;
BinaryFormatter formatter = new BinaryFormatter();
file = formatter.Deserialize(str) as ssbfile;
MessageBox.Show("The file can not be opened", "Error",
this.exists = true;
this.Path = path;
When the build button is clicked, settings are serialized to a temporary file. Using XML serialization is easy, too. The only difference is that you need to specify the type of object you are serializing.
private void Serialize(Settings set)
Stream stream= File.Open(Form1.temp+"\\settings.xml", FileMode.Create);
XmlSerializer formatter = new XmlSerializer(typeof(Settings));
After this, all the images are copied to a temp folder and their names are changed to 1.jpg, 2.jpg, etc. The reason for this is that the player application will access them using these names. If the names remained the same, either the source code of the player application would have to be changed dynamically or the names would have to be passed to the player, too. Apart from that, this style of naming makes it very easy to know which image comes after which.
So at this point, all necessary files have been copied to the temp folder. Now it is time for compilation!
As I have already mentioned, to generate an executable file from your program you will need the
CompilerParameters classes. The code snippet below shows all the necessary steps:
private bool compile(string path)
bool result = false;
using (CSharpCodeProvider code=new CSharpCodeProvider())
CompilerParameters compar = new CompilerParameters();
string pathtoicon = "";
if( !string.IsNullOrEmpty(iconbox.ImageLocation) &&
compar.CompilerOptions = "/target:winexe" + " " + "/win32icon:"
+ "\"" + pathtoicon + "\"";
compar.GenerateExecutable = true;
compar.IncludeDebugInformation = false;
for (int i = 1; i < filelistbox.Items.Count+1; i++)
compar.EmbeddedResources.Add(Form1.temp + "\\" + i.ToString() + ".jpg");
if (this.backmusiccheck.Checked && File.Exists(musicpath.Text))
compar.EmbeddedResources.Add(Form1.temp + "\\music.mp3");
compar.EmbeddedResources.Add(Form1.temp + "\\settings.xml");
compar.OutputAssembly = path;
compar.GenerateInMemory = false;
compar.TreatWarningsAsErrors = false;
CompilerResults res = code.CompileAssemblyFromSource(compar,
if (res.Errors.Count > 0)
result = false;
result = true;
This is how to build an executable file from your program. Now let's see how to run the slideshow.
So we have successfully built the slideshow and we are going to run it. Firstly, I will describe it in general and then go into details.
The player application consists of one form, one picturebox and one button. The button is under the picturebox and is not visible. You might be wondering why we need a button at all. The answer is that we need it for disabling the Escape key. The button is set as
CancelButton of the form, so when the user clicks the Escape key, the application either quits or continues depending on the options that the user has chosen. A little trick.
When you run the generated slideshow, settings are deserialized and various options are set according to it. After that, the slideshow begins.
In order to deserialize options, we need a stream that contains the XML document to deserialize. As the XML document is embedded in the application itself, we can retrieve it using classes and methods in the
System.Reflection namespace. Then we will be able to deserialize the XML document. Here are the details:
XmlSerializer ser = new XmlSerializer(typeof(Settings));
Stream st =
set = ser.Deserialize(st) as Settings;
If the user has added background music, then it will be extracted to temp folder.
private string extractmusic()
string path = Environment.GetEnvironmentVariable("TEMP") + "\\music.mp3";
Stream musicstream =
BinaryReader read = new BinaryReader(musicstream);
FileStream fs = new FileStream(path, FileMode.Create);
BinaryWriter write = new BinaryWriter(fs);
byte bt = new byte[musicstream.Length];
musicstream.Read(bt, 0, bt.Length);
To play the extracted file, I use this class. It allows you to loop playing very easily.
private void playmusic(string path)
MP3Player player = new MP3Player();
player.Looping = set.Loopmusic;
After retrieving the options and setting them, the first picture is displayed. If the user has chosen to advance to the next image by a mouse click, then the application waits for it. Otherwise, after a specified time interval, the image changes automatically. Images are also retrieved using reflection and they are either stretched to full screen or they are left as they are. When a new image is shown, the application is set as
private void setimage(int index)
Image temp =Image.FromStream(
index.ToString() + ".jpg"));
this.pictureBox1.SizeMode = PictureBoxSizeMode.StretchImage;
if (pictureBox1.Height >= temp.Height && pictureBox1.Width >= temp.Width)
pictureBox1.SizeMode = PictureBoxSizeMode.CenterImage;
pictureBox1.SizeMode = PictureBoxSizeMode.StretchImage;
pictureBox1.Image = temp;
this.TopMost = true;
current = current % set.Count + 1;
That's all !!!
XML serialization is quite powerful and easy to use. It helps you to exchange information between different applications. The ability to embed files in an assembly and retrieve them dynamically from the assembly itself is a powerful feature, too. What I like most about this program is that the compiled source code is the same and doesn't depend on the files and options you have chosen.
- June 21, 2007 - Initial Release
- October 26, 2007 - Article updated