Setting Wallpaper

Published 31 October 06 09:51 AM | Coding4Fun 
  This sample application allows you select an image and set it as wallpaper.
3 Leaf Development

Difficulty: Easy
Time Required: 1-3 hours
Cost: Free
Software: Visual Studio Express Editions
Hardware:
Download: Download

     

    Interacting visually with the Windows Desktop from code is fun, so I decided to see what it would take to change the appearance.  This sample application allows you select an image and set it as wallpaper:

    It turns out that wallpaper is not directly accessible from managed code, but working with Win32 API’s is no problem in this case.  Developing this application allowed me to work with methods imported from system DLL’s, the registry, the file open dialog, a custom enumerated type, and use datasource binding to that enumerated type.

    The application allows you to browse to an image, view a preview (resized smaller to fit if necessary), select the display style (Tiled, Stretched, or Centered), and set the image as the Desktop background.  This enabled me to work some of the new features in Visual Studio 2005 as well.  The code samples shown in this article use Visual C# 2005 Express Edition, however any of the Visual Studio Express Editions can be used to create a similar sample.  Visual Basic source code is also included with the code download for this article. Beta 2 of the Express editions can be downloaded from http://msdn.microsoft.com/express.

    As seen above, the form consists of a button to browse to an image, a button to set the background to that image, a drop-down list of sizing options, and the currently selected image.  Not visible are a SplitContainer control (separating the buttons and ComboBox control from the image) and a file open dialog.  As seen in the ResearchHelp sample, the SplitContainer control is easy to use and allows the user more control over the layout of the user interface.  In the upper panel, the interactive controls have been placed, while the lower space is filled with a docked PictureBox control.

    Desktop wallpaper can use one of three different sizing styles for display.  The Tiled option displays the image at full-size, repeating the image as needed, horizontally and vertically, to fill the screen.  The Stretched option displays the image at whatever size necessary to fill the screen either horizontally or vertically.  Finally, the Centered option places the image at the center of the screen, exactly once, whether if fills the screen or not, even allowing it to go beyond the edges of the screen if it is too large.  In order to support these three styles in an object-oriented way, an enumerated type was created.  This allows us to use the various style options as strongly-typed objects.  This is preferable to string or numeric representations that may not contain valid values and can cause trouble when passed to a method.

    Visual C#

    public enum Style: int
    {
        Tiled, Centered, Stretched
    }
    

    Visual Basic

    Public Enum Style As Integer
        Tiled
        Centered
        Stretched
    End Enum

    The code that actually sets the image as wallpaper accepts the path to the image and a Style reference.  Two registry values are set in the Control Panel\Desktop key.  Based on which sizing style is requested, numeric codes are set for the WallpaperStyle and TileWallpaper values.  Using an enumerated type for the style means the value is guaranteed to match one of the three defined options -- no default case is needed.

    Visual C#

    RegistryKey key = Registry.CurrentUser.OpenSubKey("Control Panel\\Desktop", true);
    switch( style )
    {
        case Style.Stretched :
            key.SetValue(@"WallpaperStyle", "2") ; 
            key.SetValue(@"TileWallpaper", "0") ;
            break;
        case Style.Centered :
            key.SetValue(@"WallpaperStyle", "1") ; 
            key.SetValue(@"TileWallpaper", "0") ; 
            break;
        case Style.Tiled :
            key.SetValue(@"WallpaperStyle", "1") ; 
            key.SetValue(@"TileWallpaper", "1") ;
            break;
    }

    Visual Basic

    Dim key As RegistryKey = My.Computer.Registry.CurrentUser.OpenSubKey("Control Panel\Desktop", True)
    Select Case selectedStyle
        Case Style.Stretched
            key.SetValue("WallpaperStyle", "2")
            key.SetValue("TileWallpaper", "0")
        Case Style.Centered
            key.SetValue("WallpaperStyle", "1")
            key.SetValue("TileWallpaper", "0")
        Case Style.Tiled
            key.SetValue("WallpaperStyle", "1")
            key.SetValue("TileWallpaper", "1")
    End Select

    At this point, the sizing options have been set, but the actual image path still needs to be set.  The SystemParametersInfo function exists in the user32.dll to allow you to set or retrieve hardware and configuration information from your system.  The function accepts four arguments.  The first indicates the operation to take place, the second two parameters represent data to be set, dependant on requested operation, and the final parameter allows you to specify how changes are saved and/or broadcasted.  The DllImport attribute allows you to specify a DLL, the function to call, and any required arguments.

    Visual C#

    [DllImport("user32.dll", CharSet = CharSet.Auto)]
    static extern int SystemParametersInfo(
        int uAction, int uParam, string lpvParam, int fuWinIni);
    

    Visual Basic

    <DllImport("user32")> _
    Public Shared Function SystemParametersInfo(ByVal uAction As Integer, _
         ByVal uParam As Integer, ByVal lpvParam As String, ByVal fuWinIni _   
         As Integer) As Integer
    End Function

    In addition to importing the function, you will need to define some constants for use with it.  The first constant represents the wallpaper operation to take place in this sample, to be used in the first argument.  The other two constants will be combined together for the final argument.

    Visual C#

    const int SPI_SETDESKWALLPAPER = 20;
    const int SPIF_UPDATEINIFILE = 0x01;
    const int SPIF_SENDWININICHANGE = 0x02;
    Visual Basic
    Const SPI_SETDESKWALLPAPER As Integer = 20
    Const SPIF_UPDATEINIFILE As Integer = &H1&
    Const SPIF_SENDWININICHANGE As Integer = &H2&

    Once the function is imported, you can call it like any other.  The operation to be invoked is SPI_SETDESKWALLPAPER.  In our sample, the second argument is not needed so set to zero.  The third argument is a reference to the image path.  Note that the image must be in bitmap format.  The final argument specifies that the changes should persist, and also be immediately visible.

    Visual C#

    SystemParametersInfo(SPI_SETDESKWALLPAPER, 0, path, SPIF_UPDATEINIFILE | SPIF_SENDWININICHANGE);

    Visual Basic

    SystemParametersInfo(SPI_SETDESKWALLPAPER, 0, path, SPIF_UPDATEINIFILE Or SPIF_SENDWININICHANGE)

    At this point, everything is in place to update the desktop wallpaper.  The user interface provides a Browse button that defaults to the Windows system directory with a *.bmp filter.  About a dozen bitmaps are available here.  The drop-down list is databound to the Style enumerated type by calling the Enum.GetNames() method in the System namespace.  This returns a string array perfect for lists and iteration.

    Visual C#

    styleComboBox.DataSource = System.Enum.GetNames(typeof(Wallpaper.Style));

    Visual Basic

    styleComboBox.DataSource = System.Enum.GetNames(GetType(Wallpaper.Style))

    When the user clicks the Set button, the selected ComboBox text must be casted back to the enumerated item object.  Note that this method would throw an exception if an invalid string was passed to it, but this isn’t a risk with a ComboBox.  The conversion occurs as follows:

    Visual C#

    (Wallpaper.Style)Enum.Parse(typeof(Wallpaper.Style), styleComboBox.Text)

    Visual Basic

    CType(System.Enum.Parse(GetType(Wallpaper.Style), styleComboBox.Text),            
          Wallpaper.Style)

    Conclusion

    The Win32 API makes it relatively easy to take advantage of features that aren’t available in the .NET Framework.  A nice addition would be to use the Save() method of the Bitmap class to automatically convert images to Bitmap format so a user could select JPEG or GIF images from the local hard drive.  Download Visual C# 2005 Express Edition or Visual Basic 2005 Express Edition and give this application a try.  Get started at http://msdn.microsoft.com/express.  

    Comment Notification

    If you would like to receive an email when updates are made to this post, please register here

    Subscribe to this post's comments using RSS

    Comments

    # Kris said on October 31, 2006 11:46 PM:

    Hi,

     Very interesting. I would like to write some text at the bottom right hand corner of the desktop - mostly reminders for the day for me. How do I accomplish this? There should be an Win32 API because one of the SysInternals tools does this. Can you provide any info.

    Thanks.

    # espinete said on February 8, 2007 4:46 AM:

    Hello mister, great article, it's good for me.

    A question, I would like setting screesaver in windows xp, is it possible using SystemParametersInfo ? any help, please ?

    Thanks, greetings, regards

    # Business Inquirer said on April 16, 2007 10:19 AM:

    Please not that my XP Pro SvPack 2 has the following TileWallpaper and WallpaperStyle entries, respectively.

    Centered=0,0

    Tiled=1,0

    Stretched=0,2

    # dshome said on April 24, 2007 4:23 PM:

    Vor all Windows, except Windows Vista ist the code usable. On Vista change nothing.

    # FX89 said on June 25, 2007 1:45 PM:

    Hi there, i've just been trying to write a small program that would change the desktop walpaper and i got stuck at the following:

       char wpString[200]; strcpy(szBuf, "c:\\pictures\\00.bmp");

       SystemParametersInfo(SPI_SETDESKWALLPAPER, 0, (void*)wpString, SPIF_SENDWININICHANGE);  

    The code doesn't work propperly since all it does is removing the desktop wallpaper, regardless of the value of wpString.

    If anyone can tell me what's wrong with it, i would very much apreciate it.

    Thanks and good luck

    # Lalit Patel said on July 8, 2007 10:23 AM:

    May I download Full Caode of this type of fun codding if i want anytime in your website?

    # joseph broxton said on August 18, 2007 1:36 PM:

    thank you

    have been searching help files

    for info on setting wallpaper

    just what i needed

    # Carl said on August 22, 2007 8:15 PM:

    What would be a good way to have a list of wallpapers then have them set to change at intervals? Say 1 per hour or per reboot.

    # DongMT said on September 15, 2007 1:04 AM:

    thank you, that is fantastic with using Registry and user32.dll

    # Coding4Fun said on October 2, 2007 3:09 PM:

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

    # Noticias externas said on October 2, 2007 3:39 PM:

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

    # Yingqiang said on January 15, 2008 3:08 AM:

    this porgram does not work for my computer,

    my OS is WinXP.

    It is strange, for some picture it will be ok to work correcly, but for many others, it doesn't work.

    # Coding4Fun said on January 16, 2008 12:47 PM:

    @Yingqiang:  What are the file types that work and what won't work?  Do you see a pattern?

    # Lee said on March 15, 2008 7:59 PM:

    Bitmaps will only work, for me at least, and probably for Yingqiang also.

    You must convert other image filetypes to a bitmap...save the bitmap...then load into systemparamentersinfo.

    # Axel said on March 24, 2008 6:48 AM:

    This is documented: http://msdn2.microsoft.com/en-us/library/ms724947(VS.85).aspx

    In short, BMP works on all versions and JPEG only on Vista or 2008.

    # A said on April 8, 2008 4:12 AM:

    Is there a way to make this work from CMD using RunDll32?

    Ex:  RunDll32.exe user32.dll,SystemParametersInfo 20,0,C:\path\to\wallpaper.bmp,0x01

    or something similar?

    # Coding4Fun said on April 8, 2008 4:40 PM:

    You set the program up to be a command line application and do everything through args.

    # A said on April 9, 2008 3:08 AM:

    I'm actually asking more for the purpose of a batch file rather than an application.  I'm having trouble figuring out the exact syntax to use though.  Do you have any advice or resources I could check for how to properly use RunDll32 and user32.dll to change a Windows wallpaper?

    # Coding4Fun said on April 9, 2008 12:45 PM:

    http://windowsitpro.com/article/articleid/93152/how-can-a-batch-script-alter-the-users-screen-saver-and-wallpaper-settings-and-become-effective-without-a-logoff-and-logon.html

    # A said on April 10, 2008 2:58 AM:

    Woohoo!  That website had so much useful information on it!  Thanks!  Though, now my problem is that Windows XP only supports using BMP files as backgrounds when setting them to

    HKEY_CURRENT_USER\Control Panel\Desktop

    which is what the "RUNDLL32.EXE user32.dll, UpdatePerUserSystemParameters" command is used to refresh.  To use a JPG image, http://windowsitpro.com/article/articleid/74578/jsi-tip-3259-windows-2000-wallpaper-policy.html suggests that I use the Active Desktop feature to load a JPG as the background.  I'm currently trying this, but I haven't yet gotten it to change within Windows without requiring a reboot (admittedly, I'm a little fuzzy on Active Desktop, so I'm still working through some options I haven't tried yet).  Do you have any words of wisdom for me on this?

    Also, out of morbid curiosity, how does Windows go about converting non-BMP images to BMP when you normally set a wallpaper anyway?

    # DZ said on July 10, 2008 11:41 PM:

    "Also, out of morbid curiosity, how does Windows go about converting non-BMP images to BMP when you normally set a wallpaper anyway?"

    Simple. Somewhere inside your profile folder (usually C:\Documents and Settings\<your username>), there's a bitmap with the generic name "wallpaper.bmp" -- that's the actual image that's being set as the wallpaper. When Windows finds that an image isn't a wallpaper, it simply converts to BMP, rewrites the generic wallpaper file, and sets it to that, while saving the location of the original image elsewhere.

    # Ross said on September 27, 2008 3:20 AM:

    How do I do the same for Active Desktop .jpg files?

    Leave a Comment

    (required) 
    (optional)
    (required) 
    Page view tracker