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("\\", "#")) ); } } }