我正在尝试使用Windows API来设置主监视器.它似乎不起作用 - 我的屏幕只是轻弹而没有任何反应.
public const int DM_ORIENTATION = 0x00000001; public const int DM_PAPERSIZE = 0x00000002; public const int DM_PAPERLENGTH = 0x00000004; public const int DM_PAPERWIDTH = 0x00000008; public const int DM_SCALE = 0x00000010; public const int DM_POSITION = 0x00000020; public const int DM_NUP = 0x00000040; public const int DM_DISPLAYORIENTATION = 0x00000080; public const int DM_COPIES = 0x00000100; public const int DM_DEFAULTSOURCE = 0x00000200; public const int DM_PRINTQUALITY = 0x00000400; public const int DM_COLOR = 0x00000800; public const int DM_DUPLEX = 0x00001000; public const int DM_YRESOLUTION = 0x00002000; public const int DM_TTOPTION = 0x00004000; public const int DM_COLLATE = 0x00008000; public const int DM_FORMNAME = 0x00010000; public const int DM_LOGPIXELS = 0x00020000; public const int DM_BITSPERPEL = 0x00040000; public const int DM_PELSWIDTH = 0x00080000; public const int DM_PELSHEIGHT = 0x00100000; public const int DM_DISPLAYFLAGS = 0x00200000; public const int DM_DISPLAYFREQUENCY = 0x00400000; public const int DM_ICMMETHOD = 0x00800000; public const int DM_ICMINTENT = 0x01000000; public const int DM_MEDIATYPE = 0x02000000; public const int DM_DITHERTYPE = 0x04000000; public const int DM_PANNINGWIDTH = 0x08000000; public const int DM_PANNINGHEIGHT = 0x10000000; public const int DM_DISPLAYFIXEDOUTPUT = 0x20000000; public const int ENUM_CURRENT_SETTINGS = -1; public const int CDS_UPDATEREGISTRY = 0x01; public const int CDS_TEST = 0x02; public const int CDS_SET_PRIMARY = 0x00000010; public const long DISP_CHANGE_SUCCESSFUL = 0; public const long DISP_CHANGE_RESTART = 1; public const long DISP_CHANGE_FAILED = -1; public const long DISP_CHANGE_BADMODE = -2; public const long DISP_CHANGE_NOTUPDATED = -3; public const long DISP_CHANGE_BADFLAGS = -4; public const long DISP_CHANGE_BADPARAM = -5; public const long DISP_CHANGE_BADDUALVIEW = -6; public static void SetPrimary(Screen screen) { DISPLAY_DEVICE d = new DISPLAY_DEVICE(); DEVMODE dm = new DEVMODE(); d.cb = Marshal.SizeOf(d); uint deviceID = 1; User_32.EnumDisplayDevices(null, deviceID, ref d, 0); // User_32.EnumDisplaySettings(d.DeviceName, 0, ref dm); dm.dmPelsWidth = 2560; dm.dmPelsHeight = 1600; dm.dmPositionX = screen.Bounds.Right; dm.dmFields = DM_POSITION | DM_PELSWIDTH | DM_PELSHEIGHT; User_32.ChangeDisplaySettingsEx(d.DeviceName, ref dm, IntPtr.Zero, CDS_SET_PRIMARY, IntPtr.Zero); }
我这样称呼方法:
SetPrimary(Screen.AllScreens[1])
有任何想法吗?
以下是基于ADBailey解决方案的完整代码:
public class MonitorChanger { public static void SetAsPrimaryMonitor(uint id) { var device = new DISPLAY_DEVICE(); var deviceMode = new DEVMODE(); device.cb = Marshal.SizeOf(device); NativeMethods.EnumDisplayDevices(null, id, ref device, 0); NativeMethods.EnumDisplaySettings(device.DeviceName, -1, ref deviceMode); var offsetx = deviceMode.dmPosition.x; var offsety = deviceMode.dmPosition.y; deviceMode.dmPosition.x = 0; deviceMode.dmPosition.y = 0; NativeMethods.ChangeDisplaySettingsEx( device.DeviceName, ref deviceMode, (IntPtr)null, (ChangeDisplaySettingsFlags.CDS_SET_PRIMARY | ChangeDisplaySettingsFlags.CDS_UPDATEREGISTRY | ChangeDisplaySettingsFlags.CDS_NORESET), IntPtr.Zero); device = new DISPLAY_DEVICE(); device.cb = Marshal.SizeOf(device); // Update remaining devices for (uint otherid = 0; NativeMethods.EnumDisplayDevices(null, otherid, ref device, 0); otherid++) { if (device.StateFlags.HasFlag(DisplayDeviceStateFlags.AttachedToDesktop) && otherid != id) { device.cb = Marshal.SizeOf(device); var otherDeviceMode = new DEVMODE(); NativeMethods.EnumDisplaySettings(device.DeviceName, -1, ref otherDeviceMode); otherDeviceMode.dmPosition.x -= offsetx; otherDeviceMode.dmPosition.y -= offsety; NativeMethods.ChangeDisplaySettingsEx( device.DeviceName, ref otherDeviceMode, (IntPtr)null, (ChangeDisplaySettingsFlags.CDS_UPDATEREGISTRY | ChangeDisplaySettingsFlags.CDS_NORESET), IntPtr.Zero); } device.cb = Marshal.SizeOf(device); } // Apply settings NativeMethods.ChangeDisplaySettingsEx(null, IntPtr.Zero, (IntPtr)null, ChangeDisplaySettingsFlags.CDS_NONE, (IntPtr)null); } } [StructLayout(LayoutKind.Explicit, CharSet = CharSet.Ansi)] public struct DEVMODE { public const int CCHDEVICENAME = 32; public const int CCHFORMNAME = 32; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = CCHDEVICENAME)] [System.Runtime.InteropServices.FieldOffset(0)] public string dmDeviceName; [System.Runtime.InteropServices.FieldOffset(32)] public Int16 dmSpecVersion; [System.Runtime.InteropServices.FieldOffset(34)] public Int16 dmDriverVersion; [System.Runtime.InteropServices.FieldOffset(36)] public Int16 dmSize; [System.Runtime.InteropServices.FieldOffset(38)] public Int16 dmDriverExtra; [System.Runtime.InteropServices.FieldOffset(40)] public UInt32 dmFields; [System.Runtime.InteropServices.FieldOffset(44)] Int16 dmOrientation; [System.Runtime.InteropServices.FieldOffset(46)] Int16 dmPaperSize; [System.Runtime.InteropServices.FieldOffset(48)] Int16 dmPaperLength; [System.Runtime.InteropServices.FieldOffset(50)] Int16 dmPaperWidth; [System.Runtime.InteropServices.FieldOffset(52)] Int16 dmScale; [System.Runtime.InteropServices.FieldOffset(54)] Int16 dmCopies; [System.Runtime.InteropServices.FieldOffset(56)] Int16 dmDefaultSource; [System.Runtime.InteropServices.FieldOffset(58)] Int16 dmPrintQuality; [System.Runtime.InteropServices.FieldOffset(44)] public POINTL dmPosition; [System.Runtime.InteropServices.FieldOffset(52)] public Int32 dmDisplayOrientation; [System.Runtime.InteropServices.FieldOffset(56)] public Int32 dmDisplayFixedOutput; [System.Runtime.InteropServices.FieldOffset(60)] public short dmColor; // See note below! [System.Runtime.InteropServices.FieldOffset(62)] public short dmDuplex; // See note below! [System.Runtime.InteropServices.FieldOffset(64)] public short dmYResolution; [System.Runtime.InteropServices.FieldOffset(66)] public short dmTTOption; [System.Runtime.InteropServices.FieldOffset(68)] public short dmCollate; // See note below! [System.Runtime.InteropServices.FieldOffset(72)] [MarshalAs(UnmanagedType.ByValTStr, SizeConst = CCHFORMNAME)] public string dmFormName; [System.Runtime.InteropServices.FieldOffset(102)] public Int16 dmLogPixels; [System.Runtime.InteropServices.FieldOffset(104)] public Int32 dmBitsPerPel; [System.Runtime.InteropServices.FieldOffset(108)] public Int32 dmPelsWidth; [System.Runtime.InteropServices.FieldOffset(112)] public Int32 dmPelsHeight; [System.Runtime.InteropServices.FieldOffset(116)] public Int32 dmDisplayFlags; [System.Runtime.InteropServices.FieldOffset(116)] public Int32 dmNup; [System.Runtime.InteropServices.FieldOffset(120)] public Int32 dmDisplayFrequency; } public enum DISP_CHANGE : int { Successful = 0, Restart = 1, Failed = -1, BadMode = -2, NotUpdated = -3, BadFlags = -4, BadParam = -5, BadDualView = -6 } [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; } [Flags()] public enum DisplayDeviceStateFlags : int { ///The device is part of the desktop. AttachedToDesktop = 0x1, MultiDriver = 0x2, ///The device is part of the desktop. PrimaryDevice = 0x4, ///Represents a pseudo device used to mirror application drawing for remoting or other purposes. MirroringDriver = 0x8, ///The device is VGA compatible. VGACompatible = 0x10, ///The device is removable; it cannot be the primary display. Removable = 0x20, ///The device has more display modes than its output devices support. ModesPruned = 0x8000000, Remote = 0x4000000, Disconnect = 0x2000000, } [Flags()] public enum ChangeDisplaySettingsFlags : uint { CDS_NONE = 0, CDS_UPDATEREGISTRY = 0x00000001, CDS_TEST = 0x00000002, CDS_FULLSCREEN = 0x00000004, CDS_GLOBAL = 0x00000008, CDS_SET_PRIMARY = 0x00000010, CDS_VIDEOPARAMETERS = 0x00000020, CDS_ENABLE_UNSAFE_MODES = 0x00000100, CDS_DISABLE_UNSAFE_MODES = 0x00000200, CDS_RESET = 0x40000000, CDS_RESET_EX = 0x20000000, CDS_NORESET = 0x10000000 } public class NativeMethods { [DllImport("user32.dll")] public static extern DISP_CHANGE ChangeDisplaySettingsEx(string lpszDeviceName, ref DEVMODE lpDevMode, IntPtr hwnd, ChangeDisplaySettingsFlags dwflags, IntPtr lParam); [DllImport("user32.dll")] // A signature for ChangeDisplaySettingsEx with a DEVMODE struct as the second parameter won't allow you to pass in IntPtr.Zero, so create an overload public static extern DISP_CHANGE ChangeDisplaySettingsEx(string lpszDeviceName, IntPtr lpDevMode, IntPtr hwnd, ChangeDisplaySettingsFlags dwflags, IntPtr lParam); [DllImport("user32.dll")] public static extern bool EnumDisplayDevices(string lpDevice, uint iDevNum, ref DISPLAY_DEVICE lpDisplayDevice, uint dwFlags); [DllImport("user32.dll")] public static extern bool EnumDisplaySettings(string deviceName, int modeNum, ref DEVMODE devMode); } [StructLayout(LayoutKind.Sequential)] public struct POINTL { public int x; public int y; }