You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用IDesktopWallpaper实现桌面壁纸幻灯片效果

实现Windows桌面壁纸幻灯片效果

我已经通过DesktopWallpaper类实现了单张桌面壁纸的设置,代码如下:

public static void SetDesktopWallpaper(string imagePath, DesktopWallpaperPosition wallpaperPosition)
{
    IDesktopWallpaper wallpaper = DesktopWallpaper.WallpaperWrapper.GetWallpaper();

    wallpaper.SetPosition(wallpaperPosition);
    wallpaper.SetWallpaper(null, imagePath);
    Marshal.ReleaseComObject(wallpaper);
}

但现在需要实现多张图片的幻灯片轮换效果,不清楚SetSlideshow(IntPtr items)的参数如何传入图片路径列表,现有类定义如下:

public class DesktopWallpaper
{
    [StructLayout(LayoutKind.Sequential)]
    public struct Rect
    {
        public int Left;
        public int Top;
        public int Right;
        public int Bottom;
    }

    public enum DesktopSlideshowOptions
    {
        ShuffleImages = 0x01
    }

    public enum DesktopSlideshowState
    {
        Enabled = 0x01,
        Slideshow = 0x02,
        DisabledByRemoteSession = 0x04
    }

    public enum DesktopSlideshowDirection
    {
        Forward = 0,
        Backward = 1
    }

    public enum DesktopWallpaperPosition
    {
        Center = 0,
        Tile = 1,
        Stretch = 2,
        Fit = 3,
        Fill = 4,
        Span = 5
    }

    [ComImport, Guid("B92B56A9-8B55-4E14-9A89-0199BBB6F93B"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
    public interface IDesktopWallpaper
    {
        void SetWallpaper([MarshalAs(UnmanagedType.LPWStr)] string monitorID, [MarshalAs(UnmanagedType.LPWStr)] string wallpaper);

        [return: MarshalAs(UnmanagedType.LPWStr)]
        string GetWallpaper([MarshalAs(UnmanagedType.LPWStr)] string monitorID);

        [return: MarshalAs(UnmanagedType.LPWStr)]
        string GetMonitorDevicePathAt(uint monitorIndex);

        [return: MarshalAs(UnmanagedType.U4)]
        uint GetMonitorDevicePathCount();

        [return: MarshalAs(UnmanagedType.Struct)]
        Rect GetMonitorRECT([MarshalAs(UnmanagedType.LPWStr)] string monitorID);

        void SetBackgroundColor([MarshalAs(UnmanagedType.U4)] uint color);

        [return: MarshalAs(UnmanagedType.U4)]
        uint GetBackgroundColor();

        void SetPosition([MarshalAs(UnmanagedType.I4)] DesktopWallpaperPosition position);

        [return: MarshalAs(UnmanagedType.I4)]
        DesktopWallpaperPosition GetPosition();

        void SetSlideshow(IntPtr items);

        IntPtr GetSlideshow();

        void SetSlideshowOptions(DesktopSlideshowDirection options, uint slideshowTick);
        [PreserveSig]

        uint GetSlideshowOptions(out DesktopSlideshowDirection options, out uint slideshowTick);

        void AdvanceSlideshow([MarshalAs(UnmanagedType.LPWStr)] string monitorID, [MarshalAs(UnmanagedType.I4)] DesktopSlideshowDirection direction);

        DesktopSlideshowDirection GetStatus();

        bool Enable();
    }

    public static class WallpaperWrapper
    {
        static readonly Guid CLSID_DesktopWallpaper = new Guid("{C2CF3110-460E-4fc1-B9D0-8A1C0C9CC4BD}");

        public static IDesktopWallpaper GetWallpaper()
        {
            Type typeDesktopWallpaper = Type.GetTypeFromCLSID(CLSID_DesktopWallpaper);
            return (IDesktopWallpaper)Activator.CreateInstance(typeDesktopWallpaper);
        }

    }
}

解决方法

SetSlideshow(IntPtr items)的参数实际是指向IShellItemArray接口的指针,需要将图片路径列表转换为这个COM对象后传入。以下是完整实现:

1. 添加必要的COM接口定义

需要补充IShellItem和IShellItemArray的COM导入定义,以及用于创建ShellItem的系统API:

[ComImport, Guid("43826D1E-E718-42EE-BC55-A1E261C37BFE"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IShellItem
{
    void BindToHandler(IntPtr pbc, [MarshalAs(UnmanagedType.LPStruct)] Guid bhid, [MarshalAs(UnmanagedType.LPStruct)] Guid riid, out IntPtr ppv);
    void GetParent(out IShellItem ppsi);
    void GetDisplayName(SIGDN sigdnName, out IntPtr ppszName);
    void GetAttributes(uint sfgaoMask, out uint psfgaoAttribs);
    void Compare(IShellItem psi, uint hint, out int piOrder);
}

[ComImport, Guid("B63EA76D-1F85-456F-A19C-48159EFA858B"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IShellItemArray
{
    void BindToHandler(IntPtr pbc, [MarshalAs(UnmanagedType.LPStruct)] Guid bhid, [MarshalAs(UnmanagedType.LPStruct)] Guid riid, out IntPtr ppv);
    void GetPropertyStore(int flags, [MarshalAs(UnmanagedType.LPStruct)] Guid riid, out IntPtr ppv);
    void GetPropertyDescriptionList(IntPtr keyType, [MarshalAs(UnmanagedType.LPStruct)] Guid riid, out IntPtr ppv);
    void GetAttributes(uint dwAttribFlags, uint sfgaoMask, out uint psfgaoAttribs);
    uint GetCount();
    void GetItemAt(uint index, out IShellItem ppsi);
    void EnumItems(out IEnumShellItems ppenumShellItems);
}

[ComImport, Guid("7F73BE3F-FB79-493C-A6C7-7EE14E245841"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IEnumShellItems
{
    uint Next(uint celt, [Out, MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.Interface, SizeParamIndex = 0)] IShellItem[] rgelt, out uint pceltFetched);
    void Skip(uint celt);
    void Reset();
    void Clone(out IEnumShellItems ppenum);
}

public enum SIGDN : uint
{
    SIGDN_DESKTOPABSOLUTEPARSING = 0x80028000,
}

public static class Shell32
{
    [DllImport("shell32.dll", CharSet = CharSet.Unicode, PreserveSig = false)]
    public static extern void SHCreateItemFromParsingName(
        [MarshalAs(UnmanagedType.LPWStr)] string pszPath,
        IntPtr pbc,
        [MarshalAs(UnmanagedType.LPStruct)] Guid riid,
        out IShellItem ppsi);

    [DllImport("shell32.dll", PreserveSig = false)]
    public static extern void SHCreateShellItemArrayFromShellItems(
        uint cItems,
        [MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.Interface)] IShellItem[] apsitems,
        out IShellItemArray ppia);
}

2. 实现设置幻灯片的方法

添加静态方法,将图片路径列表转换为IShellItemArray并传入SetSlideshow:

public static void SetDesktopSlideshow(List<string> imagePaths, uint slideIntervalSeconds, DesktopWallpaperPosition position, bool shuffle)
{
    if (imagePaths == null || imagePaths.Count == 0)
        throw new ArgumentException("图片路径列表不能为空");

    IDesktopWallpaper wallpaper = DesktopWallpaper.WallpaperWrapper.GetWallpaper();
    try
    {
        // 转换路径为IShellItem数组
        List<IShellItem> shellItems = new List<IShellItem>();
        Guid shellItemGuid = typeof(IShellItem).GUID;

        foreach (string path in imagePaths)
        {
            if (!File.Exists(path))
                throw new FileNotFoundException("图片不存在", path);
            
            Shell32.SHCreateItemFromParsingName(path, IntPtr.Zero, shellItemGuid, out IShellItem item);
            shellItems.Add(item);
        }

        // 创建IShellItemArray
        Shell32.SHCreateShellItemArrayFromShellItems((uint)shellItems.Count, shellItems.ToArray(), out IShellItemArray itemArray);

        // 设置幻灯片
        IntPtr itemArrayPtr = Marshal.GetComInterfaceForObject(itemArray, typeof(IShellItemArray));
        wallpaper.SetSlideshow(itemArrayPtr);

        // 设置切换间隔(单位:毫秒)
        DesktopSlideshowDirection options = shuffle ? 
            (DesktopSlideshowDirection)((int)DesktopSlideshowDirection.Forward | (int)DesktopSlideshowOptions.ShuffleImages) : 
            DesktopSlideshowDirection.Forward;
        wallpaper.SetSlideshowOptions(options, slideIntervalSeconds * 1000);

        // 设置壁纸位置
        wallpaper.SetPosition(position);

        // 启用幻灯片
        wallpaper.Enable();

        // 释放资源
        Marshal.Release(itemArrayPtr);
        Marshal.ReleaseComObject(itemArray);
        foreach (var item in shellItems)
            Marshal.ReleaseComObject(item);
    }
    finally
    {
        Marshal.ReleaseComObject(wallpaper);
    }
}

3. 调用示例

// 示例:设置3张图片,每10秒切换一次,填充模式,随机播放
List<string> imagePaths = new List<string>
{
    @"C:\Wallpapers\img1.jpg",
    @"C:\Wallpapers\img2.jpg",
    @"C:\Wallpapers\img3.jpg"
};

SetDesktopSlideshow(imagePaths, 10, DesktopWallpaperPosition.Fill, true);

关键说明

  • SetSlideshow接收的IntPtr是IShellItemArray接口的指针,必须通过Shell32的API创建该对象
  • 切换间隔单位是毫秒,需将秒数乘以1000转换
  • DesktopSlideshowOptions.ShuffleImages是标记位,需和DesktopSlideshowDirection组合使用
  • 所有COM对象使用后必须手动释放,避免内存泄漏

内容的提问来源于stack exchange,提问作者Chibako

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.13 04:23:09