using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using WindowsDisplayAPI.Native;
using WindowsDisplayAPI.Native.DisplayConfig.Structures;
using WindowsDisplayAPI.Native.Structures;
namespace WindowsDisplayAPI.DisplayConfig
{
///
/// Represents a path display adapter
///
public class PathDisplayAdapter : IEquatable
{
///
/// Creates a new PathDisplayAdapter
///
/// The adapter local unique identification
public PathDisplayAdapter(LUID adapterId)
{
AdapterId = adapterId;
}
///
/// Gets the display adapter local identification LUID
///
public LUID AdapterId { get; }
///
/// Gets the display adapter device path
///
/// Error code can be retrieved from Win32Exception.NativeErrorCode property
public string DevicePath
{
get
{
var adapterName = new DisplayConfigAdapterName(AdapterId);
var result = DisplayConfigApi.DisplayConfigGetDeviceInfo(ref adapterName);
if (result == Win32Status.Success)
{
return adapterName.AdapterDevicePath;
}
throw new Win32Exception((int) result);
}
}
///
/// Gets a boolean value indicating the instance validity
///
public bool IsInvalid
{
get => AdapterId.IsEmpty();
}
///
public bool Equals(PathDisplayAdapter other)
{
if (ReferenceEquals(null, other))
{
return false;
}
if (ReferenceEquals(this, other))
{
return true;
}
return AdapterId == other.AdapterId;
}
///
/// Retrieving a list of all adapters from the currently active and inactive paths
///
/// An array of PathDisplayAdapter instances
public static PathDisplayAdapter[] GetAdapters()
{
var adapters = new Dictionary();
foreach (var pathInfo in PathInfo.GetAllPaths())
{
if (!pathInfo.DisplaySource.Adapter.IsInvalid &&
!adapters.ContainsKey(pathInfo.DisplaySource.Adapter.AdapterId))
{
adapters.Add(pathInfo.DisplaySource.Adapter.AdapterId, pathInfo.DisplaySource.Adapter);
}
foreach (var pathTargetInfo in pathInfo.TargetsInfo)
{
if (!pathTargetInfo.DisplayTarget.Adapter.IsInvalid &&
!adapters.ContainsKey(pathTargetInfo.DisplayTarget.Adapter.AdapterId))
{
adapters.Add(pathTargetInfo.DisplayTarget.Adapter.AdapterId, pathTargetInfo.DisplayTarget.Adapter);
}
}
}
return adapters.Values.ToArray();
}
///
/// Checks for equality of two PathDisplayAdapter instances
///
/// The first instance
/// The second instance
/// true if both instances are equal, otherwise false
public static bool operator ==(PathDisplayAdapter left, PathDisplayAdapter right)
{
return Equals(left, right) || left?.Equals(right) == true;
}
///
/// Checks for inequality of two PathDisplayAdapter instances
///
/// The first instance
/// The second instance
/// true if both instances are not equal, otherwise false
public static bool operator !=(PathDisplayAdapter left, PathDisplayAdapter right)
{
return !(left == right);
}
///
public override bool Equals(object obj)
{
if (ReferenceEquals(null, obj))
{
return false;
}
if (ReferenceEquals(this, obj))
{
return true;
}
return obj.GetType() == GetType() && Equals((PathDisplayAdapter) obj);
}
///
public override int GetHashCode()
{
return AdapterId.GetHashCode();
}
///
public override string ToString()
{
return DevicePath;
}
#if !NETSTANDARD
///
/// Opens the registry key of the Windows PnP manager for this display adapter
///
/// A RegistryKey instance for successful call, otherwise null
public Microsoft.Win32.RegistryKey OpenDevicePnPKey()
{
if (string.IsNullOrWhiteSpace(DevicePath))
return null;
var path = DevicePath;
if (path.StartsWith("\\\\?\\"))
{
path = path.Substring(4).Replace("#", "\\");
if (path.EndsWith("}"))
{
var guidIndex = path.LastIndexOf("{", StringComparison.InvariantCulture);
if (guidIndex > 0)
path = path.Substring(0, guidIndex);
}
}
return Microsoft.Win32.Registry.LocalMachine.OpenSubKey("SYSTEM\\CurrentControlSet\\Enum\\" + path,
Microsoft.Win32.RegistryKeyPermissionCheck.ReadSubTree);
}
#endif
///
/// Gets the corresponding DisplayAdapter instance
///
/// An instance of DisplayAdapter, or null
public DisplayAdapter ToDisplayAdapter()
{
return DisplayAdapter.GetDisplayAdapters()
.FirstOrDefault(
adapter => DevicePath.StartsWith("\\\\?\\" + adapter.DevicePath.Replace("\\", "#"))
);
}
}
}