How do I change my Windows desktop wallpaper programmatically?

Korcholis picture Korcholis · Dec 7, 2011 · Viewed 18.8k times · Source

I'd wish to set a wallpaper for Windows XP using C#. I've developed the code so it perfectly works in Windows 7, but apparently it's not the same for XP. I add that wallpaper as a resource, set its compile action as Content and Always copy. It, curiously, sets the correct Wallpaper name inside the Desktop's properties dialog. However, the wallpaper is not set. My code looks like this:

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(string wpaper, Style style)
    {
        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());
        }

        string tempPath = "Resources\\"+wpaper;
        SystemParametersInfo(SPI_SETDESKWALLPAPER,
            0,
            tempPath,
            SPIF_UPDATEINIFILE | SPIF_SENDWININICHANGE);
    }
}

When calling Wallpaper.Set("wpapername"), it gets the wallpaper from project resources. It works on Win7, but not on WinXP. Am I doing something wrong?

Answer

Korcholis picture Korcholis · Dec 12, 2011

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));).