Skip to content

Instantly share code, notes, and snippets.

@emoacht
Created May 28, 2021 05:45
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save emoacht/16b2160338228fbc7b885383782e9233 to your computer and use it in GitHub Desktop.
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.
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