using System; using System.Collections.Generic; using System.Linq; using System.Runtime.InteropServices; using System.Text; using System.Threading.Tasks; namespace DisplayMagicianShared.Windows { public enum WIN32STATUS { ERROR_SUCCESS = 0, ERROR_ACCESS_DENIED = 5, ERROR_NOT_SUPPORTED = 50, ERROR_GEN_FAILURE = 31, ERROR_INVALID_PARAMETER = 87, ERROR_INSUFFICIENT_BUFFER = 122, } public enum DISPLAYCONFIG_DEVICE_INFO_TYPE { DISPLAYCONFIG_DEVICE_INFO_GET_SOURCE_NAME = 1, DISPLAYCONFIG_DEVICE_INFO_GET_TARGET_NAME = 2, DISPLAYCONFIG_DEVICE_INFO_GET_TARGET_PREFERRED_MODE = 3, DISPLAYCONFIG_DEVICE_INFO_GET_ADAPTER_NAME = 4, DISPLAYCONFIG_DEVICE_INFO_SET_TARGET_PERSISTENCE = 5, DISPLAYCONFIG_DEVICE_INFO_GET_TARGET_BASE_TYPE = 6, DISPLAYCONFIG_DEVICE_INFO_GET_SUPPORT_VIRTUAL_RESOLUTION = 7, DISPLAYCONFIG_DEVICE_INFO_SET_SUPPORT_VIRTUAL_RESOLUTION = 8, DISPLAYCONFIG_DEVICE_INFO_GET_ADVANCED_COLOR_INFO = 9, DISPLAYCONFIG_DEVICE_INFO_SET_ADVANCED_COLOR_STATE = 10, DISPLAYCONFIG_DEVICE_INFO_GET_SDR_WHITE_LEVEL = 11, } public enum DISPLAYCONFIG_COLOR_ENCODING { DISPLAYCONFIG_COLOR_ENCODING_RGB = 0, DISPLAYCONFIG_COLOR_ENCODING_YCBCR444 = 1, DISPLAYCONFIG_COLOR_ENCODING_YCBCR422 = 2, DISPLAYCONFIG_COLOR_ENCODING_YCBCR420 = 3, DISPLAYCONFIG_COLOR_ENCODING_INTENSITY = 4, } public enum DISPLAYCONFIG_SCALING { DISPLAYCONFIG_SCALING_IDENTITY = 1, DISPLAYCONFIG_SCALING_CENTERED = 2, DISPLAYCONFIG_SCALING_STRETCHED = 3, DISPLAYCONFIG_SCALING_ASPECTRATIOCENTEREDMAX = 4, DISPLAYCONFIG_SCALING_CUSTOM = 5, DISPLAYCONFIG_SCALING_PREFERRED = 128, } public enum DISPLAYCONFIG_ROTATION { DISPLAYCONFIG_ROTATION_IDENTITY = 1, DISPLAYCONFIG_ROTATION_ROTATE90 = 2, DISPLAYCONFIG_ROTATION_ROTATE180 = 3, } public enum DISPLAYCONFIG_VIDEO_OUTPUT_TECHNOLOGY { DISPLAYCONFIG_OUTPUT_TECHNOLOGY_OTHER = -1, DISPLAYCONFIG_OUTPUT_TECHNOLOGY_HD15 = 0, DISPLAYCONFIG_OUTPUT_TECHNOLOGY_SVIDEO = 1, DISPLAYCONFIG_OUTPUT_TECHNOLOGY_COMPOSITE_VIDEO = 2, DISPLAYCONFIG_OUTPUT_TECHNOLOGY_COMPONENT_VIDEO = 3, DISPLAYCONFIG_OUTPUT_TECHNOLOGY_DVI = 4, DISPLAYCONFIG_OUTPUT_TECHNOLOGY_HDMI = 5, DISPLAYCONFIG_OUTPUT_TECHNOLOGY_LVDS = 6, DISPLAYCONFIG_OUTPUT_TECHNOLOGY_D_JPN = 8, DISPLAYCONFIG_OUTPUT_TECHNOLOGY_SDI = 9, DISPLAYCONFIG_OUTPUT_TECHNOLOGY_DISPLAYPORT_EXTERNAL = 10, DISPLAYCONFIG_OUTPUT_TECHNOLOGY_DISPLAYPORT_EMBEDDED = 11, DISPLAYCONFIG_OUTPUT_TECHNOLOGY_UDI_EXTERNAL = 12, DISPLAYCONFIG_OUTPUT_TECHNOLOGY_UDI_EMBEDDED = 13, DISPLAYCONFIG_OUTPUT_TECHNOLOGY_SDTVDONGLE = 14, DISPLAYCONFIG_OUTPUT_TECHNOLOGY_MIRACAST = 15, DISPLAYCONFIG_OUTPUT_TECHNOLOGY_INDIRECT_WIRED = 16, DISPLAYCONFIG_OUTPUT_TECHNOLOGY_INDIRECT_VIRTUAL = 17, DISPLAYCONFIG_OUTPUT_TECHNOLOGY_INTERNAL = unchecked((int)0x80000000), } public enum DISPLAYCONFIG_TOPOLOGY_ID { DISPLAYCONFIG_TOPOLOGY_INTERNAL = 0x00000001, DISPLAYCONFIG_TOPOLOGY_CLONE = 0x00000002, DISPLAYCONFIG_TOPOLOGY_EXTEND = 0x00000004, DISPLAYCONFIG_TOPOLOGY_EXTERNAL = 0x00000008, } public enum DISPLAYCONFIG_PATH { DISPLAYCONFIG_PATH_ACTIVE = 0x00000001, DISPLAYCONFIG_PATH_PREFERRED_UNSCALED = 0x00000004, DISPLAYCONFIG_PATH_SUPPORT_VIRTUAL_MODE = 0x00000008, } public enum DISPLAYCONFIG_SOURCE_FLAGS { DISPLAYCONFIG_SOURCE_IN_USE = 0x00000001, } public enum DISPLAYCONFIG_TARGET_FLAGS { DISPLAYCONFIG_TARGET_IN_USE = 0x00000001, DISPLAYCONFIG_TARGET_FORCIBLE = 0x00000002, DISPLAYCONFIG_TARGET_FORCED_AVAILABILITY_BOOT = 0x00000004, DISPLAYCONFIG_TARGET_FORCED_AVAILABILITY_PATH = 0x00000008, DISPLAYCONFIG_TARGET_FORCED_AVAILABILITY_SYSTEM = 0x00000010, DISPLAYCONFIG_TARGET_IS_HMD = 0x00000020, } public enum QDC { QDC_ALL_PATHS = 0x00000001, // Get all paths QDC_ONLY_ACTIVE_PATHS = 0x00000002, // Get only the active paths currently in use QDC_DATABASE_CURRENT = 0x00000004, // Get the current paths in the display database QDC_VIRTUAL_MODE_AWARE = 0x00000010, // Get the virtual mode aware paths QDC_INCLUDE_HMD = 0x00000020, } public enum DISPLAYCONFIG_SCANLINE_ORDERING { DISPLAYCONFIG_SCANLINE_ORDERING_UNSPECIFIED = 0, DISPLAYCONFIG_SCANLINE_ORDERING_PROGRESSIVE = 1, DISPLAYCONFIG_SCANLINE_ORDERING_INTERLACED = 2, DISPLAYCONFIG_SCANLINE_ORDERING_INTERLACED_UPPERFIELDFIRST = DISPLAYCONFIG_SCANLINE_ORDERING_INTERLACED, DISPLAYCONFIG_SCANLINE_ORDERING_INTERLACED_LOWERFIELDFIRST = 3, } public enum DISPLAYCONFIG_PIXELFORMAT { DISPLAYCONFIG_PIXELFORMAT_8BPP = 1, DISPLAYCONFIG_PIXELFORMAT_16BPP = 2, DISPLAYCONFIG_PIXELFORMAT_24BPP = 3, DISPLAYCONFIG_PIXELFORMAT_32BPP = 4, DISPLAYCONFIG_PIXELFORMAT_NONGDI = 5, } public enum DISPLAYCONFIG_MODE_INFO_TYPE { DISPLAYCONFIG_MODE_INFO_TYPE_SOURCE = 1, DISPLAYCONFIG_MODE_INFO_TYPE_TARGET = 2, DISPLAYCONFIG_MODE_INFO_TYPE_DESKTOP_IMAGE = 3, } [StructLayout(LayoutKind.Sequential)] public struct DISPLAYCONFIG_DEVICE_INFO_HEADER { public DISPLAYCONFIG_DEVICE_INFO_TYPE type; public int size; public LUID adapterId; public uint id; } [StructLayout(LayoutKind.Sequential)] public struct DISPLAYCONFIG_GET_ADVANCED_COLOR_INFO { public DISPLAYCONFIG_DEVICE_INFO_HEADER header; public uint value; public DISPLAYCONFIG_COLOR_ENCODING colorEncoding; public int bitsPerColorChannel; public bool advancedColorSupported => (value & 0x1) == 0x1; public bool advancedColorEnabled => (value & 0x2) == 0x2; public bool wideColorEnforced => (value & 0x4) == 0x4; public bool advancedColorForceDisabled => (value & 0x8) == 0x8; } [StructLayout(LayoutKind.Sequential)] public struct POINTL { public int x; public int y; } [StructLayout(LayoutKind.Sequential)] public struct LUID { public uint LowPart; public int HighPart; public long Value => ((long)HighPart << 32) | LowPart; public override string ToString() => Value.ToString(); } [StructLayout(LayoutKind.Sequential)] public struct DISPLAYCONFIG_SOURCE_MODE { public uint width; public uint height; public DISPLAYCONFIG_PIXELFORMAT pixelFormat; public POINTL position; } [StructLayout(LayoutKind.Sequential)] public struct DISPLAYCONFIG_RATIONAL { public uint Numerator; public uint Denominator; public override string ToString() => Numerator + " / " + Denominator; } [StructLayout(LayoutKind.Sequential)] public struct DISPLAYCONFIG_2DREGION { public uint cx; public uint cy; } [StructLayout(LayoutKind.Sequential)] public struct DISPLAYCONFIG_DESKTOP_IMAGE_INFO { public POINTL PathSourceSize; public RECT DesktopImageRegion; public RECT DesktopImageClip; } [StructLayout(LayoutKind.Sequential)] public struct DISPLAYCONFIG_VIDEO_SIGNAL_INFO { public ulong pixelRate; public DISPLAYCONFIG_RATIONAL hSyncFreq; public DISPLAYCONFIG_RATIONAL vSyncFreq; public DISPLAYCONFIG_2DREGION activeSize; public DISPLAYCONFIG_2DREGION totalSize; public uint videoStandard; public DISPLAYCONFIG_SCANLINE_ORDERING scanLineOrdering; } [StructLayout(LayoutKind.Sequential)] public struct DISPLAYCONFIG_TARGET_MODE { public DISPLAYCONFIG_VIDEO_SIGNAL_INFO targetVideoSignalInfo; } [StructLayout(LayoutKind.Explicit)] public struct DISPLAYCONFIG_MODE_INFO_union { [FieldOffset(0)] public DISPLAYCONFIG_TARGET_MODE targetMode; [FieldOffset(0)] public DISPLAYCONFIG_SOURCE_MODE sourceMode; [FieldOffset(0)] public DISPLAYCONFIG_DESKTOP_IMAGE_INFO desktopImageInfo; } [StructLayout(LayoutKind.Sequential)] public struct DISPLAYCONFIG_PATH_SOURCE_INFO { public LUID adapterId; public uint id; public uint modeInfoIdx; public DISPLAYCONFIG_SOURCE_FLAGS statusFlags; } [StructLayout(LayoutKind.Sequential)] public struct DISPLAYCONFIG_PATH_TARGET_INFO { public LUID adapterId; public uint id; public uint modeInfoIdx; public DISPLAYCONFIG_VIDEO_OUTPUT_TECHNOLOGY outputTechnology; public DISPLAYCONFIG_ROTATION rotation; public DISPLAYCONFIG_SCALING scaling; public DISPLAYCONFIG_RATIONAL refreshRate; public DISPLAYCONFIG_SCANLINE_ORDERING scanLineOrdering; public bool targetAvailable; public DISPLAYCONFIG_TARGET_FLAGS statusFlags; } [StructLayout(LayoutKind.Sequential)] public struct DISPLAYCONFIG_PATH_INFO { public DISPLAYCONFIG_PATH_SOURCE_INFO sourceInfo; public DISPLAYCONFIG_PATH_TARGET_INFO targetInfo; public DISPLAYCONFIG_PATH flags; } [StructLayout(LayoutKind.Sequential)] public struct DISPLAYCONFIG_MODE_INFO { public DISPLAYCONFIG_MODE_INFO_TYPE infoType; public uint id; public LUID adapterId; public DISPLAYCONFIG_MODE_INFO_union info; } [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] public struct DISPLAYCONFIG_GET_SOURCE_NAME { public DISPLAYCONFIG_DEVICE_INFO_HEADER header; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)] public string viewGdiDeviceName; } [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] public struct DISPLAYCONFIG_TARGET_DEVICE_NAME_FLAGS { public uint value; } [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] public struct DISPLAYCONFIG_GET_TARGET_NAME { public DISPLAYCONFIG_DEVICE_INFO_HEADER header; public DISPLAYCONFIG_TARGET_DEVICE_NAME_FLAGS flags; public DISPLAYCONFIG_VIDEO_OUTPUT_TECHNOLOGY outputTechnology; public ushort edidManufactureId; public ushort edidProductCodeId; public uint connectorInstance; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 64)] public string monitorFriendlyDeviceName; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)] public string monitorDevicePath; } [StructLayout(LayoutKind.Sequential)] internal struct DISPLAYCONFIG_GET_TARGET_PREFERRED_NAME { public DISPLAYCONFIG_DEVICE_INFO_HEADER header; public uint Width; public uint Height; public DISPLAYCONFIG_TARGET_MODE TargetMode; } [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] internal struct DISPLAYCONFIG_GET_ADAPTER_NAME { public DISPLAYCONFIG_DEVICE_INFO_HEADER header; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)] public string AdapterDevicePath; } [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] internal struct DISPLAYCONFIG_SUPPORT_VIRTUAL_RESOLUTION { public DISPLAYCONFIG_DEVICE_INFO_HEADER header; [MarshalAs(UnmanagedType.U4)] private uint DisableMonitorVirtualResolution; public bool IsMonitorVirtualResolutionDisabled { get => DisableMonitorVirtualResolution > 0; } } [StructLayout(LayoutKind.Sequential)] internal struct DISPLAYCONFIG_SET_TARGET_PERSISTENCE { public DISPLAYCONFIG_DEVICE_INFO_HEADER header; [MarshalAs(UnmanagedType.U4)] public uint BootPersistenceOn; public bool IsBootPersistenceOn { get => BootPersistenceOn > 0; } } [StructLayout(LayoutKind.Sequential)] internal struct DISPLAYCONFIG_GET_TARGET_BASE_TYPE { public DISPLAYCONFIG_DEVICE_INFO_HEADER header; [MarshalAs(UnmanagedType.U4)] public DISPLAYCONFIG_VIDEO_OUTPUT_TECHNOLOGY BaseOutputTechnology; } [StructLayout(LayoutKind.Sequential)] internal struct DISPLAYCONFIG_SET_ADVANCED_COLOR_STATE { public DISPLAYCONFIG_DEVICE_INFO_HEADER header; [MarshalAs(UnmanagedType.U4)] public uint EnableAdvancedColor; public bool IsAdvancedColorEnabled { get => EnableAdvancedColor > 0; } } [StructLayout(LayoutKind.Sequential)] internal struct DISPLAYCONFIG_SDR_WHITE_LEVEL { public DISPLAYCONFIG_DEVICE_INFO_HEADER header; // SDRWhiteLevel represents a multiplier for standard SDR white // peak value i.e. 80 nits represented as fixed point. // To get value in nits use the following conversion // SDRWhiteLevel in nits = (SDRWhiteLevel / 1000 ) * 80 public ulong SDRWhiteLevel; } [StructLayout(LayoutKind.Sequential)] public struct RECT { public int left; public int top; public int right; public int bottom; } class CCDImport { // GetDisplayConfigBufferSizes [DllImport("user32")] public static extern int GetDisplayConfigBufferSizes(QDC flags, out int numPathArrayElements, out int numModeInfoArrayElements); // QueryDisplayConfig [DllImport("user32")] public static extern int QueryDisplayConfig(QDC flags, ref int numPathArrayElements, [In, Out] DISPLAYCONFIG_PATH_INFO[] pathArray, ref int numModeInfoArrayElements, [In, Out] DISPLAYCONFIG_MODE_INFO[] modeInfoArray, out DISPLAYCONFIG_TOPOLOGY_ID currentTopologyId); [DllImport("user32")] public static extern int QueryDisplayConfig(QDC flags, ref int numPathArrayElements, [In, Out] DISPLAYCONFIG_PATH_INFO[] pathArray, ref int numModeInfoArrayElements, [In, Out] DISPLAYCONFIG_MODE_INFO[] modeInfoArray, IntPtr currentTopologyId); // DisplayConfigGetDeviceInfo [DllImport("user32")] public static extern int DisplayConfigGetDeviceInfo(ref DISPLAYCONFIG_GET_SOURCE_NAME requestPacket); [DllImport("user32")] public static extern int DisplayConfigGetDeviceInfo(ref DISPLAYCONFIG_GET_TARGET_NAME requestPacket); [DllImport("user32")] public static extern int DisplayConfigGetDeviceInfo(ref DISPLAYCONFIG_GET_TARGET_PREFERRED_NAME requestPacket); [DllImport("user32")] public static extern int DisplayConfigGetDeviceInfo(ref DISPLAYCONFIG_GET_ADAPTER_NAME requestPacket); [DllImport("user32")] public static extern int DisplayConfigGetDeviceInfo(ref DISPLAYCONFIG_SET_TARGET_PERSISTENCE requestPacket); [DllImport("user32")] public static extern int DisplayConfigGetDeviceInfo(ref DISPLAYCONFIG_GET_TARGET_BASE_TYPE requestPacket); [DllImport("user32")] public static extern int DisplayConfigGetDeviceInfo(ref DISPLAYCONFIG_SUPPORT_VIRTUAL_RESOLUTION requestPacket); /*[DllImport("user32")] public static extern int DisplayConfigGetDeviceInfo(ref DISPLAYCONFIG_SET_SUPPORT_VIRTUAL_RESOLUTION requestPacket); */ [DllImport("user32")] public static extern int DisplayConfigGetDeviceInfo(ref DISPLAYCONFIG_GET_ADVANCED_COLOR_INFO requestPacket); [DllImport("user32")] public static extern int DisplayConfigGetDeviceInfo(ref DISPLAYCONFIG_SET_ADVANCED_COLOR_STATE requestPacket); [DllImport("user32")] public static extern int DisplayConfigGetDeviceInfo(ref DISPLAYCONFIG_SDR_WHITE_LEVEL requestPacket); // DisplayConfigSetDeviceInfo [DllImport("user32")] public static extern int DisplayConfigSetDeviceInfo( ref DISPLAYCONFIG_SET_TARGET_PERSISTENCE targetPersistence ); // Have disabled the DisplayConfigSetDeviceInfo options except for SET_TARGET_PERSISTENCE, as per the note // from https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-displayconfigsetdeviceinfo // "DisplayConfigSetDeviceInfo can currently only be used to start and stop boot persisted force projection on an analog target." /*[DllImport("user32")] public static extern int DisplayConfigSetDeviceInfo( ref DISPLAYCONFIG_SUPPORT_VIRTUAL_RESOLUTION targetSupportVirtualResolution );*/ // SetDisplayConfig [DllImport("user32")] public static extern int SetDisplayConfig( [In] uint pathArrayElements, [In] DISPLAYCONFIG_PATH_INFO[] pathArray, [In] uint modeInfoArrayElements, [In] DISPLAYCONFIG_MODE_INFO[] modeInfoArray, [In] QDC flags ); } }