none
How to change the Wallpaper programmatically?

    Question

  • I have a lot of wallpapers I have in several sub directories of a main wallpaper directory.

    Sadly in Windows 7 if you select a slideshow it only uses the images in the current directory and no images in sub directories.

    Now my idea was to write a program that lets me select multiple directories and create a new temp directory with all the images in these, set windows to use a slideshow of all these images and then delete the temp directory.

    Windows somehow caches the current wallpaper image even if the original file is deleted, I assume that doesn't happen if its a slideshow with many images?

    Now the question is, how do I set a wallpaper slideshow in Windows 7 with C#?

    And googling this I found a lot of people saying only bmp or only bmp and jpg files are supported, is this true? If so, how can that be when I can only use png images if I manually set a wallpaper?


    Wednesday, March 29, 2017 1:35 PM

All replies

  • On Windows 10, IActiveDesktop::SetWallpaper works with *.png.

    But I cannot test for Windows 7...


    • Edited by Castorix31 Wednesday, March 29, 2017 2:06 PM
    Wednesday, March 29, 2017 2:05 PM
  • Hi Ishiirou,

    Thank you for posting here.

    >>And googling this I found a lot of people saying only bmp or only bmp and jpg files are supported, is this true? If so, how can that be when I can only use png images if I manually set a wallpaper?

    For your question, you could set the png image as background image. Please try the following code.

    using Microsoft.Win32;
    using System;
    using System.Collections.Generic;
    using System.IO;
    using System.Linq;
    using System.Runtime.InteropServices;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace change_Wallpaper2
    {
        class Program
        {
            /// <summary>
            /// set the parameter of system
            /// </summary>
            /// <param name="uAction"></param>
            /// <param name="uParam"></param>
            /// <param name="lpvParam"></param>
            /// <param name="fuWinIni"></param>
            /// <example></example>
            /// <returns></returns>
            [DllImport("user32.dll", EntryPoint = "SystemParametersInfo")]
            public static extern int SystemParametersInfo(UAction uAction, int uParam, StringBuilder lpvParam, int fuWinIni);
            static void Main(string[] args)
            {
                GetBackgroud();
                SetBackgroud(@"C:\Users\v-wezan\Desktop\Qimage\2.png");
            }
            public enum UAction
            {
                /// <summary>
                /// set the desktop background image
                /// </summary>
                SPI_SETDESKWALLPAPER = 0x0014,
                /// <summary>
                /// set the desktop background image
                /// </summary>
                SPI_GETDESKWALLPAPER = 0x0073,
            }
            public static string GetBackgroud()
            {
                StringBuilder s = new StringBuilder(300);
                SystemParametersInfo(UAction.SPI_GETDESKWALLPAPER, 300, s, 0);
                return s.ToString();
            }
            /// <summary>
            /// set the desktop background image
            /// </summary>
            /// <param name="fileName">the path of image</param>
            /// <returns></returns>
            public static int SetBackgroud(string fileName)
            {
                int result = 0;
                if (File.Exists(fileName))
                {
                    StringBuilder s = new StringBuilder(fileName);
                    result = SystemParametersInfo(UAction.SPI_SETDESKWALLPAPER, 0, s, 0x2);
                }
                return result;
            }
            /// <summary>
            /// set the option of registry
            /// </summary>
            /// <param name="optionsName">the name of registry</param>
            /// <param name="optionsData">set the data of registry</param>
            /// <param name="msg"></param>
            /// <returns></returns>
            public static bool SetOptions(string optionsName, string optionsData, ref string msg)
            {
                bool returnBool = true;
                RegistryKey classesRoot = Registry.CurrentUser;
                RegistryKey registryKey = classesRoot.OpenSubKey(@"Control Panel\Desktop", true);
                try
                {
                    if (registryKey != null)
                    {
                        registryKey.SetValue(optionsName.ToUpper(), optionsData);
                    }
                    else
                    {
                        returnBool = false;
                    }
                }
                catch
                {
                    returnBool = false;
                    msg = "Error when read the registry";
                }
                finally
                {
                    classesRoot.Close();
                    registryKey.Close();
                }
                return returnBool;
            }
        }
    }

    My computer in win10. I do not have environment of win7 to test the code. But in my computer it works well.

    For the method SetBackgroud(), if it return the result 0 means it fails. If it return the result 1, it means success.

    If you set the background image successfully, but it does not changed in desktop, you could to use the SetOptions() method in my code to set the HKEY_CURRENT_USER\Control Panel\Desktop registry.

    I set the .png image to my computer background image. I use a gif to show the result.

    I hope this would be helpful.

    Best Regards,

    Wendy


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.



    Thursday, March 30, 2017 6:41 AM
    Moderator
  • Thanks, I got it to work for a single image (I am currently testing this on Windows 10 as well, I need to test it on Windows 7 later).

    Now I need to try to set a slideshow. But you made a small error, the registry key is "Wallpaper", the key you mentioned does not work.

    I tested some more and setting a slideshow works quite differently, apparently there is an ini where it can be seen but it is encoded weirdly, it looks like a base64 string but encoded it becomes a short string full of special symbols that in no way resembles the path to the directory with the image.

    Also, it works quite differently in Windows 7 because in Windows 10 for whatever reason only Microsoft knows you can no longer select which images in a directory to use for the slideshow, you can ONLY use the entire directory.

    This is neat but far from what I want.


    • Edited by Ishiirou Thursday, March 30, 2017 12:43 PM
    Thursday, March 30, 2017 12:29 PM
  • Hi Ishiirou,

    Thank you for feedback.

    Does the code works well on Win7?

    If it works well in win7, please ignore the registry. And you could use a timer to set the dynamic wallpaper. It works well for me.

    using Microsoft.Win32;
    using System;
    using System.Collections.Generic;
    using System.IO;
    using System.Linq;
    using System.Runtime.InteropServices;
    using System.Text;
    using System.Threading.Tasks;
    using System.Timers;
    
    namespace change_Wallpaper2
    {
        class Program
        {
            /// <summary>
            /// set the parameter of system
            /// </summary>
            /// <param name="uAction"></param>
            /// <param name="uParam"></param>
            /// <param name="lpvParam"></param>
            /// <param name="fuWinIni"></param>
            /// <example></example>
            /// <returns></returns>
            [DllImport("user32.dll", EntryPoint = "SystemParametersInfo")]
            public static extern int SystemParametersInfo(UAction uAction, int uParam, StringBuilder lpvParam, int fuWinIni);
            int picIndex = 0;
    
            private static System.Timers.Timer aTimer;
    
            static void Main(string[] args)
            {
                Program p = new Program();
                GetBackgroud();
                p.SetTimer();
                Console.ReadLine();
                aTimer.Stop();
                aTimer.Dispose();
            }
    
            private void SetTimer()
            {
                // Create a timer with a two second interval.
                aTimer = new System.Timers.Timer(2000);
                // Hook up the Elapsed event for the timer. 
                aTimer.Elapsed += OnTimedEvent;
                aTimer.AutoReset = true;
                aTimer.Enabled = true;
            }
    
            // Specify what you want to happen when the Elapsed event is raised.
            private void OnTimedEvent(object source, ElapsedEventArgs e)
            {
                string[] filenames = System.IO.Directory.GetFiles(@"C:\Users\v-wezan\Desktop\Qimage");
                List<string> list = new List<string>();
                list = filenames.ToList();
                if (picIndex < list.Count)
                {
                    SetBackgroud(list[picIndex].ToString());
                    picIndex += 1;
                }
                else
                {
                    picIndex = 0;
                    SetBackgroud(list[picIndex].ToString());
                }
                //SetBackgroud(@"C:\Users\v-wezan\Desktop\Qimage\2.png");
            }
            public enum UAction
            {
                /// <summary>
                /// set the desktop background image
                /// </summary>
                SPI_SETDESKWALLPAPER = 0x0014,
                /// <summary>
                /// set the desktop background image
                /// </summary>
                SPI_GETDESKWALLPAPER = 0x0073,
            }
            public static string GetBackgroud()
            {
                StringBuilder s = new StringBuilder(300);
                SystemParametersInfo(UAction.SPI_GETDESKWALLPAPER, 300, s, 0);
                return s.ToString();
            }
            /// <summary>
            /// set the desktop background image
            /// </summary>
            /// <param name="fileName">the path of file</param>
            /// <returns></returns>
            public static int SetBackgroud(string fileName)
            {
                int result = 0;
                if (File.Exists(fileName))
                {
                    StringBuilder s = new StringBuilder(fileName);
                    result = SystemParametersInfo(UAction.SPI_SETDESKWALLPAPER, 0, s, 0x2);
                }
                return result;
            }
        }
    }


    I hope this would be helpful.

    Best Regards,

    Wendy


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.



    Friday, March 31, 2017 5:46 AM
    Moderator
  • Hi lshiirou,

    Any update?

    If your question has been solve, please mark the useful reply as answer.

    Best Regards,

    Wendy


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    Wednesday, April 12, 2017 6:55 AM
    Moderator
  • Hi, i'm trying to change the wallpaper using SystemParametersInfo, it works well in windows application, but if in windows service, it couldn't work, i already allowed the service to interact with desktop, don't know why, hope to get your reply, thanks very much.
    • Edited by Qidong Kuang Thursday, September 6, 2018 12:13 PM
    Thursday, September 6, 2018 10:09 AM