Created
May 28, 2021 05:45
-
-
Save emoacht/16b2160338228fbc7b885383782e9233 to your computer and use it in GitHub Desktop.
Find index number of display shown in the OS's display settings. The reliability of this method is unknown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.Diagnostics; | |
using System.Linq; | |
using System.Runtime.InteropServices; | |
using System.Text; | |
public static class DisplayHelper | |
{ | |
#region Win32 | |
[DllImport("Setupapi.dll", SetLastError = true)] | |
private static extern IntPtr SetupDiGetClassDevs( | |
[MarshalAs(UnmanagedType.LPStruct), In] Guid ClassGuid, | |
IntPtr Enumerator, // Null | |
IntPtr hwndParent, // Null | |
DIGCF Flags); | |
private const int INVALID_HANDLE_VALUE = -1; | |
private const int ERROR_NO_MORE_ITEMS = 259; | |
[DllImport("Setupapi.dll", SetLastError = true)] | |
[return: MarshalAs(UnmanagedType.Bool)] | |
private static extern bool SetupDiDestroyDeviceInfoList( | |
IntPtr DeviceInfoSet); | |
[DllImport("Setupapi.dll", SetLastError = true)] | |
[return: MarshalAs(UnmanagedType.Bool)] | |
private static extern bool SetupDiEnumDeviceInfo( | |
IntPtr DeviceInfoSet, | |
uint MemberIndex, | |
ref SP_DEVINFO_DATA DeviceInfoData); | |
[DllImport("Setupapi.dll", CharSet = CharSet.Auto, SetLastError = true)] | |
[return: MarshalAs(UnmanagedType.Bool)] | |
private static extern bool SetupDiGetDeviceInstanceId( | |
IntPtr DeviceInfoSet, | |
ref SP_DEVINFO_DATA DeviceInfoData, | |
[Out] StringBuilder DeviceInstanceId, | |
uint DeviceInstanceIdSize, | |
out uint RequiredSize); | |
[StructLayout(LayoutKind.Sequential)] | |
private struct SP_DEVINFO_DATA | |
{ | |
public uint cbSize; | |
public Guid ClassGuid; | |
public uint DevInst; | |
public IntPtr Reserved; | |
} | |
[Flags] | |
private enum DIGCF : uint | |
{ | |
DIGCF_DEFAULT = 0x00000001, // only valid with DIGCF_DEVICEINTERFACE | |
DIGCF_PRESENT = 0x00000002, | |
DIGCF_ALLCLASSES = 0x00000004, | |
DIGCF_PROFILE = 0x00000008, | |
DIGCF_DEVICEINTERFACE = 0x00000010 | |
} | |
#endregion | |
/// <summary> | |
/// Finds index number of display shown in the OS's display settings. | |
/// </summary> | |
/// <param name="deviceInstanceId">Device instance ID</param> | |
/// <returns>If found, one-based index number. Otherwise, -1.</returns> | |
public static int FindIndexOf(string deviceInstanceId) | |
{ | |
var ids = EnumerateMonitorDeviceInstanceIds() | |
.Reverse() | |
.Select((id, index) => (id, index)) | |
.ToDictionary(x => x.id, x => x.index + 1); | |
return ids.TryGetValue(deviceInstanceId.ToUpper(), out int index) | |
? index | |
: -1; | |
} | |
private static readonly Guid GUID_DEVINTERFACE_MONITOR = new Guid("E6F07B5F-EE97-4a90-B076-33F57BF4EAA7"); | |
private static IEnumerable<string> EnumerateMonitorDeviceInstanceIds() | |
{ | |
var deviceInfoSet = IntPtr.Zero; | |
try | |
{ | |
deviceInfoSet = SetupDiGetClassDevs( | |
GUID_DEVINTERFACE_MONITOR, | |
IntPtr.Zero, // DISPLAY | |
IntPtr.Zero, | |
DIGCF.DIGCF_DEVICEINTERFACE | DIGCF.DIGCF_PRESENT); | |
if (deviceInfoSet.ToInt64() == INVALID_HANDLE_VALUE) // Assuming 32bit process | |
{ | |
Debug.WriteLine($"Failed to get device information list."); | |
yield break; | |
} | |
uint memberIndex = 0; | |
while (true) | |
{ | |
var deviceInfoData = new SP_DEVINFO_DATA { cbSize = (uint)Marshal.SizeOf<SP_DEVINFO_DATA>() }; | |
if (SetupDiEnumDeviceInfo( | |
deviceInfoSet, | |
memberIndex, | |
ref deviceInfoData)) | |
{ | |
yield return GetDeviceInstanceId(deviceInfoSet, deviceInfoData); | |
} | |
else | |
{ | |
if (Marshal.GetLastWin32Error() == ERROR_NO_MORE_ITEMS) | |
yield break; | |
Debug.WriteLine($"Failed to enumerate device information structures."); | |
} | |
memberIndex++; | |
} | |
} | |
finally | |
{ | |
SetupDiDestroyDeviceInfoList(deviceInfoSet); | |
} | |
} | |
private static string GetDeviceInstanceId(IntPtr DeviceInfoSet, SP_DEVINFO_DATA DeviceInfoData) | |
{ | |
SetupDiGetDeviceInstanceId( | |
DeviceInfoSet, | |
ref DeviceInfoData, | |
null, | |
0, | |
out uint requiredSize); | |
var buffer = new StringBuilder((int)requiredSize); | |
if (SetupDiGetDeviceInstanceId( | |
DeviceInfoSet, | |
ref DeviceInfoData, | |
buffer, | |
requiredSize, | |
out _)) | |
{ | |
return buffer.ToString(); | |
} | |
return string.Empty; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment