Change desktop wallpaper using code in .NET
C#.NetWpfDesktopWallpaperC# Problem Overview
How can I change the desktop wallpaper using C# Code?
C# Solutions
Solution 1 - C#
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.
Solution 2 - C#
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());
}
Solution 3 - C#
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
Solution 4 - C#
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);
Solution 5 - C#
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.