2010-10-14 36 views
5

Tôi đang cố gắng tạo ứng dụng để tách màn hình phụ khỏi hộp Windows (câu chuyện dài).Ứng dụng C++ để tách màn hình phụ

Đây là của Microsoft mẫu mã mà tôi sử dụng như một cơ sở: http://support.microsoft.com/kb/308216/en-us

Đây là mã của tôi:

#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; 
} 

Tuy nhiên, khi tôi biên dịch và chạy nó tất cả tôi nhận được màn hình nhấp nháy như thể nó đang thay đổi độ phân giải nhưng nó không thực sự làm bất cứ điều gì có ý nghĩa (tôi nhận thấy con chuột di chuyển ... nhưng khác hơn là không có gì).

Có lẽ người khác đã tạo tiện ích để thực hiện chức năng chính xác này, chức năng này sẽ hoạt động tốt nếu nó có thể được gọi từ dòng lệnh.

Suy nghĩ?

Trả lời

0

Đoạn mã ở trên thực sự làm gián đoạn thiết bị hiển thị phụ, không giám sát. Thiết bị hiển thị giống nhau có thể chứa nhiều màn hình. Tôi chưa thành công với vấn đề này

2

Bạn có thể sử dụng SetDisplayConfig để thực hiện việc này trong các cửa sổ 7. Ví dụ bên dưới tắt tất cả màn hình phụ.

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)); 

Đối với một biết thêm chút về chức năng sử dụng: http://msdn.microsoft.com/en-us/library/ff539596%28v=VS.85%29.aspx

1

Tôi biết đây là một cách chủ đề cũ nhưng tôi bắt gặp nó trong khi nghiên cứu vấn đề của riêng tôi: Looking for a phương pháp để hiển thị một phi máy tính để bàn tương tác trên một thiết bị tách rời màn hình phụ trong khi console session (và do đó WinSta0) bị khóa trên Windows 7.

trả lời cho câu hỏi ban đầu:

Khi tách một thiết bị hiển thị:

DEVMODE.dmPelsWidth = 0; 
DEVMODE.dmPelsHeight = 0; 
DEVMODE.dmFields = DM_POSITION | DM_PELSWIDTH | DM_PELSHEIGHT; 
ChangeDisplaySettingsEx(....  

Nếu bạn đang tách một màn hình, cuộc gọi thứ hai để ChangeDisplaySettings(Ex) là không cần thiết nếu bạn chỉ định CDS_RESET cùng với CDS_UPDATEREGISTRY trong cuộc gọi ban đầu. Tuy nhiên, nếu bạn đang gắn màn hình, lệnh gọi thứ hai tới số ChangeDisplaySettings có vẻ như được yêu cầu (hoặc ít nhất, tôi chưa tìm ra cách nào để thực hiện).

Tôi cung cấp mã C# hoạt động bên dưới. Dưới đây là một kịch bản PowerShell để sử dụng với nó

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!' } 
} 
+0

Tôi chắc chắn sẽ quan tâm đến nhìn thấy những gì C# mã bạn đã đưa ra. –

+0

Nathan, tôi đã phải loại bỏ rất nhiều các ý kiến ​​ra nhưng tôi đã nhận nó được đăng ở đây ở phía dưới. Nó được viết để sử dụng với PowerShell. Tôi đưa vào bài đăng này một ví dụ nhỏ. Thưởng thức. – Frobozz

1
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; 
    } 
} 
} 
+0

sau khi sao chép dán tất cả các thứ 'pinvoke' lại với nhau và thất bại khủng khiếp, tôi lấy mã của bạn. 'DetachDisplayDevice' đang hoạt động hoàn hảo nhưng tôi không thể nhận được' AttachDisplayDevice' để làm việc. 'ChangeDisplaySettingsEx' đang trả về' Win32.DISP_CHANGE.FAILED' cho tôi mọi lúc mọi khi tôi đặt cho 'DEVMODE'. Bạn có gặp phải vấn đề này không? Bạn có sửa chữa không? – MadddinTribleD

Các vấn đề liên quan