我正在尝试创建一个从Windows框中分离辅助监视器的应用程序(长篇故事)。
以下是我用作基础的Microsoft示例代码: http://support.microsoft.com/kb/308216/en-us
这是我的代码:
#include <iostream>
#include <windows.h>
void DetachDisplay()
{
BOOL FoundSecondaryDisp = FALSE;
DWORD DispNum = 0;
DISPLAY_DEVICE DisplayDevice;
LONG Result;
TCHAR szTemp[200];
int i = 0;
DEVMODE defaultMode;
// initialize DisplayDevice
ZeroMemory(&DisplayDevice, sizeof(DisplayDevice));
DisplayDevice.cb = sizeof(DisplayDevice);
// get all display devices
while (EnumDisplayDevices(NULL, DispNum, &DisplayDevice, 0))
{
ZeroMemory(&defaultMode, sizeof(DEVMODE));
defaultMode.dmSize = sizeof(DEVMODE);
if ( !EnumDisplaySettings((LPSTR)DisplayDevice.DeviceName, ENUM_REGISTRY_SETTINGS, &defaultMode) )
OutputDebugString("Store default failed\n");
if ((DisplayDevice.StateFlags & DISPLAY_DEVICE_ATTACHED_TO_DESKTOP) &&
!(DisplayDevice.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE))
{
DEVMODE DevMode;
ZeroMemory(&DevMode, sizeof(DevMode));
DevMode.dmSize = sizeof(DevMode);
DevMode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL | DM_POSITION
| DM_DISPLAYFREQUENCY | DM_DISPLAYFLAGS ;
Result = ChangeDisplaySettingsEx((LPSTR)DisplayDevice.DeviceName, &DevMode, NULL, CDS_UPDATEREGISTRY, NULL);
//Result = ChangeDisplaySettingsEx((LPSTR)DisplayDevice.DeviceName, &DevMode, NULL, CDS_UPDATEREGISTRY, NULL);
ChangeDisplaySettingsEx (NULL, NULL, NULL, 0, NULL);
//The code below shows how to re-attach the secondary displays to the desktop
//ChangeDisplaySettingsEx((LPSTR)DisplayDevice.DeviceName, &defaultMode, NULL, CDS_UPDATEREGISTRY, NULL);
//ChangeDisplaySettingsEx((LPSTR)DisplayDevice.DeviceName, &defaultMode, NULL, CDS_UPDATEREGISTRY, NULL);
}
// Reinit DisplayDevice just to be extra clean
ZeroMemory(&DisplayDevice, sizeof(DisplayDevice));
DisplayDevice.cb = sizeof(DisplayDevice);
DispNum++;
} // end while for all display devices
}
int main()
{
DetachDisplay();
return 0;
}
然而,当我编译并运行它时,我得到的是闪烁的屏幕,好像它正在改变分辨率,但它实际上没有做任何有意义的事情(我注意到鼠标移动......但除此之外什么都没有)
也许其他人已经创建了一个实用程序来执行这个确切的功能,如果可以从命令行调用它,效果会一样好。
思想?
答案 0 :(得分:2)
您可以使用 SetDisplayConfig 在Windows 7中执行此操作。以下示例将禁用所有辅助屏幕。
UINT32 NumPathArrayElements = 0;
UINT32 NumModeInfoArrayElements = 0;
LONG error = GetDisplayConfigBufferSizes(QDC_ONLY_ACTIVE_PATHS,&NumPathArrayElements,&NumModeInfoArrayElements);
std::vector<DISPLAYCONFIG_PATH_INFO> PathInfoArray(NumPathArrayElements);
std::vector<DISPLAYCONFIG_MODE_INFO> ModeInfoArray(NumModeInfoArrayElements);
error = QueryDisplayConfig(QDC_ONLY_ACTIVE_PATHS,&NumPathArrayElements, &PathInfoArray[0],&NumModeInfoArrayElements, &ModeInfoArray[0],NULL);
for(unsigned int i=0;i<PathInfoArray.size();++i){
if(PathInfoArray[i].sourceInfo.modeInfoIdx<ModeInfoArray.size()){
int modeIndex=PathInfoArray[i].sourceInfo.modeInfoIdx;
_POINTL pos=ModeInfoArray[modeIndex].sourceMode.position;
if(pos.x!=0 || pos.y!=0){
PathInfoArray[i].flags=0;
break;
}
}
}
error = SetDisplayConfig(NumPathArrayElements, &PathInfoArray[0],NumModeInfoArrayElements, &ModeInfoArray[0],(SDC_APPLY | SDC_ALLOW_CHANGES | SDC_USE_SUPPLIED_DISPLAY_CONFIG));
有关所用功能的更多信息:http://msdn.microsoft.com/en-us/library/ff539596%28v=VS.85%29.aspx
答案 1 :(得分:2)
using System;
using System.Runtime.InteropServices;
namespace MyNamespace
{
public class Win32
{
public struct POINTL
{
public Int32 x;
public Int32 y;
}
public struct RECT
{
public long left;
public long top;
public long right;
public long bottom;
}
[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;
}
[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 DmFlags 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;
}
[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
}
[StructLayout(LayoutKind.Sequential)]
public struct SECURITY_ATTRIBUTES
{
public int nLength;
public IntPtr lpSecurityDescriptor;
public int bInheritHandle;
}
[Flags]
public enum ACCESS_MASK : uint
{
DELETE = 0x00010000,
READ_CONTROL = 0x00020000,
WRITE_DAC = 0x00040000,
WRITE_OWNER = 0x00080000,
SYNCHRONIZE = 0x00100000,
STANDARD_RIGHTS_REQUIRED = 0x000F0000,
STANDARD_RIGHTS_READ = 0x00020000,
STANDARD_RIGHTS_WRITE = 0x00020000,
STANDARD_RIGHTS_EXECUTE = 0x00020000,
STANDARD_RIGHTS_ALL = 0x001F0000,
SPECIFIC_RIGHTS_ALL = 0x0000FFFF,
ACCESS_SYSTEM_SECURITY = 0x01000000,
MAXIMUM_ALLOWED = 0x02000000,
GENERIC_READ = 0x80000000,
GENERIC_WRITE = 0x40000000,
GENERIC_EXECUTE = 0x20000000,
GENERIC_ALL = 0x10000000,
DESKTOP_READOBJECTS = 0x00000001,
DESKTOP_CREATEWINDOW = 0x00000002,
DESKTOP_CREATEMENU = 0x00000004,
DESKTOP_HOOKCONTROL = 0x00000008,
DESKTOP_JOURNALRECORD = 0x00000010,
DESKTOP_JOURNALPLAYBACK = 0x00000020,
DESKTOP_ENUMERATE = 0x00000040,
DESKTOP_WRITEOBJECTS = 0x00000080,
DESKTOP_SWITCHDESKTOP = 0x00000100,
WINSTA_ENUMDESKTOPS = 0x00000001,
WINSTA_READATTRIBUTES = 0x00000002,
WINSTA_ACCESSCLIPBOARD = 0x00000004,
WINSTA_CREATEDESKTOP = 0x00000008,
WINSTA_WRITEATTRIBUTES = 0x00000010,
WINSTA_ACCESSGLOBALATOMS = 0x00000020,
WINSTA_EXITWINDOWS = 0x00000040,
WINSTA_ENUMERATE = 0x00000100,
WINSTA_READSCREEN = 0x00000200,
WINSTA_ALL_ACCESS = 0x0000037F
}
[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
}
[Flags()]
public enum DISP_CHANGE : int
{
SUCCESSFUL = 0,
RESTART = 1,
FAILED = -1,
BADMODE = -2,
NOTUPDATED = -3,
BADFLAGS = -4,
BADPARAM = -5,
BADDUALVIEW = -6
}
[Flags()]
public enum DmFlags : int
{
DM_ORIENTATION = 0x00000001,
DM_PAPERSIZE = 0x00000002,
DM_PAPERLENGTH = 0x00000004,
DM_PAPERWIDTH = 0x00000008,
DM_SCALE = 0x00000010,
DM_POSITION = 0x00000020,
DM_NUP = 0x00000040,
DM_DISPLAYORIENTATION = 0x00000080,
DM_COPIES = 0x00000100,
DM_DEFAULTSOURCE = 0x00000200,
DM_PRINTQUALITY = 0x00000400,
DM_COLOR = 0x00000800,
DM_DUPLEX = 0x00001000,
DM_YRESOLUTION = 0x00002000,
DM_TTOPTION = 0x00004000,
DM_COLLATE = 0x00008000,
DM_FORMNAME = 0x00010000,
DM_LOGPIXELS = 0x00020000,
DM_BITSPERPEL = 0x00040000,
DM_PELSWIDTH = 0x00080000,
DM_PELSHEIGHT = 0x00100000,
DM_DISPLAYFLAGS = 0x00200000,
DM_DISPLAYFREQUENCY = 0x00400000,
DM_ICMMETHOD = 0x00800000,
DM_ICMINTENT = 0x01000000,
DM_MEDIATYPE = 0x02000000,
DM_DITHERTYPE = 0x04000000,
DM_PANNINGWIDTH = 0x08000000,
DM_PANNINGHEIGHT = 0x10000000,
DM_DISPLAYFIXEDOUTPUT = 0x20000000
}
[DllImport("kernel32.dll")]
public static extern uint GetLastError();
[DllImport("user32.dll", EntryPoint = "CreateWindowStation", CharSet = CharSet.Unicode, SetLastError = true)]
public static extern IntPtr CreateWindowStation(
[MarshalAs(UnmanagedType.LPWStr)] string name,
[MarshalAs(UnmanagedType.U4)] uint dwFlags,
[MarshalAs(UnmanagedType.U4)] ACCESS_MASK desiredAccess,
[MarshalAs(UnmanagedType.LPStr)] ref SECURITY_ATTRIBUTES attributes
);
[DllImport("user32.dll", EntryPoint = "CreateWindowStation", CharSet = CharSet.Unicode, SetLastError = true)]
public static extern IntPtr CreateWindowStation(
[MarshalAs(UnmanagedType.LPWStr)] string name,
[MarshalAs(UnmanagedType.U4)] uint dwFlags,
[MarshalAs(UnmanagedType.U4)] ACCESS_MASK desiredAccess,
[MarshalAs(UnmanagedType.U4)] uint attributes
);
[DllImport("user32.dll", EntryPoint = "CreateDesktop", CharSet = CharSet.Unicode, SetLastError = true)]
public static extern IntPtr CreateDesktop(
[MarshalAs(UnmanagedType.LPWStr)] string desktopName,
[MarshalAs(UnmanagedType.LPWStr)] string device, // must be null.
[MarshalAs(UnmanagedType.LPWStr)] string deviceMode, // must be null,
[MarshalAs(UnmanagedType.U4)] int flags, // use 0
[MarshalAs(UnmanagedType.U4)] ACCESS_MASK accessMask,
[MarshalAs(UnmanagedType.LPStruct)] ref SECURITY_ATTRIBUTES attributes
);
[DllImport("user32.dll", EntryPoint = "CreateDesktop", CharSet = CharSet.Unicode, SetLastError = true)]
public static extern IntPtr CreateDesktop(
[MarshalAs(UnmanagedType.LPWStr)] string desktopName,
[MarshalAs(UnmanagedType.LPWStr)] string device, // must be null.
[MarshalAs(UnmanagedType.LPWStr)] string deviceMode, // must be null,
[MarshalAs(UnmanagedType.U4)] int flags, // use 0
[MarshalAs(UnmanagedType.U4)] ACCESS_MASK accessMask,
[MarshalAs(UnmanagedType.U4)] uint attributes
);
[DllImport("user32.dll", EntryPoint = "CloseDesktop", CharSet = CharSet.Unicode, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool CloseDesktop(IntPtr handle);
[DllImport("user32.dll")]
public static extern IntPtr OpenWindowStation(
[MarshalAs(UnmanagedType.LPWStr)]string name,
[MarshalAs(UnmanagedType.Bool)] bool fInherit,
[MarshalAs(UnmanagedType.U4)] uint desiredAccess
);
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool SetProcessWindowStation(IntPtr hWinSta);
[DllImport("user32.dll")]
public static extern IntPtr GetProcessWindowStation();
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool CloseWindowStation(IntPtr hWinSta);
[DllImport("user32.dll")]
public static extern bool EnumDisplayDevices(string lpDevice, uint iDevNum, ref DISPLAY_DEVICE lpDisplayDevice, uint dwFlags);
[DllImport("user32.dll")]
public static extern int EnumDisplaySettingsEx(string lpszDeviceName, int iModeNum, ref DEVMODE lpDevMode, uint dwFlags);
[DllImport("user32.dll")]
public static extern int ChangeDisplaySettingsEx(
string lpszDeviceName,
ref DEVMODE lpDevMode,
IntPtr hwnd,
ChangeDisplaySettingsFlags dwflags,
IntPtr lParam);
[DllImport("user32.dll")]
public static extern int ChangeDisplaySettingsEx(
string lpszDeviceName,
IntPtr lpDevMode,
IntPtr hwnd,
ChangeDisplaySettingsFlags dwflags,
IntPtr lParam);
[DllImport("user32.dll")]
public static extern IntPtr GetDC(IntPtr hWnd);
[DllImport("user32.dll")]
public static extern bool ReleaseDC(IntPtr hWnd, IntPtr hDC);
[DllImport("user32.dll")]
public static extern int DrawText(IntPtr hDC, string lpString, int nCount, ref RECT lpRect, uint uFormat);
[DllImport("user32.dll")]
static extern bool GetClientRect(IntPtr hWnd, out RECT lpRect);
public const int ENUM_CURRENT_SETTINGS = -1;
public const int ENUM_REGISTRY_SETTINGS = -2;
public const int CWF_CREATE_ONLY = 1;
public const int DF_ALLOWOTHERACCOUNTHOOK = 1;
public const int DT_TOP = 0x00000000;
public const int DT_LEFT = 0x00000000;
public const int DT_CENTER = 0x00000001;
public const int DT_RIGHT = 0x00000002;
public const int DT_VCENTER = 0x00000004;
public const int DT_BOTTOM = 0x00000008;
public const int DT_WORDBREAK = 0x00000010;
public const int DT_SINGLELINE = 0x00000020;
public const int DT_EXPANDTABS = 0x00000040;
public const int DT_TABSTOP = 0x00000080;
public const int DT_NOCLIP = 0x00000100;
public const int DT_EXTERNALLEADING = 0x00000200;
public const int DT_CALCRECT = 0x00000400;
public const int DT_NOPREFIX = 0x00000800;
public const int DT_INTERNAL = 0x00001000;
}
public class Gdi32
{
[Flags()]
public enum DeviceCap : int
{
DRIVERVERSION = 0,
TECHNOLOGY = 2,
HORZSIZE = 4,
VERTSIZE = 6,
HORZRES = 8,
VERTRES = 10,
BITSPIXEL = 12,
PLANES = 14,
NUMBRUSHES = 16,
NUMPENS = 18,
NUMMARKERS = 20,
NUMFONTS = 22,
NUMCOLORS = 24,
PDEVICESIZE = 26,
CURVECAPS = 28,
LINECAPS = 30,
POLYGONALCAPS = 32,
TEXTCAPS = 34,
CLIPCAPS = 36,
RASTERCAPS = 38,
ASPECTX = 40,
ASPECTY = 42,
ASPECTXY = 44,
SHADEBLENDCAPS = 45,
LOGPIXELSX = 88,
LOGPIXELSY = 90,
SIZEPALETTE = 104,
NUMRESERVED = 106,
COLORRES = 108,
PHYSICALWIDTH = 110,
PHYSICALHEIGHT = 111,
PHYSICALOFFSETX = 112,
PHYSICALOFFSETY = 113,
SCALINGFACTORX = 114,
SCALINGFACTORY = 115,
VREFRESH = 116,
DESKTOPVERTRES = 117,
DESKTOPHORZRES = 118,
BLTALIGNMENT = 119
}
[DllImport("gdi32.dll")]
public static extern int GetDeviceCaps(IntPtr hdc, int nIndex);
[DllImport("gdi32.dll")]
public static extern IntPtr CreateDC(string lpszDriver, string lpszDevice, string lpszOutput, IntPtr lpInitData);
[DllImport("gdi32.dll", EntryPoint = "DeleteDC")]
public static extern bool DeleteDC([In] IntPtr hdc);
[DllImport("gdi32.dll")]
public static extern int SetTextColor(IntPtr hdc, int crColor);
[DllImport("gdi32.dll")]
public static extern int SetBkColor(IntPtr hdc, int crColor);
}
public class Display
{
public static void EnumDisplayDevices()
{
uint deviceID = 0;
Win32.DISPLAY_DEVICE d = new Win32.DISPLAY_DEVICE();
d.cb = Marshal.SizeOf(d);
Win32.DEVMODE dm = GetDevMode();
while (Win32.EnumDisplayDevices(null, deviceID, ref d, 1))
{
// Print Device Information
Console.WriteLine("\nDeviceID: {5} \nDeviceName: {0} \nDeviceString: {1}\nDeviceID (GUID): {2}\nDeviceKey {3}\nStateFlags {4}\n",
d.DeviceName, d.DeviceString, d.DeviceID, d.DeviceKey, d.StateFlags, deviceID);
deviceID++;
}
}
private static Win32.DEVMODE GetDevMode()
{
Win32.DEVMODE dm = new Win32.DEVMODE();
dm.dmDeviceName = new String(new char[32]);
dm.dmFormName = new String(new char[32]);
dm.dmSize = (short)Marshal.SizeOf(dm);
return dm;
}
public static bool DetachDisplayDevice(uint deviceID)
{
bool rval = false;
Win32.DEVMODE dm = GetDevMode();
Win32.DISPLAY_DEVICE d = new Win32.DISPLAY_DEVICE();
d.cb = Marshal.SizeOf(d);
// Get the display device
if (!Win32.EnumDisplayDevices(null, deviceID, ref d, 0))
{
Console.WriteLine("Device not found!");
return false;
}
// Test that the display is actually attached to the desktop - bail if it is not
if ((d.StateFlags & Win32.DisplayDeviceStateFlags.AttachedToDesktop) == 0)
{
Console.WriteLine("Display Device {0} is not attached to this desktop!", d.DeviceName);
return false;
}
// Get current device settings
if (0 == Win32.EnumDisplaySettingsEx(d.DeviceName, Win32.ENUM_CURRENT_SETTINGS, ref dm, 0))
{
Console.WriteLine("Settings for {0} could not be enumerated!", d.DeviceName);
return false;
}
// Prepare for detach
dm.dmPelsWidth = 0;
dm.dmPelsHeight = 0;
dm.dmFields = Win32.DmFlags.DM_POSITION | Win32.DmFlags.DM_PELSWIDTH | Win32.DmFlags.DM_PELSHEIGHT;
//dm.dmFields = (int) (DmFlags.DM_POSITION);
// Test the change
int iRet = Win32.ChangeDisplaySettingsEx(d.DeviceName, ref dm, IntPtr.Zero, Win32.ChangeDisplaySettingsFlags.CDS_TEST, IntPtr.Zero);
if (iRet == (int)Win32.DISP_CHANGE.FAILED)
{
Console.WriteLine("Unable To Process Your Request.");
return false;
}
// Now do it for real
iRet = Win32.ChangeDisplaySettingsEx(
d.DeviceName,
ref dm,
IntPtr.Zero,
Win32.ChangeDisplaySettingsFlags.CDS_UPDATEREGISTRY | Win32.ChangeDisplaySettingsFlags.CDS_RESET,
IntPtr.Zero
);
//Win32.ChangeDisplaySettingsEx((string) null, IntPtr.Zero, IntPtr.Zero, 0, IntPtr.Zero); // Not needed for detach with CDS_RESET set.
switch (iRet)
{
case (int)Win32.DISP_CHANGE.SUCCESSFUL:
{
Console.WriteLine("Detached display: {0} \n", d.DeviceName);
rval = true;
break;
}
case (int)Win32.DISP_CHANGE.RESTART:
{
Console.WriteLine("A reboot is required for the change to take affect.\n");
break;
}
default:
{
Console.WriteLine("Failed! Return value: {0}\n", iRet);
break;
}
}
return rval;
}
public static bool AttachDisplayDevice(uint deviceID)
{
bool rval = false;
Win32.DEVMODE dm = GetDevMode();
Win32.DISPLAY_DEVICE d = new Win32.DISPLAY_DEVICE();
d.cb = Marshal.SizeOf(d);
int nWidth;
IntPtr hdc;
// Get current device context width
hdc = Win32.GetDC(IntPtr.Zero);
nWidth = Gdi32.GetDeviceCaps(hdc, (int)Gdi32.DeviceCap.HORZRES);
Win32.ReleaseDC(IntPtr.Zero, hdc);
// Get the display device
if (!Win32.EnumDisplayDevices(null, deviceID, ref d, 0))
{
Console.WriteLine("Device not found!");
return false;
}
// Test that the display is NOT actually attached to the desktop - bail if it is
if ((d.StateFlags & Win32.DisplayDeviceStateFlags.AttachedToDesktop) != 0)
{
Console.WriteLine("Display Device {0} is already attached to this desktop!", d.DeviceName);
return false;
}
// Get current device settings
if (0 == Win32.EnumDisplaySettingsEx(d.DeviceName, Win32.ENUM_REGISTRY_SETTINGS, ref dm, 0))
{
Console.WriteLine("Settings for {0} could not be enumerated!", d.DeviceName);
return false;
}
// Prepare for attach
dm.dmPosition.x += nWidth;
dm.dmFields = Win32.DmFlags.DM_POSITION;
// Test the change
int iRet = Win32.ChangeDisplaySettingsEx(d.DeviceName, ref dm, IntPtr.Zero, Win32.ChangeDisplaySettingsFlags.CDS_TEST, IntPtr.Zero);
if (iRet == (int)Win32.DISP_CHANGE.FAILED)
{
Console.WriteLine("Unable To Process Your Request.");
return false;
}
// Now do it for real
iRet = Win32.ChangeDisplaySettingsEx(
d.DeviceName,
ref dm,
IntPtr.Zero,
Win32.ChangeDisplaySettingsFlags.CDS_UPDATEREGISTRY | Win32.ChangeDisplaySettingsFlags.CDS_NORESET,
IntPtr.Zero
);
Win32.ChangeDisplaySettingsEx((string)null, IntPtr.Zero, IntPtr.Zero, 0, IntPtr.Zero);
switch (iRet)
{
case (int)Win32.DISP_CHANGE.SUCCESSFUL:
{
Console.WriteLine("Attached display: {0} \n", d.DeviceName);
rval = true;
break;
}
case (int)Win32.DISP_CHANGE.RESTART:
{
Console.WriteLine("A reboot is required for the change to take affect.\n");
break;
}
default:
{
Console.WriteLine("Failed! Return value: {0}\n", iRet);
break;
}
}
return rval;
}
}
}
答案 2 :(得分:1)
我知道这是一个老式的线程,但我在研究自己的问题时遇到了它:寻找一种方法,在分离的辅助显示设备上显示非交互式桌面,同时控制台会话(因此WinSta0)被锁定在Windows 7上。
回答原始问题:
拆卸显示设备时:
DEVMODE.dmPelsWidth = 0;
DEVMODE.dmPelsHeight = 0;
DEVMODE.dmFields = DM_POSITION | DM_PELSWIDTH | DM_PELSHEIGHT;
ChangeDisplaySettingsEx(....
如果您要分离显示,如果您在原始呼叫中指定ChangeDisplaySettings(Ex)
和CDS_RESET
,则无需再次拨打CDS_UPDATEREGISTRY
。但是,如果您要附加一个显示器,则第二次调用ChangeDisplaySettings
似乎确实需要(或者,至少,我还没有找到解决方法)。
我在下面提供了工作C#代码。这是一个与它一起使用的PowerShell脚本
param(
[Parameter(Mandatory=$true, Position = 0)] [string]$Function,
[Parameter(Mandatory=$false, Position = 1)] [int]$DeviceID
)
clear-host
add-type -TypeDefinition (Get-Content -Path .\Display.cs | Out-String)
Switch ($Function) {
'Enum' {[MyNamespace.Display]::EnumDisplayDevices()}
'Detach' {[MyNamespace.Display]::DetachDisplayDevice($DeviceID)}
'Attach' {[MyNamespace.Display]::AttachDisplayDevice($DeviceID)}
Default { write-host 'There is no "' $Function '" function available!' }
}
答案 3 :(得分:0)
上面的代码段实际上会分离辅助显示设备,而不是监视器。相同的显示设备可能包含多个监视器。我还没有成功解决这个问题