# Setting Wallpaper

## Description

 This sample application allows you select an image and set it as wallpaper. Sean Campbell 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 https://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 https://msdn.microsoft.com/express.

## The Discussion

• 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.

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

• 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.

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

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

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

• 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?

• 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?

• 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?

• "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.

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

• Python on Vista:

import ctypes

SPI_SETDESKWALLPAPER = 0x14

SPIF_UPDATEINIFILE = 0X01

SPIF_SENDWININICHANGE = 0X02

def change_paper(picture):

try:

ctypes.windll.user32.SystemParametersInfoW(SPI_SETDESKWALLPAPER, 0, picture, SPIF_UPDATEINIFILE|SPIF_SENDWININICHANGE)

except:

print("Set Wallpaper failed!")

• unfortunately this doesn't always work in vista...

• I thought I'd get fancy and set my application to detect the OS version.  If it's XP, copy the jpg/gif/whatever (non-bmp) to a file with the same name .bmp in the temp folder.  Then, I'd set that to the background.  No good on XP, so there must be something more that's needed.  Has anyone been able to find a workaround for XP?  I know the OS can handle it, as you can open a JPG in a number of applications and select "Set as wallpaper" and it works.

• Answered my own question.  I am converting to a BMP as so:

Image oldImage = Image.FromFile(sourceFile, false);

oldImage.Save(tempfilename, System.Drawing.Imaging.ImageFormat.Bmp);

//sourceFile = the full path to and file name of the JPG, GIF, etc

//tempfilename = the full path to and file name of the BMP getting created

• wouldnt it work on vista if you just lib 64?

• @Duke, it should.  You can even make VS have a "Any CPU" setting so you don't target x86 or x64 CPUs

• Hi!!!

This is very good for set desktop wallpaper.

But I want some disadvantage this project i.e.

we can only *.bmp format file set not of

all image formate like these *.JPG, *.GIF  etc;

Please provide some hint(code) for others image format set wallpaper.

Thanks & Regards

Durgesh

India

• @durgesh, this is a pretty old article.  The quick solution is to just save the image as a bmp?

• Hello I am trying to use this code but I don't really understand it much. I've read through the entire article and when I pasted the code it didn't work. I'm using vbexpress 2008 and i'm not sure if i'm pasting the code properly. I'll continue messing around with it till it works but even with the select case statement its being weird. So right now i'm going to go back through the code and place some of it in separate functions just to see if that will clear anything up.

• @Joel, use the download link at the top of the page.  The articles are there to talk you through the concepts and show the harder code and the "heart of it" code.  With that being said, most articles alone won't produce a 100% functional program.

• This code and document works...it really help me out.

thanks a ton.

• public enum Style: int

{

Tiled, Centered, Stretched

}

Visual Basic

Public Enum Style As Integer

Tiled

Centered

Stretched

End Enum

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;

}

• There's actually a problem.. or rather: I've got a question... if I have an animated gif, I can set it as background and it's still animated - how does it work? Does it use ActiveDesktop? can't I use it just as well? I target my "Wallpaper Changer" to XP, Vista and 7, but I don't want to use any WPF.

And on another note: is there any way to use the wallpaper-changing-animation that comes with Windows 7 when it adjusts the paper? It slowly fades one into the other .. it'd be great if my program could do this just as well...