How can I change the desktop wallpaper using C# Code?
5 Answers
Here's a class yanked from an app I wrote a year or two ago:
public sealed class Wallpaper
{
Wallpaper() { }
const int SPI_SETDESKWALLPAPER = 20;
const int SPIF_UPDATEINIFILE = 0x01;
const int SPIF_SENDWININICHANGE = 0x02;
[DllImport("user32.dll", CharSet = CharSet.Auto)]
static extern int SystemParametersInfo(int uAction, int uParam, string lpvParam, int fuWinIni);
public enum Style : int
{
Tiled,
Centered,
Stretched
}
public static void Set(Uri uri, Style style)
{
System.IO.Stream s = new System.Net.WebClient().OpenRead(uri.ToString());
System.Drawing.Image img = System.Drawing.Image.FromStream(s);
string tempPath = Path.Combine(Path.GetTempPath(), "wallpaper.bmp");
img.Save(tempPath, System.Drawing.Imaging.ImageFormat.Bmp);
RegistryKey key = Registry.CurrentUser.OpenSubKey(@"Control Panel\Desktop", true);
if (style == Style.Stretched)
{
key.SetValue(@"WallpaperStyle", 2.ToString());
key.SetValue(@"TileWallpaper", 0.ToString());
}
if (style == Style.Centered)
{
key.SetValue(@"WallpaperStyle", 1.ToString());
key.SetValue(@"TileWallpaper", 0.ToString());
}
if (style == Style.Tiled)
{
key.SetValue(@"WallpaperStyle", 1.ToString());
key.SetValue(@"TileWallpaper", 1.ToString());
}
SystemParametersInfo(SPI_SETDESKWALLPAPER,
0,
tempPath,
SPIF_UPDATEINIFILE | SPIF_SENDWININICHANGE);
}
}
I haven't tested it extensively, so use at your own risk.
-
This will only set BMP files. If I want to set a JPEG what is the method? – Sauron Jun 30 '09 at 04:19
-
1Not sure if windows support jpeg as wallpaper... it convert other images into bmp before setting up as wallpaper (correct me if im wrong) if that is the case you have to do the conversion in your code – Umair Ahmed Jun 30 '09 at 04:43
-
5I've been using this for jpegs just fine. Just because its called a bmp in the code above does not limit it. it will *probably* work for pngs and gifs as well as others, but I havent verified that. – Neil N Jun 30 '09 at 05:07
-
the above code takes a jpg (when passed to the set function) and saves it as a temp bmp, then sets that. When set again.. its just overwrites that temp bmp with the new one. – Neil N Jun 30 '09 at 05:09
-
1@NeilN This's Great, but what about if want to add a checkbox "Blank wallpaper" to set the wallpaper to black! – Murhaf Sousli Apr 11 '12 at 06:20
-
4FYI: This code does not work with PNGs. I had to convert to BMP manually first. – Program.X Aug 08 '13 at 12:24
-
@UmairAhmed , Half true half false, windows supports all major image formats, ie that is what filetypes are for. however it mostly utilizes bmp (32bit propriatary bmp/bmpx with alpha layer support) for majority of UI images... but the login screen for example is a standard jpg image called "backgrounddefault.jpg" with a size limit of 256kb even the system splices remain jpg and windows does not use bmp(x) in the process. (Windows 7 onwards) IE if you want alpha layer for some reason check out 32bit BMP documentation etc. – LokizFenrir Oct 23 '14 at 08:47
-
You could do this using a batch file command and executing the batch command using Process See this SO question: http://stackoverflow.com/questions/7779491/changing-wallpaper-with-a-batch-file-on-program-close-possible – Quintonn Mar 05 '15 at 15:57
-
1Wow! It's totally works and it supports JPG... Really good job. Congrats. – Umut D. Apr 17 '15 at 21:04
-
Sorry, I'm a bit of a noob in this, but I didn't manage to find any info online. Can someone explain what is SystemParametersInfo for? – alexpro_23 Nov 24 '21 at 18:01
Bases on this useful answer, I've also made my own app to set wallpaper matching screen resolution.
But the registry settings were wrong. Here are the correct values (tested on Win 7, Win 8.1, Win 10).
if (style == Style.Fill)
{
key.SetValue(@"WallpaperStyle", 10.ToString());
key.SetValue(@"TileWallpaper", 0.ToString());
}
if (style == Style.Fit)
{
key.SetValue(@"WallpaperStyle", 6.ToString());
key.SetValue(@"TileWallpaper", 0.ToString());
}
if (style == Style.Span) // Windows 8 or newer only!
{
key.SetValue(@"WallpaperStyle", 22.ToString());
key.SetValue(@"TileWallpaper", 0.ToString());
}
if (style == Style.Stretch)
{
key.SetValue(@"WallpaperStyle", 2.ToString());
key.SetValue(@"TileWallpaper", 0.ToString());
}
if (style == Style.Tile)
{
key.SetValue(@"WallpaperStyle", 0.ToString());
key.SetValue(@"TileWallpaper", 1.ToString());
}
if (style == Style.Center)
{
key.SetValue(@"WallpaperStyle", 0.ToString());
key.SetValue(@"TileWallpaper", 0.ToString());
}

- 1
- 1

- 407
- 3
- 9
-
5
-
1Of course you can.It is a matter of concept - I wrote it this way because someone else did. – badsamaritan Mar 19 '17 at 22:04
If you want to temporarily set a desktop wallpaper without polluting the Windows settings history, here is a gist I made.
It backups the wallpaper history (stored in the registry) before setting the temporary wallpaper and you can restore it back afterwards.
https://gist.github.com/Drarig29/4aa001074826f7da69b5bb73a83ccd39

- 1,902
- 1
- 19
- 42
If you're using UWP in c# , here's the code I found here
using Windows.System.UserProfile;
// Pass in a relative path to a file inside the local appdata folder
async Task<bool> SetWallpaperAsync(string localAppDataFileName)
{
bool success = false;
if (UserProfilePersonalizationSettings.IsSupported())
{
var uri = new Uri("ms-appx:///Local/" + localAppDataFileName);
StorageFile file = await StorageFile.GetFileFromApplicationUriAsync(uri);
UserProfilePersonalizationSettings profileSettings = UserProfilePersonalizationSettings.Current;
success = await profileSettings.TrySetWallpaperImageAsync(file);
}
}
Actually I think it can be more simple file.png is your photo ,it can be .jpg or something else
StorageFile file = await ApplicationData.Current.LocalFolder.CreateFileAsync("file.png", CreationCollisionOption.ReplaceExisting);
bool success = false;
UserProfilePersonalizationSettings profileSettings = UserProfilePersonalizationSettings.Current;
success = await profileSettings.TrySetWallpaperImageAsync(file);

- 31
- 3
Tweaking Neal N's answer for Gifs:
private const int SPI_SETDESKWALLPAPER = 20;
private const int SPIF_UPDATEINIFILE = 0x01;
private const int SPIF_SENDWININICHANGE = 0x02;
[DllImport("user32.dll", CharSet = CharSet.Auto)]
private static extern int SystemParametersInfo(int uAction, int uParam, string lpvParam, int fuWinIni);
public enum Style : int
{
Tiled,
Centered,
Stretched
}
/// <summary>
/// Loops numFrames times, animating the desktop background as the given gif.
/// Remember this will sorta bog down your computer, and probably isn't best to be running 24/7.
/// If numFrames is negative this will loop forever
/// </summary>
/// <param name="gifPath">The gif to be animated</param>
/// <param name="transparencyReplace">If the gif has transparency, it will be "replaced" with this color.</param>
/// <param name="framesPerSecond">How many frames to play per second. This is a max: most likely it will be a little slower than this especially at first.</param>
/// <param name="style">Whether to tile, center, or stretch each gif frame as it's played.</param>
/// <param name="numFrames">The number of frames to play. If negative, this method will loop forever.</param>
public static void SetDesktopBackgroundAsGifAsync(string gifPath, System.Drawing.Color transparencyReplace, int framesPerSecond, Style style, int numFrames)
{
Thread workerThread = new Thread(() => SetDesktopBackgroundAsGif(gifPath, transparencyReplace, framesPerSecond, style, numFrames));
workerThread.Start();
}
/// <summary>
/// Loops numFrames times, animating the desktop background as the given gif.
/// Remember this will sorta bog down your computer, and probably isn't best to be running 24/7.
/// If num frames is negative this will loop forever.
//// <summary>
/// <param name="gifPath">The gif to be animated</param>
/// <param name="backgroundImage">Image to render the gif on top of (because of transparency)</param>
/// <param name="framesPerSecond">How many frames to play per second. This is a max: most likely it will be a little slower than this.</param>
/// <param name="style">Whether to tile, center, or stretch each gif frame as it's played.</param>
/// <param name="numFrames">The number of frames to play. If negative, this method will loop forever.</param>
public static void SetDesktopBackgroundAsGifAsync(string gifPath, System.Drawing.Image backgroundImage, int framesPerSecond, Style style, int numFrames)
{
Thread workerThread = new Thread(() => SetDesktopBackgroundAsGif(gifPath, backgroundImage, framesPerSecond, style, numFrames));
workerThread.Start();
}
/// <summary>
/// Loops numFrames times, animating the desktop background as the given gif.
/// Remember this will sorta bog down your computer, and probably isn't best to be running 24/7.
/// if numFrames is negative this will loop forever
/// </summary>
/// <param name="gifPath">The gif to be animated</param>
/// <param name="transparencyReplace">If the gif has transparency, it will be "replaced" with this color.</param>
/// <param name="framesPerSecond">How many frames to play per second. This is a max: most likely it will be a little slower than this.</param>
/// <param name="style">Whether to tile, center, or stretch each gif frame as it's played.</param>
/// <param name="numFrames">The number of frames to play. If negative, this method will loop forever.</param>
public static void SetDesktopBackgroundAsGif(string gifPath, System.Drawing.Color transparencyReplace, int framesPerSecond, Style style, int numFrames)
{
if (!File.Exists(gifPath))
throw new Exception("Given gif: '" + gifPath + "' not found");
FileStream gifFile = new FileStream(gifPath, FileMode.Open);
GifBitmapDecoder gifDecoder = new GifBitmapDecoder(gifFile, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.OnLoad);
if (gifDecoder.Frames.Count == 0)
throw new Exception("No frames in given gif");
Bitmap backgroundImage = new Bitmap(gifDecoder.Frames[0].PixelWidth, gifDecoder.Frames[0].PixelHeight, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
using(Graphics g = Graphics.FromImage(backgroundImage))
{
g.FillRectangle(new System.Drawing.SolidBrush(transparencyReplace), 0, 0, gifDecoder.Frames[0].PixelWidth, gifDecoder.Frames[0].PixelHeight);
}
gifFile.Close();
SetDesktopBackgroundAsGif(gifPath, backgroundImage, framesPerSecond, style, numFrames);
}
/// <summary>
/// Loops infinitely, animating the desktop background as the given gif.
/// Remember this will sorta bog down your computer, and probably isn't best to be running 24/7.
/// </summary>
/// <param name="gifPath">The gif to be animated</param>
/// <param name="backgroundImage">Image to render the gif on top of (because of transparency)</param>
/// <param name="framesPerSecond">How many frames to play per second. This is a max: most likely it will be a little slower than this.</param>
/// <param name="style">Whether to tile, center, or stretch each gif frame as it's played.</param>
/// <param name="numFrames">The number of frames to play. If negative, this method will loop forever.</param>
private static void SetDesktopBackgroundAsGif(string gifPath, System.Drawing.Image backgroundImage, int framesPerSecond, Style style, int numFrames)
{
if (!File.Exists(gifPath))
throw new Exception("Given gif: '" + gifPath + "' not found");
FileStream gifFile = new FileStream(gifPath, FileMode.Open);
GifBitmapDecoder gifDecoder = new GifBitmapDecoder(gifFile, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.OnLoad);
if (gifDecoder.Frames.Count == 0)
throw new Exception("No frames in given gif");
Console.WriteLine("Saving frames to temporary files:");
int numFramesSoFar = 0;
for (int i = 0; i < gifDecoder.Frames.Count; i++)
{
BitmapFrame gifFrame = gifDecoder.Frames[i];
PngBitmapEncoder pngEncoder = new PngBitmapEncoder();
pngEncoder.Frames.Add(gifFrame);
MemoryStream pngStream = new MemoryStream();
pngEncoder.Save(pngStream);
Image frameImage = Image.FromStream(pngStream);
Bitmap bmp = new Bitmap(frameImage.Width, frameImage.Height, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
using (Graphics g = Graphics.FromImage(bmp))
{
g.DrawImage(backgroundImage, 0, 0);
g.DrawImageUnscaled(frameImage, 0, 0);
}
string tempPath = Path.Combine(Path.GetTempPath(), gifPath + i + ".bmp");
bmp.Save(tempPath, System.Drawing.Imaging.ImageFormat.Bmp);
Console.WriteLine("Saved frame " + i);
numFramesSoFar++;
if (numFrames >= 0 && numFramesSoFar >= numFrames) break;
}
Console.WriteLine("Setting frames to desktop background at about " + framesPerSecond + " FPS");
// 1.0/... to convert to seconds per frame (instead of frames per second)
// * 1000 to convert to milliseconds per frame
// * 1000 to convert to microseconds per frame
// * 10 to convert to 0.1s of microseconds per frame = 100s of nanoseconds per frame
long ticksBetweenFrames = (long)Math.Round(1.0 / framesPerSecond) * 1000*1000*10;
Stopwatch timer = new Stopwatch();
timer.Start();
numFramesSoFar = 0;
while(numFrames < 0 || numFramesSoFar < numFrames)
{
for (int i = 0; i < gifDecoder.Frames.Count; i++)
{
// Sleep until we're at the desired frame rate, if needed.
if(ticksBetweenFrames > timer.ElapsedTicks)
Thread.Sleep(new TimeSpan(Math.Max(0, ticksBetweenFrames - timer.ElapsedTicks)));
timer.Restart();
// From http://stackoverflow.com/a/1061682/2924421
string filePath = Path.Combine(Path.GetTempPath(), "wallpaper" + i + ".bmp");
RegistryKey key = Registry.CurrentUser.OpenSubKey(@"Control Panel\Desktop", true);
if (style == Style.Stretched)
{
key.SetValue(@"WallpaperStyle", 2.ToString());
key.SetValue(@"TileWallpaper", 0.ToString());
}
if (style == Style.Centered)
{
key.SetValue(@"WallpaperStyle", 1.ToString());
key.SetValue(@"TileWallpaper", 0.ToString());
}
if (style == Style.Tiled)
{
key.SetValue(@"WallpaperStyle", 1.ToString());
key.SetValue(@"TileWallpaper", 1.ToString());
}
SystemParametersInfo(SPI_SETDESKWALLPAPER,
0,
filePath,
SPIF_UPDATEINIFILE | SPIF_SENDWININICHANGE);
numFramesSoFar++;
if (numFrames >= 0 && numFramesSoFar >= numFrames) break;
}
}
gifFile.Close();
}
Also note that you need to use:
using Microsoft.Win32;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Media;
using System.Windows.Media.Imaging;
Finally, right click on your Project, Add Reference, and (in Assemblies and Framework) add Presentation Core, System.Xaml, and WindowsBase.
Then right click on your Project and go into Properties, and make sure Target Framework is .Net Framework 4.5. If you change this you may need to restart Visual Studio.

- 4,217
- 3
- 22
- 34
-
3Of course it bogs down the machine. There's a blocking infinite loop with a call to `Thread.Sleep` thrown haphazardly in. There are much better ways to wait for time to pass. – Cody Gray - on strike May 18 '14 at 00:40
-
No, I think it has more to do with the call to SystemParametersInfo (say, 10 times a second). The desktop isn't meant to be refreshed like that. This is evidinced by "explorer" going from 0% to 6-12% cpu usage, simply by running a program that calls this method. I tweaked my answer though, adding async methods and making the call to the Thread.Sleep less spammy (only happens when needed). Any other glaring concerns? – Phylliida May 18 '14 at 01:50
-
I considered tweaking it to stop the threads by another method, but that seems like it's going overboard for a method that probably isn't that good practice in the first place. – Phylliida May 18 '14 at 01:55
-
On second thought, I added a numFrames parameter which specifies the number of frames you want to animate before this method halts. If negative, it will go forever. – Phylliida May 18 '14 at 02:06
-