您的位置:首页 > 编程语言 > C#

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

2013-09-27 19:05 260 查看
原文 http://www.cnblogs.com/coolkiss/archive/2013/09/18/3328854.html

经过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;
}
}


内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐