Wallpaper Cycler

Sign in to queue


  This sample demonstrate simple wallpaper cycler. It expects a folder in which it will find images. Upon startup, it will change the wallpaper, and it will even modify the placement behavior based on the size of the image found.
Arian Kulp's Blog

Difficulty: Easy
Time Required: 1-3 hours
Cost: Free
Software: Visual Basic or Visual C# Express Editions

A number of articles ago, a simple wallpaper utility was written. I thought it would be nice to put together some of the concepts that we've looked at recently and create a new, enhanced wallpaper changer. Specifically, this application is no longer based on a specific file. Instead, it expects a folder in which it will find images. Upon startup, it will change the wallpaper, and it will even modify the placement behavior based on the size of the image found.

You can read the article now, but for added benefit download a copy of Visual Studio 2005 Express Edition for C# or Visual Basic. These are free if downloaded during most of 2006, and provide all of the tools necessary to create great applications. After you install Visual Studio Express, download the code for this article from the links at the top. Choose from C# or Visual Basic, according to your personal preference—the applications are functionally identical.

As with most recent In the Box columns, this application will start with no visible interface beyond its notification icon in the system tray. The available options will be to display the settings, change the wallpaper on-demand, or exit. The "Show Settings" option is in bold. This is a visual cue that if you double-click the icon, this is the action that will take place. There is no built-in support for this feature. Simply set the menu item's Font.Bold property to "True" and create a MouseDoubleClick event handler for the NotifyIcon control.

Generic Episode Image

Figure 1: The notification icon menu

Scanning folders

The heart of the application is its ability to scan a folder randomly to find an image to display as the desktop background. This is surprisingly easy using the System.IO.Directory class. Its static/shared GetFiles method returns a collection of all files in a given folder. You can optionally pass a wildcard pattern, and a recursive qualifier. It would have made sense to specify a wildcard pattern including extensions like .JPG and .GIF, but apparently only a single expression can be used. The third parameter takes an argument of type System.IO.SearchOption. This is where you can specify a top-level file listing (TopDirectoryOnly), or a recursive (AllDirectories) one.

Visual Basic

' Specify top-level or sub-folders
Dim opt As System.IO.SearchOption = _

If subfoldersCheckbox.Checked Then
    opt = System.IO.SearchOption.AllDirectories

End If

' Grab complete list of files
Dim files As String() = System.IO.Directory.GetFiles( _
    picturesPathTextBox.Text, "*", opt)

Visual C#

// Specify top-level or sub-folders
System.IO.SearchOption opt = System.IO.SearchOption.TopDirectoryOnly;
if( FsubfoldersCheckbox.Checked ) opt = 

// Grab complete list of files
string[] files = System.IO.Directory.GetFiles(
picturesPathTextBox.Text, "*", opt);

At this point, the files object contains an array of strings. Each entry is a fully-qualified filename from within the supplied folder. It would be nice to just randomly select an entry from this collection, but recall that we were not able to filter based on file extension. This must be done now. Two other exclusions also apply. First, we don't want to select the file that was used last time (we save one time back). Second, we don't want to select the temporary image that we generate (discussed later). The following code demonstrates copying the array into a generic List collection, element by element, provided that each element meets our exacting criteria.

Visual Basic

' Filter list to remove non-images, last image shown,
' and the app-generated BMP file from a previous run.
Dim filteredFiles As New List(Of String)()

For Each file As String In files

    Dim ext As String = file.Substring(file.LastIndexOf("."))

    If ".jpg .bmp .gif".IndexOf(ext) > -1 AndAlso _
        file.EndsWith("coding4fun-desktop.bmp") = False AndAlso _
        Not file = My.Settings.LastImageShown Then

    End If

Visual C#

// Filter list to remove non-images, last image shown,
// and the app-generated BMP file from a previous run.

List<String> filteredFiles = new List<string>();
foreach (string file in files)
    string ext = file.Substring(file.LastIndexOf("."));

    if (".jpg .bmp .gif".IndexOf(ext) > -1 &&

        !file.EndsWith("coding4fun-desktop.bmp") &&
        file != settings.LastImageShown)

After all of this processing, it is possible that no files remain in our collection. Perhaps the folder was empty initially, none of the files were images, or the only image found was used last time. Either nothing will be returned, or a random index will be generated to grab one element out of the collection. Recall that these elements are full pathnames. We will save that pathname as the LastImageShown setting, create a Bitmap object given the pathname, then return that object.

Visual Basic

' Make sure there are any files left
If filteredFiles.Count = 0 Then Return Nothing

' Randomly grab a file
Dim filename As String = filteredFiles(rnd.Next(filteredFiles.Count))

' Remember last image shown
My.Settings.LastImageShown = filename

' Return the bitmap object from this filename
Return New Bitmap(filename)

Visual C#

// Make sure there are any files left
if (filteredFiles.Count == 0) 
    return null;

// Randomly grab a file
string filename = filteredFiles[rnd.Next(filteredFiles.Count)];

// Remember last image shown
settings.LastImageShown = filename;

// Return the bitmap object from this filename
return new Bitmap(filename);

Finally the image is saved as a BMP file in the My Pictures folder, and passed to the appropriate system API function, SystemParametersInfo, to effect the change. Most of this is the same as in the original In the Box column referenced above, but the original required an image to be in BMP format to begin with. As it turns out, once you have loaded an image into a Bitmap object, saving as a BMP file format is a single line of code:

Visual Basic

' Convert to BMP and save

img.Save(picturesPath, System.Drawing.Imaging.ImageFormat.Bmp)

Visual C#

// Convert to BMP and save)
img.Save(picturesPath, System.Drawing.Imaging.ImageFormat.Bmp);

Study the SetDesktopBackground static/shared method in WindowsAPI.vb/.cs to see the implementation details.


Because the image to display can vary wildly each time, the settings dialog includes a number of behavioral settings. The first checkbox allows you to specify if sub-folders should be scanned or not. If you are pointing at a collection of home photos divided into sub-folders for albums, this could be useful.

The three ComboBox controls allow some flexibility in how images are displayed depending on their size relative to the desktop size. By default, images larger than the desktop will be stretched to fit. Now the term "stretched" is taken from the Windows Display control panel. It's a bit of a misnomer, since what it really means is "stretched or shrunk" in either direction to exactly fill the screen. It's really ugly if you have a widescreen display and conventional (4:3) images.

Images smaller than the screen will be centered. The final category, Tiled, is a bit more flexible. If you have very small images, you may want to tile them for a repeating pattern. Just specify how small is small (128 pixels in both directions, by default), specify the action (it doesn't need to be Tiled), and watch it go. I personally like the defaults, but it made some sense to allow them to be preferences so anyone can change them easily.

Generic Episode Image

Figure 2: Settings dialog

All of the settings directly correspond to project settings defined in Visual Studio. This nifty feature lets you define settings at the user or application level, set a datatype, and even a default value. Then, to complete the coolness, you can actually databind these settings to the controls. All you need to do is load and save when necessary. The mechanics of copying data between controls and settings are taken care of for you!

Generic Episode Image

Figure 3: Databinding settings

Working with the Registry

The application must write to the registry in order to set the stretched/tiled/centered attributes. This is very easy using the Registry object. Just use a static property, such as CurrentUser to access the HKEY_CURRENT_USER key. You can dig deeper by using a method like OpenSubKey to open nested keys and access their values. The wallpaper cycler application also uses the registry to add itself to Windows startup. The auto-start CheckBox control calls some shared/static methods in the WindowsAPI class to add and remove itself:

Visual Basic

' Based on checkbox, call API functions to add or remove
' application path from registry Run section for current user.

If autostartCheckbox.Checked Then
    WindowsAPI.AddStartupItem("BackgroundCycler", _ 

End If

Visual C#

// Based on checkbox, call API functions to add or remove
// application path from registry Run section for current user.
            if (autostartCheckbox.Checked)


Notice the call to System.Reflection.Assembly class. The GetEntryAssembly method returns a reference to the assembly that contained the startup code for the current application. The Location property returns the assembly filename, in this case the path to the executable file. In the AddStartupItem method, the sub-key for the current user's Run entries is opened, and a new value is added. So simple, but so powerful:

Visual Basic

Dim key As RegistryKey = _
    Registry.CurrentUser.OpenSubKey( _
    "Software\Microsoft\Windows\CurrentVersion\Run", True)
key.SetValue(name, path)

Visual C#

RegistryKey key = Registry.CurrentUser.OpenSubKey(
                @"Software\Microsoft\Windows\CurrentVersion\Run", true);

            key.SetValue(name, path);

Potential Enhancements

The application is ready to use, and fun too! You can change wallpaper frequently, even if your images are not already in BMP format, and you don't need to go into Desktop properties to do it. It might also be fun to add an option to automatically change images on a timed interval. Another challenge would be to provide the ability to download images at random from URLs. You could provide a URL to an image gallery, scan the HTML for image links, then randomly select one to download, convert, and show as wallpaper. Lots of options!


I hope this got you thinking about things to do with the Bitmap object, the Registry object, and desktop interaction. Be sure to visit https://msdn.microsoft.com/vstudio/express/ to download your preferred version of Visual Studio 2005 Express Edition. Then, take a look at the source code for this project, learn, and do even more. Good luck, and best of all, have fun!


image, wall paper

The Discussion

  • User profile image
    Hi Sam! Photos i send on e-mail.  Green,Green

    Hi Sam! Photos i send on e-mail.

    Green,Hi Sam! Photos i send on e-mail.


  • User profile image
    Matt McCormick

    I am having trouble with this, I can't seem to get the wallpaper to stay. I can set a wallpaper, and sometimes it will stay the wallapaper until I log out, and sometimes it wont stay at all. By stay, I mean the wallpaper I set appears, then later its just a blue background (or whatever the default background color is). Any help is appreciated... mbmccormick@gmail.com.

  • User profile image

    SystemParametersInfo does not work in Windows Vista

  • User profile image
    tristan corner

    this is very useful infomation because a made a good progran from it.

    [system error]

  • User profile image
    kirupaBlog - If it isn’t broken, take it apart and fix it! » Blog Archive » Interesting Links #3: Write Better Code, AK-47, Webcams…
  • User profile image
    MSDN Blog Postings » MultiWall - Wallpaper Tool for Multiple Monitors
  • User profile image
    Noticias externas

    Are you more productive with more monitors? Would you be even more productive with better wallpaper management

  • User profile image

    Are you more productive with more monitors? Would you be even more productive with better wallpaper management?

  • User profile image

    Cool! I had the same idea, and I'd like to make it in Python!

    My problem is how to say to Windows XP which image to load... (API). Some suggestion?


  • User profile image

    I had some issues with errors on vista and vb 2008. I made the following change and it worked:

           Dim filteredFiles As New List(Of String)()

           For Each file As String In files

               If file.LastIndexOf(".") > 0 Then

                   Dim ext As String = file.Substring(file.LastIndexOf("."))

                   If ".jpg .bmp .gif".IndexOf(ext) > -1 AndAlso _

                      file.EndsWith("coding4fun-desktop.bmp") = False AndAlso _

                     Not file = My.Settings.LastImageShown Then


                   End If

               End If


Add Your 2 Cents