How do I change my Windows desktop wallpaper programmatically?
Well, this is a bit awkward, but I'll answer my own question with what I found.
I had to reuse more code from the accepted answer here. Basically the problem in XP was that it needed to use a bmp file, so I managed to convert a project resource to a bmp file using that previous example and a little of tweaking. The Set method works perfectly this way:
public static void Set(string wpaper, Style style)
{
using(System.Drawing.Image img = System.Drawing.Image.FromFile(Path.GetFullPath(wpaper)))
{
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);
}
The important part is on the third line of this code (System.Drawing.Image.FromFile(Path.GetFullPath(wpaper));
).
For a good reliable solution.
Add the foillowing class to your project
using Microsoft.Win32;
using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Runtime.InteropServices;
namespace XXXNAMESPACEXXX
{
public class Wallpaper
{
public enum Style : int
{
Tiled,
Centered,
Stretched
}
[DllImport("user32.dll")]
public static extern Int32 SystemParametersInfo(UInt32 action, UInt32 uParam, String vParam, UInt32 winIni);
public static readonly UInt32 SPI_SETDESKWALLPAPER = 0x14;
public static readonly UInt32 SPIF_UPDATEINIFILE = 0x01;
public static readonly UInt32 SPIF_SENDWININICHANGE = 0x02;
public static bool Set(string filePath, Style style)
{
bool Success = false;
try
{
Image i = System.Drawing.Image.FromFile(Path.GetFullPath(filePath));
Set(i, style);
Success = true;
}
catch //(Exception ex)
{
//ex.HandleException();
}
return Success;
}
public static bool Set(Image image, Style style)
{
bool Success = false;
try
{
string TempPath = Path.Combine(Path.GetTempPath(), "wallpaper.bmp");
image.Save(TempPath, ImageFormat.Bmp);
RegistryKey key = Registry.CurrentUser.OpenSubKey(@"Control Panel\Desktop", true);
switch (style)
{
case Style.Stretched:
key.SetValue(@"WallpaperStyle", 2.ToString());
key.SetValue(@"TileWallpaper", 0.ToString());
break;
case Style.Centered:
key.SetValue(@"WallpaperStyle", 1.ToString());
key.SetValue(@"TileWallpaper", 0.ToString());
break;
default:
case Style.Tiled:
key.SetValue(@"WallpaperStyle", 1.ToString());
key.SetValue(@"TileWallpaper", 1.ToString());
break;
}
SystemParametersInfo(SPI_SETDESKWALLPAPER, 0, TempPath, SPIF_UPDATEINIFILE | SPIF_SENDWININICHANGE);
Success = true;
}
catch //(Exception ex)
{
//ex.HandleException();
}
return Success;
}
}
}
Note: Replace XXXNAMESPACEXXX with the default namespace of your project.
Then it can be used like the following:
string FilePath = TxtFilePath.Text;
Wallpaper.Set(FilePath, Wallpaper.Style.Centered);
It can also be used like this:
if(Wallpaper.Set(FilePath, Wallpaper.Style.Centered))
{
MessageBox.Show("Your wallpaper has been set to " + FilePath);
}
else
{
MessageBox.Show("There was a problem setting the wallpaper.");
}
This is verfied working on Windows XP, 7, 8, 8.1 and Windows 10.
Note It is worth bearing in mind that this method will bypass any desktop wallpaper security restictions applied by network admin.