【问题标题】:How to set multiple desktop backgrounds (dual monitor)如何设置多个桌面背景(双显示器)
【发布时间】:2009-10-08 20:45:47
【问题描述】:

我有一个代码 sn-p 可以在两台显示器上设置一个图像,但我最近为我的笔记本电脑准备了第二台显示器,我想修改我的代码,以便为每台显示器设置不同的图像。

有什么想法吗?

(单显示器的这段代码是:

[DllImport("user32.dll", CharSet = CharSet.Auto)]
        private static extern Int32 SystemParametersInfo(UInt32 action, UInt32 uParam, String vParam, UInt32 winIni);
        private static readonly UInt32 SPI_SETDESKWALLPAPER = 0x14;
        private static readonly UInt32 SPIF_UPDATEINIFILE = 0x01;
        private static readonly UInt32 SPIF_SENDWININICHANGE = 0x02;

        private void SetWallpaper(string path)
        {
            if (path != null)
            {

                string savepath = Settings.Default.SavePath;

                Image imgInFile = Image.FromFile(path);
                imgInFile.Save(savepath, ImageFormat.Bmp);
                SystemParametersInfo(SPI_SETDESKWALLPAPER, 3, savepath, SPIF_UPDATEINIFILE | SPIF_SENDWININICHANGE);
            }
            else
            {
                MessageBox.Show("Path Null");
            }
        }

)

【问题讨论】:

  • 我用 UltraMon 做这个和更多:realtimesoft.com/ultramon
  • 这实际上是我想到将它们设置成这样的地方。然而,我不喜欢花钱买东西,因为我只是懒得学习如何自己做。

标签: c# windows monitor wallpaper


【解决方案1】:

好吧,拿了别人的答案代码并稍作修改...... 问题是之前的代码假定主监视器在要创建的新图片中位于最顶部和最左侧......它对我不起作用。 编辑 --> 发现 Windows 7 和 10 在平铺图片的起始位置方面表现不同。 Win 10 从左上角开始.... Win 7 总是从主监视器开始。

using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using Microsoft.Win32;
using System.Windows.Forms;
using System.IO;


namespace toolbox.Wallpaper
{
    public class CustomWally
    {
        const int SetDeskWallpaper = 20;
        const int UpdateIniFile = 0x01;
        const int SendWinIniChange = 0x02;
        [DllImport("user32.dll", CharSet = CharSet.Auto)]
        static extern int SystemParametersInfo(int uAction, int uParam, string lpvParam, int fuWinIni);




        Point primaryMonitorPoint = new Point(0, 0);
        const string defaultBackgroundFile = @"C:\Users\Public\Pictures\Sample Pictures\DefaultBackground.jpg";
        Dictionary<string, Image> images = new Dictionary<string, Image>();

        public CustomWally()
        {
            //figure out where the main monitor is in relation to the virtualScreenBitmap
            foreach (Screen scr in Screen.AllScreens)
            {
                images.Add(scr.DeviceName, null);
                screenos.Add(scr.DeviceName);
                if (scr.Bounds.Left < primaryMonitorPoint.X)
                    primaryMonitorPoint.X = scr.Bounds.Left;
                if (scr.Bounds.Top < primaryMonitorPoint.Y)
                    primaryMonitorPoint.Y = scr.Bounds.Top;
            }
            primaryMonitorPoint.X *= -1;
            primaryMonitorPoint.Y *= -1;

            //Image for multiple screens
            images.Add("all", null);

            //set Images in Dictionary in case there are previous Images
            if (File.Exists(defaultBackgroundFile))
            {
                using (var old = new Bitmap(defaultBackgroundFile))
                {
                    foreach (Screen scr in Screen.AllScreens)
                    {
                        Rectangle rectangle = new Rectangle(primaryMonitorPoint.X + scr.Bounds.Left, primaryMonitorPoint.Y + scr.Bounds.Top, scr.Bounds.Width, scr.Bounds.Height);
                        if (old.Width >= (rectangle.X + rectangle.Width) &&
                            old.Height >= (rectangle.Y + rectangle.Height))
                            images[scr.DeviceName] = (Bitmap)old.Clone(rectangle, old.PixelFormat);
                    }
                }
            }
        }



        List<string> screenos = new List<string>();
        int index = 0;


        public void setAlternatingWalls(string file)
        {
            images[screenos[index]] = Image.FromFile(file);
            index++;
            if (index == screenos.Count)
                index = 0;

            CreateBackgroundImage(Method.multiple);
            GC.Collect();
        }

        public void setWallforScreen(Screen screen, string file)
        {
            images[screen.DeviceName] = Image.FromFile(file);
            CreateBackgroundImage(Method.multiple);
            GC.Collect();
        }

        public void setWallforAllScreen(string file)
        {
            images["all"] = Image.FromFile(file);
            CreateBackgroundImage(Method.single);
            GC.Collect();
        }


        private enum Method
        {
            multiple,
            single
        }
        private void CreateBackgroundImage(Method method)
        {

            using (var virtualScreenBitmap = new Bitmap((int)System.Windows.Forms.SystemInformation.VirtualScreen.Width, (int)System.Windows.Forms.SystemInformation.VirtualScreen.Height))
            {
                using (var virtualScreenGraphic = Graphics.FromImage(virtualScreenBitmap))
                {

                    switch (method)
                    {
                        // alternated Screen Images
                        case Method.multiple:
                            foreach (var screen in System.Windows.Forms.Screen.AllScreens)
                            {
                                // gets the image which we want to place in virtualScreenGraphic
                                var image = (images.ContainsKey(screen.DeviceName)) ? images[screen.DeviceName] : null;

                                //sets the position and size where the images will go
                                Rectangle rectangle = new Rectangle(primaryMonitorPoint.X + screen.Bounds.Left, primaryMonitorPoint.Y + screen.Bounds.Top, screen.Bounds.Width, screen.Bounds.Height);

                                // produce a image for the screen and fill it with the desired image... centered
                                var monitorBitmap = new Bitmap(rectangle.Width, rectangle.Height);
                                if (image != null)
                                    DrawImageCentered(Graphics.FromImage(monitorBitmap), image, rectangle);

                                //draws the picture at the right place in virtualScreenGraphic
                                virtualScreenGraphic.DrawImage(monitorBitmap, rectangle);
                            }
                            break;

                        //Single screen Image
                        case Method.single:
                            // gets the image which we want to place in virtualScreenGraphic
                            var image2 = images["all"];

                            //sets the position and size where the images will go
                            Rectangle rectangle2 = new Rectangle(0, 0, virtualScreenBitmap.Width, virtualScreenBitmap.Height);

                            // fill with the desired image... centered                            
                            if (image2 != null)
                                DrawImageCentered(virtualScreenGraphic, image2, rectangle2);

                            //draws the picture at the right place in virtualScreenGraphic
                            virtualScreenGraphic.DrawImage(virtualScreenBitmap, rectangle2);
                            break;
                    }

                    virtualScreenBitmap.Save(defaultBackgroundFile, ImageFormat.Jpeg);
                }
            }

            RegistryKey key = Registry.CurrentUser.OpenSubKey(@"Control Panel\Desktop", true);
            key.SetValue(@"WallpaperStyle", 0.ToString());
            key.SetValue(@"TileWallpaper", 1.ToString());
            SystemParametersInfo(SetDeskWallpaper, 0, defaultBackgroundFile, UpdateIniFile | SendWinIniChange);
        }


        private void DrawImageCentered(Graphics g, Image img, Rectangle monitorRect)
        {
            double ratiodev = (1.0 * monitorRect.Width / monitorRect.Height) - (1.0 * img.Width / img.Height);
            if (((1.0 * monitorRect.Width / monitorRect.Height > 1) && ratiodev > -0.25 && ratiodev < 0.25))
            {
                img = getsnappedIMG(img, monitorRect);
            }


            float heightRatio = (float)monitorRect.Height / (float)img.Height;
            float widthRatio = (float)monitorRect.Width / (float)img.Width;
            int height = monitorRect.Height;
            int width = monitorRect.Width;
            int x = 0;
            int y = 0;

            if (heightRatio < widthRatio)
            {
                width = (int)((float)img.Width * heightRatio);
                height = (int)((float)img.Height * heightRatio);
                x = (int)((float)(monitorRect.Width - width) / 2f);
            }
            else
            {
                width = (int)((float)img.Width * widthRatio);
                height = (int)((float)img.Height * widthRatio);
                y = (int)((float)(monitorRect.Height - height) / 2f);
            }
            Rectangle rect = new Rectangle(x, y, width, height);
            g.DrawImage(img, rect);
        }

        private Image getsnappedIMG(Image img, Rectangle monitorRect)
        {
            double ratiodev = (1.0 * monitorRect.Width / monitorRect.Height) - (1.0 * img.Width / img.Height);
            int height = img.Height;
            int width = img.Width;

            Rectangle rect;
            if (ratiodev < 0)
            {
                rect = new Rectangle(0, 0, (int)((1.0 * monitorRect.Width / monitorRect.Height) * height), height);                
                rect.X = (width - rect.Width) / 2;                
            }
            else
            {
                rect = new Rectangle(0, 0, width, (int)(1.0 * width / (1.0 * monitorRect.Width / monitorRect.Height)));
                rect.Y = (height - rect.Height) / 2;
            }


            var img2 = (Bitmap)img;
            return (Bitmap)img2.Clone(rect, img.PixelFormat);

        }
    }
}

【讨论】:

    【解决方案2】:

    其实没有区别。

    将多台显示器视为只是扩大壁纸空间。

    因此,您需要做的是从多个图像中创建一个壁纸图像,以填充每个显示器的矩形区域。

    这个问题看起来也像duplicate

    【讨论】:

    • 多么尴尬,我忘记了这一切。我搜索了双显示器壁纸,但我什至没有看到。 +1 发现
    【解决方案3】:
    using System;
    using System.Collections.Generic;
    using System.Drawing;
    using System.Drawing.Imaging;
    using System.Runtime.InteropServices;
    
    namespace SetWallpapers
    {
        internal class Program
        {
            [DllImport("user32.dll", CharSet = CharSet.Auto)]
            private static extern Int32 SystemParametersInfo(UInt32 uiAction, UInt32 uiParam, String pvParam, UInt32 fWinIni);
    
            private static UInt32 SPI_SETDESKWALLPAPER = 20;
            private static UInt32 SPIF_UPDATEINIFILE = 0x1;
    
            public void SetImage(string filename)
            {
                SystemParametersInfo(SPI_SETDESKWALLPAPER, 0, filename, SPIF_UPDATEINIFILE);
            }
    
            private static void Main(string[] args)
            {
                var images = new Dictionary<string, Image>
                {
                    { @"\\.\DISPLAY1", Image.FromFile(@"C:\Users\Public\Pictures\Sample Pictures\Lighthouse.jpg") },
                    { @"\\.\DISPLAY2", Image.FromFile(@"C:\Users\Public\Pictures\Sample Pictures\Jellyfish.jpg") },
                    { @"\\.\DISPLAY3", Image.FromFile(@"C:\Users\Public\Pictures\Sample Pictures\Koala.jpg") }
                };
    
                CreateBackgroundImage(images);
    
            }
    
            private static void CreateBackgroundImage(Dictionary<string, Image> imageFiles)
            {
                const string defaultBackgroundFile = @"C:\Users\Public\Pictures\Sample Pictures\DefaultBackground.bmp";
    
                using (var virtualScreenBitmap = new Bitmap((int)System.Windows.SystemParameters.VirtualScreenWidth, (int)System.Windows.SystemParameters.VirtualScreenHeight))
                {
                    using (var virtualScreenGraphic = Graphics.FromImage(virtualScreenBitmap))
                    {
                        foreach (var screen in System.Windows.Forms.Screen.AllScreens)
                        {
                            var image = (imageFiles.ContainsKey(screen.DeviceName)) ? imageFiles[screen.DeviceName] : null;
    
                            var monitorDimensions = screen.Bounds;
                            var width = monitorDimensions.Width;
                            var monitorBitmap = new Bitmap(width, monitorDimensions.Height);
                            var fromImage = Graphics.FromImage(monitorBitmap);
                            fromImage.FillRectangle(SystemBrushes.Desktop, 0, 0, monitorBitmap.Width, monitorBitmap.Height);
    
                            if (image != null)
                                DrawImageCentered(fromImage, image, new Rectangle(0, 0, monitorBitmap.Width, monitorBitmap.Height));
    
                            Rectangle rectangle;
                            if (monitorDimensions.Top == 0 && monitorDimensions.Left == 0)
                            {
                                rectangle = monitorDimensions;
                            }
                            else
                            {
                                if ((monitorDimensions.Left < 0 && monitorDimensions.Width > -monitorDimensions.Left) ||
                                    (monitorDimensions.Top < 0 && monitorDimensions.Height > -monitorDimensions.Top))
                                {
                                    var isMain = (monitorDimensions.Top < 0 && monitorDimensions.Bottom > 0);
    
                                    var left = (monitorDimensions.Left < 0)
                                                   ? (int) System.Windows.SystemParameters.VirtualScreenWidth + monitorDimensions.Left
                                                   : monitorDimensions.Left;
    
                                    var top = (monitorDimensions.Top < 0)
                                                  ? (int) System.Windows.SystemParameters.VirtualScreenHeight + monitorDimensions.Top
                                                  : monitorDimensions.Top;
    
                                    Rectangle srcRect;
                                    if (isMain)
                                    {
                                        rectangle = new Rectangle(left, 0, monitorDimensions.Width, monitorDimensions.Bottom);
                                        srcRect = new Rectangle(0, -monitorDimensions.Top, monitorDimensions.Width, monitorDimensions.Height + monitorDimensions.Top);
                                    }
                                    else
                                    {
                                        rectangle = new Rectangle(0, top, monitorDimensions.Right, monitorDimensions.Height);
                                        srcRect = new Rectangle(-monitorDimensions.Left, 0, monitorDimensions.Width + monitorDimensions.Left,
                                                                monitorDimensions.Height);
                                    }
    
                                    virtualScreenGraphic.DrawImage(monitorBitmap, rectangle, srcRect, GraphicsUnit.Pixel);
                                    rectangle = new Rectangle(left, top, monitorDimensions.Width, monitorDimensions.Height);
                                }
                                else
                                {
                                    var left = (monitorDimensions.Left < 0)
                                                   ? (int) System.Windows.SystemParameters.VirtualScreenWidth + monitorDimensions.Left
                                                   : monitorDimensions.Left;
                                    var top = (monitorDimensions.Top < 0)
                                                  ? (int) System.Windows.SystemParameters.VirtualScreenHeight + monitorDimensions.Top
                                                  : monitorDimensions.Top;
                                    rectangle = new Rectangle(left, top, monitorDimensions.Width, monitorDimensions.Height);
                                }
                            }
                            virtualScreenGraphic.DrawImage(monitorBitmap, rectangle);
                        }
    
                        virtualScreenBitmap.Save(defaultBackgroundFile, ImageFormat.Bmp);
                    }
                }
    
                SystemParametersInfo(SPI_SETDESKWALLPAPER, 0u, defaultBackgroundFile, SPIF_UPDATEINIFILE);
            }
    
    
            private static void DrawImageCentered(Graphics g, Image img, Rectangle monitorRect)
            {
                float heightRatio = (float)monitorRect.Height / (float)img.Height;
                float widthRatio = (float)monitorRect.Width / (float)img.Width;
                int height = monitorRect.Height;
                int width = monitorRect.Width;
                int x = 0;
                int y = 0;
    
                if (heightRatio > 1f && widthRatio > 1f)
                {
                    height = img.Height;
                    width = img.Width;
                    x = (int)((float)(monitorRect.Width - width) / 2f);
                    y = (int)((float)(monitorRect.Height - height) / 2f);
                }
                else
                {
                    if (heightRatio < widthRatio)
                    {
                        width = (int)((float)img.Width * heightRatio);
                        height = (int)((float)img.Height * heightRatio);
                        x = (int)((float)(monitorRect.Width - width) / 2f);
                    }
                    else
                    {
                        width = (int)((float)img.Width * widthRatio);
                        height = (int)((float)img.Height * widthRatio);
                        y = (int)((float)(monitorRect.Height - height) / 2f);
                    }
                }
    
                Rectangle rect = new Rectangle(x, y, width, height);
                g.DrawImage(img, rect);
            }
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-10-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-04-30
      • 1970-01-01
      相关资源
      最近更新 更多