Introduction
This is the second version to the application. I made changes according to the remarks posted by the viewers.
This is an attempt to create a simple application that has a simple GUI and still does all the desired functionality. I wanted an application that collects the images by itself and spares me that feature.
The following subjects are discussed in this article:
- Setting a wallpaper using WinAPI.
- Using
xmlWriter
for file writing.
- Image File type changing.
- Getting all the files from a directory recursively.
- Separating files from directories in a collection.
- Implementing Drag & Drop scenario.
- Showing the application in the traybar.
Background
To change the Desktop background, the application needs to use the WinAPI SystemParametersInfo
and supply it with the desired image parameters. The only problem is that the API accepts only the BMP image type. My solution was to create a BMP from each JPG or JPEG file in the directory.
Using the code
- Setting a wallpaper using WinAPI:
The API function "SystemParametersInfo
" has many usages. I will use the SPI_SETDESKWALLPAPER
parameter which tells the system to change the wallpaper. The SPIF_SENDCHANGE
parameter tells the system to send all the open windows an acknowledgement message about the wallpaper changing.
nResult = WinAPI.SystemParametersInfo(SPI_SETDESKWALLPAPER,
1, fileName, SPIF_SENDCHANGE);
- Using
xmlTextWriter
for file writing:
My xml file holds the last selected image that was wallpapered. After each wallpaper changing, the xml file will be updated so that the next time the application uses the proper image. The xmlTextwriter
must start with writer.WriteStartElement
and end with writer.WriteEndElement
. In the middle, each element is added using its name and value: "picIndex
", tempPicIndex.ToString()
. The flush
method forces the writer to immediately write the data. The Close
method closes the writer.
XmlTextWriter writer =
new XmlTextWriter(m_settingsPath + "\\settings.xml", null);
writer.Formatting = Formatting.Indented;
writer.Indentation = 4;
writer.WriteComment("Settings for WallPaper changer program");
writer.WriteStartElement("settings");
writer.WriteElementString("picIndex", tempPicIndex.ToString());
writer.WriteElementString("Interval", tempGlobalInterval.ToString());
writer.WriteEndElement();
writer.Flush();
writer.Close();
- Image File type changing:
First, you need to create a BMP file in the memory using the Bitmap
constructor, and then you need to save the new file to the local HD.
Bitmap theImage = new Bitmap(fileName);
theImage.Save (localPath + "\\new.bmp",
System.Drawing.Imaging.ImageFormat.Bmp);
- Getting all the files from a directory recursively:
In order to get all the files from all sub-directories, the application needs to use the Directory
class. I used a recursive method to gather all files. I got all the files from each sub-directory to a string
array and added each one of them to the ListBox
.
string[] dirs = Directory.GetFiles(localPath , fileType);
foreach (string dir in dirs){
mycheckedListBox.Items.Add (dir ,CheckState.Checked);
}
- Separating file from directories in a collection:
For each of the files, the application checks if it is a file or a directory by the FileAttributes
property. In the following code, the application casts the string named dir
and checks if it is file or directory by its fileattributes.Directory
flag:
if (File.GetAttributes(dir) == FileAttributes.Directory) bAns = true;
- Implementing Drag & Drop scenario:
First of all, in the Form Designer mode, the listbox.allowDrag
and the form.allowDrag
must be set to true
. The next step is to change the DragAndDrop effect (and the icon of the cursor) and allow the drop scenario to continue. Otherwise the DragDrop
event will never be reached.
private void mycheckedListBox_DragEnter(object sender,
System.Windows.Forms.DragEventArgs e)
{
if (e.Data.GetDataPresent(DataFormats.FileDrop, false)==true)
e.Effect = DragDropEffects.All;
}
Finally, I have implemented the DragDrop
event to get all the files to a string
ArrayList
:
private void mycheckedListBox_DragDrop(object sender,
System.Windows.Forms.DragEventArgs e)
{
string[] files = (string[])e.Data.GetData(DataFormats.FileDrop);
foreach (string dirfile in files) { ....}
}
- Showing the application in the traybar:
C# has wrapped all the procedures to a very simple one. All you need to do is add notifyIcon
to your application's form and to relate it to contextMenu
. The next step is to implement the Form.resize
and make sure that when minimized the window will disappear:
private void Form1_Resize(object sender, System.EventArgs e)
{
if (WindowState == FormWindowState.Minimized)
this.Hide();
}
You will probably want to implement the notifyIcon.DoubleClick
also.
private void notifyIcon1_DoubleClick(object sender, System.EventArgs e)
{
this.Show();
this.WindowState = FormWindowState.Normal;
}