zoukankan      html  css  js  c++  java
  • c# 多显示器设置主屏幕(Set primary screen for multiple monitors)

    经过google加各种百度,终于找到了一个有效的解决方案,下面是两个主要类,方便后人使用

    1. Win32 API, 需要添加其它内容可以到这个网站从查找对应的c#实现

        public class WinApi
        {
            public const Int32 CCHDEVICENAME = 32;
            public const Int32 CCHFORMNAME = 32;
    
            public enum DEVMODE_SETTINGS
            {
                ENUM_CURRENT_SETTINGS = (-1),
                ENUM_REGISTRY_SETTINGS = (-2)
            }
            [Flags()]
            public enum DisplayDeviceStateFlags : int
            {
                /// <summary>The device is part of the desktop.</summary>
                AttachedToDesktop = 0x1,
                MultiDriver = 0x2,
                /// <summary>The device is part of the desktop.</summary>
                PrimaryDevice = 0x4,
                /// <summary>Represents a pseudo device used to mirror application drawing for remoting or other purposes.</summary>
                MirroringDriver = 0x8,
                /// <summary>The device is VGA compatible.</summary>
                VGACompatible = 0x10,
                /// <summary>The device is removable; it cannot be the primary display.</summary>
                Removable = 0x20,
                /// <summary>The device has more display modes than its output devices support.</summary>
                ModesPruned = 0x8000000,
                Remote = 0x4000000,
                Disconnect = 0x2000000
            }
    
            public enum Display_Device_Stateflags
            {
                DISPLAY_DEVICE_ATTACHED_TO_DESKTOP = 0x1,
                DISPLAY_DEVICE_MIRRORING_DRIVER = 0x8,
                DISPLAY_DEVICE_MODESPRUNED = 0x8000000,
                DISPLAY_DEVICE_MULTI_DRIVER = 0x2,
                DISPLAY_DEVICE_PRIMARY_DEVICE = 0x4,
                DISPLAY_DEVICE_VGA_COMPATIBLE = 0x10
            }
    
            public enum DeviceFlags
            {
                CDS_FULLSCREEN = 0x4,
                CDS_GLOBAL = 0x8,
                CDS_NORESET = 0x10000000,
                CDS_RESET = 0x40000000,
                CDS_SET_PRIMARY = 0x10,
                CDS_TEST = 0x2,
                CDS_UPDATEREGISTRY = 0x1,
                CDS_VIDEOPARAMETERS = 0x20,
            }
    
            public enum DEVMODE_Flags
            {
                DM_BITSPERPEL = 0x40000,
                DM_DISPLAYFLAGS = 0x200000,
                DM_DISPLAYFREQUENCY = 0x400000,
                DM_PELSHEIGHT = 0x100000,
                DM_PELSWIDTH = 0x80000,
                DM_POSITION = 0x20
            }
    
            public enum DisplaySetting_Results
            {
                DISP_CHANGE_BADFLAGS = -4,
                DISP_CHANGE_BADMODE = -2,
                DISP_CHANGE_BADPARAM = -5,
                DISP_CHANGE_FAILED = -1,
                DISP_CHANGE_NOTUPDATED = -3,
                DISP_CHANGE_RESTART = 1,
                DISP_CHANGE_SUCCESSFUL = 0
            }
    
            [StructLayout(LayoutKind.Sequential)]
            public struct POINTL
            {
                [MarshalAs(UnmanagedType.I4)]
                public int x;
                [MarshalAs(UnmanagedType.I4)]
                public int y;
            }
    
            [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
            public struct DEVMODE
            {
                [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
                public string dmDeviceName;
    
                [MarshalAs(UnmanagedType.U2)]
                public UInt16 dmSpecVersion;
    
                [MarshalAs(UnmanagedType.U2)]
                public UInt16 dmDriverVersion;
    
                [MarshalAs(UnmanagedType.U2)]
                public UInt16 dmSize;
    
                [MarshalAs(UnmanagedType.U2)]
                public UInt16 dmDriverExtra;
    
                [MarshalAs(UnmanagedType.U4)]
                public DEVMODE_Flags dmFields;
    
                public POINTL dmPosition;
    
                [MarshalAs(UnmanagedType.U4)]
                public UInt32 dmDisplayOrientation;
    
                [MarshalAs(UnmanagedType.U4)]
                public UInt32 dmDisplayFixedOutput;
    
                [MarshalAs(UnmanagedType.I2)]
                public Int16 dmColor;
    
                [MarshalAs(UnmanagedType.I2)]
                public Int16 dmDuplex;
    
                [MarshalAs(UnmanagedType.I2)]
                public Int16 dmYResolution;
    
                [MarshalAs(UnmanagedType.I2)]
                public Int16 dmTTOption;
    
                [MarshalAs(UnmanagedType.I2)]
                public Int16 dmCollate;
    
                [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
                public string dmFormName;
    
                [MarshalAs(UnmanagedType.U2)]
                public UInt16 dmLogPixels;
    
                [MarshalAs(UnmanagedType.U4)]
                public UInt32 dmBitsPerPel;
    
                [MarshalAs(UnmanagedType.U4)]
                public UInt32 dmPelsWidth;
    
                [MarshalAs(UnmanagedType.U4)]
                public UInt32 dmPelsHeight;
    
                [MarshalAs(UnmanagedType.U4)]
                public UInt32 dmDisplayFlags;
    
                [MarshalAs(UnmanagedType.U4)]
                public UInt32 dmDisplayFrequency;
    
                [MarshalAs(UnmanagedType.U4)]
                public UInt32 dmICMMethod;
    
                [MarshalAs(UnmanagedType.U4)]
                public UInt32 dmICMIntent;
    
                [MarshalAs(UnmanagedType.U4)]
                public UInt32 dmMediaType;
    
                [MarshalAs(UnmanagedType.U4)]
                public UInt32 dmDitherType;
    
                [MarshalAs(UnmanagedType.U4)]
                public UInt32 dmReserved1;
    
                [MarshalAs(UnmanagedType.U4)]
                public UInt32 dmReserved2;
    
                [MarshalAs(UnmanagedType.U4)]
                public UInt32 dmPanningWidth;
    
                [MarshalAs(UnmanagedType.U4)]
                public UInt32 dmPanningHeight;
            }
    
            [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
            public struct DISPLAY_DEVICE
            {
                [MarshalAs(UnmanagedType.U4)]
                public int cb;
                [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
                public string DeviceName;
                [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
                public string DeviceString;
                [MarshalAs(UnmanagedType.U4)]
                public DisplayDeviceStateFlags StateFlags;
                [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
                public string DeviceID;
                [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
                public string DeviceKey;
            }
    
            public class User_32
            {
                [DllImport("user32.dll")]
                public static extern int ChangeDisplaySettings(ref DEVMODE devMode, int flags);
    
                //[DllImport("user32.dll")]
                //public static extern int ChangeDisplaySettingsEx(ref DEVMODE devMode, int flags);
    
                [DllImport("user32.dll")]
                public static extern int ChangeDisplaySettingsEx(string lpszDeviceName, [In] ref DEVMODE lpDevMode, IntPtr hwnd, int dwFlags, IntPtr lParam);
    
                [DllImport("user32.dll")]
                public static extern bool EnumDisplayDevices(string lpDevice, int iDevNum, ref DISPLAY_DEVICE lpDisplayDevice, int dwFlags);
    
                [DllImport("user32.dll")]
                public static extern int EnumDisplaySettings(string deviceName, int modeNum, ref DEVMODE devMode);
            }
    
        }

    2. 更新主屏幕类

        public class ScreenHelper
        {
            public static List<Screen> GetAllScreen()
            {
                List<WinApi.DISPLAY_DEVICE> devices = new List<WinApi.DISPLAY_DEVICE>();
                List<Screen> screens = new List<Screen>();
                bool error = false;
                //Here I am listing all DisplayDevices (Monitors)
                for (int devId = 0; !error; devId++)
                {
                    try
                    {
                        WinApi.DISPLAY_DEVICE device = new WinApi.DISPLAY_DEVICE();
                        device.cb = Marshal.SizeOf(typeof(WinApi.DISPLAY_DEVICE));
                        error = !WinApi.User_32.EnumDisplayDevices(null, devId, ref device, 0);
                        if ((device.StateFlags & WinApi.DisplayDeviceStateFlags.AttachedToDesktop) == WinApi.DisplayDeviceStateFlags.AttachedToDesktop)
                        {
                            devices.Add(device);
                        }
                    }
                    catch (Exception)
                    {
                        error = true;
                    }
                }
    
                devices.ForEach(d => {
                    WinApi.DEVMODE ndm = NewDevMode();
                    WinApi.User_32.EnumDisplaySettings(d.DeviceName, (int)WinApi.DEVMODE_SETTINGS.ENUM_REGISTRY_SETTINGS, ref ndm);
                    screens.Add(new Screen() { 
                        DeviceMode = ndm, 
                        ScreenDevice = d, 
                        DeviceName = d.DeviceName, 
                        IsPrimary = ((d.StateFlags & WinApi.DisplayDeviceStateFlags.PrimaryDevice) == WinApi.DisplayDeviceStateFlags.PrimaryDevice),
                        ScreenWidth = (int)ndm.dmPelsWidth,
                        ScreenHeight = (int)ndm.dmPelsHeight,
                        XPosition = (int)ndm.dmPosition.x,
                        YPosition = (int)ndm.dmPosition.y
                    });
                });
    
                return screens;
            }
    
            public static void SetPrimaryScreen(string deviceName)
            {
                List<Screen> screenList = GetAllScreen();
                Screen primaryScreen = GetPrimaryScreen(screenList);
                if (primaryScreen.ScreenDevice.DeviceName == deviceName)
                    return;
    
                Screen newPrimaryScreen = GetScreen(deviceName);
    
                SwitchPrimaryScreen(newPrimaryScreen, primaryScreen);
    
            }
    
            public static Screen GetPrimaryScreen(List<Screen> devices)
            {
                foreach (Screen d in devices)
                {
                    if ((d.ScreenDevice.StateFlags & WinApi.DisplayDeviceStateFlags.PrimaryDevice) == WinApi.DisplayDeviceStateFlags.PrimaryDevice)
                    {
                        return d;
                    }
                }
                return null;
            }
    
            public static List<Screen> GetUnPrimaryScreen(List<Screen> devices)
            {
                List<Screen> dList = new List<Screen>();
    
                foreach (Screen d in devices)
                {
                    if ((d.ScreenDevice.StateFlags & WinApi.DisplayDeviceStateFlags.PrimaryDevice) != WinApi.DisplayDeviceStateFlags.PrimaryDevice)
                    {
                        dList.Add(d);
                    }
                }
                return dList;
            }
    
            public static Screen GetScreen(string deviceName)
            {
                List<Screen> screenList = GetAllScreen();
                return screenList.Where(p => p.ScreenDevice.DeviceName == deviceName).FirstOrDefault();
            }
    
            private static void SwitchPrimaryScreen(Screen newPrimary, Screen oldPrimary)
            {
                MoveOldPrimary(newPrimary, oldPrimary);
                MoveNewPrimary(newPrimary, oldPrimary);
                CommitChange(newPrimary, oldPrimary);
            }
    
            private static void MoveOldPrimary(Screen newPrimary, Screen oldPrimary)
            {
                WinApi.DEVMODE ndm3 = NewDevMode();
                ndm3.dmFields = WinApi.DEVMODE_Flags.DM_POSITION;
                ndm3.dmPosition.x = (int)newPrimary.DeviceMode.dmPelsWidth; 
                ndm3.dmPosition.y = 0;
    
                WinApi.User_32.ChangeDisplaySettingsEx(oldPrimary.ScreenDevice.DeviceName, ref ndm3, (IntPtr)null, (int)WinApi.DeviceFlags.CDS_UPDATEREGISTRY | (int)WinApi.DeviceFlags.CDS_NORESET, IntPtr.Zero);
    
            }
    
            private static void MoveNewPrimary(Screen newPrimary, Screen oldPrimary)
            {
                WinApi.DEVMODE ndm4 = NewDevMode();
                ndm4.dmFields = WinApi.DEVMODE_Flags.DM_POSITION;
                ndm4.dmPosition.x = 0;
                ndm4.dmPosition.y = 0;
                WinApi.User_32.ChangeDisplaySettingsEx(newPrimary.ScreenDevice.DeviceName, ref ndm4, (IntPtr)null, (int)WinApi.DeviceFlags.CDS_SET_PRIMARY | (int)WinApi.DeviceFlags.CDS_UPDATEREGISTRY | (int)WinApi.DeviceFlags.CDS_NORESET, IntPtr.Zero);
            }
    
            private static void CommitChange(Screen newPrimary, Screen oldPrimary)
            {
                WinApi.DEVMODE ndm5 = NewDevMode();
                WinApi.User_32.ChangeDisplaySettingsEx(oldPrimary.ScreenDevice.DeviceName, ref ndm5, (IntPtr)null, (int)WinApi.DeviceFlags.CDS_UPDATEREGISTRY, (IntPtr)null);
    
                WinApi.DEVMODE ndm6 = NewDevMode();
                WinApi.User_32.ChangeDisplaySettingsEx(newPrimary.ScreenDevice.DeviceName, ref ndm6, (IntPtr)null, (int)WinApi.DeviceFlags.CDS_SET_PRIMARY | (int)WinApi.DeviceFlags.CDS_UPDATEREGISTRY, IntPtr.Zero);
            }
    
    
            private static WinApi.DEVMODE NewDevMode()
            {
                WinApi.DEVMODE dm = new WinApi.DEVMODE();
                dm.dmDeviceName = new String(new char[31]);
                dm.dmFormName = new String(new char[31]);
                dm.dmSize = (ushort)Marshal.SizeOf(dm);
                return dm;
            }
        }
  • 相关阅读:
    APIO2018 题解
    【THUWC2017】在美妙的数学王国中畅游(bzoj5020)
    【bzoj3270】博物馆
    【库存】NOI笔试习题集
    装饰器
    异常
    类的详解
    函数
    流程控制
    运算符
  • 原文地址:https://www.cnblogs.com/coolkiss/p/3328854.html
Copyright © 2011-2022 走看看