如何以编程方式更改我的 Windows 桌面墙纸?

Posted

技术标签:

【中文标题】如何以编程方式更改我的 Windows 桌面墙纸?【英文标题】:How do I change my Windows desktop wallpaper programmatically? 【发布时间】:2012-01-14 22:10:46 【问题描述】:

我希望使用 C# 为 Windows XP 设置墙纸。我已经开发了代码,因此它可以在 Windows 7 中完美运行,但显然对于 XP 来说并不相同。我将该壁纸添加为资源,将其编译操作设置为内容并始终复制。奇怪的是,它在桌面的属性对话框中设置了正确的壁纸名称。但是,未设置壁纸。我的代码如下所示:

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

在调用 Wallpaper.Set("wpapername") 时,它会从项目资源中获取壁纸。它适用于Win7,但不适用于WinXP。我做错了吗?

【问题讨论】:

这个类似的question 可能正是你所需要的。 我的代码基于该代码,但我的壁纸需要使用该应用程序进行部署。 可能是XP没有处理相对路径,你可能需要指定壁纸的整个路径。 可能重复***.com/questions/1061678/… 【参考方案1】:

嗯,这有点尴尬,但我会用我的发现回答我自己的问题。

我不得不重用已接受答案here 中的更多代码。 基本上 XP 中的问题是它需要使用 bmp 文件,所以我设法使用前面的示例和一些调整将项目资源转换为 bmp 文件。 Set 方法以这种方式完美运行:

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


重要的部分在这段代码的第三行 (System.Drawing.Image.FromFile(Path.GetFullPath(wpaper));)。

【讨论】:

你应该在保存后处理img-Object。否则,如果代码被循环访问,你会遇到麻烦。【参考方案2】:

为了一个好的可靠的解决方案。

在你的项目中添加下面的类

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;
        

    


注意:将 XXXNAMESPACEXXX 替换为您项目的默认命名空间。

那么它可以像下面这样使用:

string FilePath = TxtFilePath.Text;

Wallpaper.Set(FilePath, Wallpaper.Style.Centered);

也可以这样使用:

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


这已在 Windows XP、7、8、8.1 和 Windows 10 上得到验证。

注意值得牢记的是,此方法会绕过网络管理员应用的任何桌面壁纸安全限制。

【讨论】:

Windows 10 引入了排列图像的新方法,例如跨度。这需要将 WallpaperStyle 设置为 22。但这在 Windows 7 上不起作用。

以上是关于如何以编程方式更改我的 Windows 桌面墙纸?的主要内容,如果未能解决你的问题,请参考以下文章

如何以编程方式在 Windows 8 和 Windows 10 桌面登录屏幕上显示状态栏? [关闭]

如何以编程方式访问连接到 Windows 桌面的 iOS 设备的文件系统?

如何以编程方式检测是不是在 Windows 桌面应用程序中启用/禁用了 javascript? (网络浏览器控件)

如何以编程方式停止 Windows 服务?

如何在 Windows 8.1 中以编程方式更改当前的 Windows 主题?

以编程方式更改 Windows 电源设置