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;

        }

    }

 

你可能感兴趣的:(primary)