c# 多显示器设置主屏幕(Set primary screen for multiple monitors)

原文: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;
        }
    }

原文地址:https://www.cnblogs.com/lonelyxmas/p/11106182.html

时间: 2024-10-08 09:41:24

c# 多显示器设置主屏幕(Set primary screen for multiple monitors)的相关文章

Linux系统显示器设置

Linux系统通过xrandr命令设置系统屏幕 1.查看当前屏幕信息xrandr 2.设置主屏幕xrandr --output VGA1 --auto --primaryxrandr --output DP2 --auto --primary黑体部分具体值,需要看第一步显示什么 3.设置扩展屏幕xrandr --output DP2 --right-of VGA1 --auto黑体部分具体值,需要看第一步显示什么 4.设置复制屏幕xrandr --output DP2 --same-as VGA

在CentOS 7 / Gnome 3 双屏时设置主屏

在Windows中设置扩展显示器为主屏的方式非常清楚,但在Linux中就不是那么明显了,下面介绍如何完成这个设置 ---------------------------------------------------------------------------------------------------------------------- 1. 在设置中,打开“显示”的设置 在这个界面,你可以看到你的两个屏幕,并可以设置其相对位置,但是设置后发现并不知道在哪里设置主屏,如图1 2. 在

C#操作电脑多显示器设置

电脑多显示器设置 第一种方式 通过使用api函数SetDisplayConfig来设置.这种方式在某些电脑中设置有几率会导致电脑黑屏 使用代码如下: private const uint SDC_APPLY = 0x00000080; private const uint SDC_TOPOLOGY_INTERNAL = 0x00000001; private const uint SDC_TOPOLOGY_CLONE = 0x00000002; private const uint SDC_TO

PowerDesigner-VBSrcipt-自动设置主键,外键名等(SQL Server)

在PowerDesigner中的设计SQL Server 数据表时,要求通过vbScript脚本实现下面的功能: 主键:pk_TableName 外键:fk_TableName_ForeignKeyColumnList 当字段作为主键,而且类型为smallint,int,bigint,那么要设置Identity =true. 当字段作为主键,而且类型为uniqueidentifier,那么要设置默认值为newid(),而且设置扩展属性rowguidcol. Option Explicit Val

Hsqldb中设置主键,并让主键自增

CREATE TABLE userinfo ( Id INTEGER GENERATED BY DEFAULT AS IDENTITY, Name varchar(100) NOT NULL, Department varchar(100) NOT NULL, Status varchar(100) DEFAULT NULL, Email varchar(200) NOT NULL, PRIMARY KEY (Id)) Hsqldb中设置主键,并让主键自增,布布扣,bubuko.com

oracle中如何设置主键并且让其自动增长

由于oracle中是没有自动增长的的,需要自己去进行写触发器等方式去进行设置: 找了一下他人写的,有两种方法可以设置主键,一种是自增长主键,另一种就是生成唯一序列. 一.自增长主键 我创建一个用户的信息表 -- Create tablecreate table USERINFO( USERNO NUMBER not null, USERNAME NVARCHAR2(20), USERPWD NVARCHAR2(20))tablespace MYPRODUCT pctfree 10 initran

SQL语句建表、设置主键、外键、check、default、unique约束

· 什么是数据库? 存放数据的仓库. · 数据库和数据结构有什么区别? 数据结构要解决在内存中操作数据的问题,数据库要解决在硬盘中操作数据的问题.数据结构研究一些抽象数据模型(ADT)和以及定义在该模型上的一些操作,数据库是由表.关系.操作组成. · 什么是主键? 主键用来标识记录的唯一性. · 什么是外键? 外键用来标识表与表之间的联系. · 什么是check约束? check约束限制了输入值的范围. · 什么是default约束? 给某个属性一个默认值. · 什么是unique约束? 限制某

数据库基础(子查询、设置主键外键)

子查询,又叫做嵌套查询. 将一个查询语句做为一个结果集供其他SQL语句使用,就像使用普通的表一样,被当作结果集的查询语句被称为子查询. 子查询有两种类型: 一种是只返回一个单值的子查询,这时它可以用在一个单值可以使用的地方,这时子查询可以看作是一个拥有返回值的函数: 另外一种是返回一列值的子查询,这时子查询可以看作是一个在内存中临时存在的数据表. 子查询示例: 练习一: 练习二: 练习三: 分页查询语句示例: 查看总共可以分为多少页: 主键        数据库主键是指表中一个列或列的组合,其值

iOS中为网站添加图标到主屏幕以及增加启动画面

虽然没有能力开发Native App,但还是可以利用iOS中Safari浏览器的特性小小的折腾一下,做一个伪Web App满足下小小的虚荣心的. 既然是在iOS中的Safari折腾的,那么代码中利用到的也基本上都是Safari的私有属性. 添加图标到主屏幕是Web App的第一步: <link rel="apple-touch-icon-precomposed" sizes="57x57" href="icon-57.png"> &l