From 190786a15a7ae94f81da0df8e6a12b3373ba68c6 Mon Sep 17 00:00:00 2001 From: Serge <5920850+seerge@users.noreply.github.com> Date: Fri, 18 Aug 2023 18:15:12 +0200 Subject: [PATCH] Internal screen detection --- app/Display/ScreenInterrogatory.cs | 74 ++++++++++++++++++++++++- app/Display/ScreenNative.cs | 86 ++++++++++++++++++++---------- 2 files changed, 132 insertions(+), 28 deletions(-) diff --git a/app/Display/ScreenInterrogatory.cs b/app/Display/ScreenInterrogatory.cs index d16557ef..1840b27b 100644 --- a/app/Display/ScreenInterrogatory.cs +++ b/app/Display/ScreenInterrogatory.cs @@ -1,4 +1,6 @@ -using System.ComponentModel; +using GHelper.Helpers; +using NvAPIWrapper.Display; +using System.ComponentModel; using System.Runtime.InteropServices; namespace GHelper.Display @@ -259,6 +261,49 @@ namespace GHelper.Display #endregion + + [Flags] + public enum DisplayDeviceStates : int + { + ATTACHED_TO_DESKTOP = 0x01, + PRIMARY_DEVICE = 0x04, + MIRRORING_DRIVER = 0x08, + VGA_COMPATIBLE = 0x10, + REMOVABLE = 0x20, + DISCONNECTED = 0x2000000, + REMOTE = 0x4000000, + MODESPRUNED = 0x8000000 + } + + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] + public struct DISPLAY_DEVICE + { + public int cb; + + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)] + public string DeviceName; + + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)] + public string DeviceString; + + public DisplayDeviceStates StateFlags; + + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)] + public string DeviceID; + + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)] + public string DeviceKey; + } + + + [DllImport(nameof(User32), CharSet = CharSet.Unicode, SetLastError = true)] + public static extern bool EnumDisplayDevices( + string? lpDevice, + uint iDevNum, + ref DISPLAY_DEVICE lpDisplayDevice, + uint dwFlags); + + private static DISPLAYCONFIG_TARGET_DEVICE_NAME DeviceName(LUID adapterId, uint targetId) { var deviceName = new DISPLAYCONFIG_TARGET_DEVICE_NAME @@ -298,6 +343,33 @@ namespace GHelper.Display } + public static IEnumerable GetDisplayDevices() + { + + var displayAdapter = new DISPLAY_DEVICE(); + displayAdapter.cb = Marshal.SizeOf(); + + var displayAdapterNumber = default(uint); + while (EnumDisplayDevices(null, displayAdapterNumber, ref displayAdapter, 1)) + { + var displayMonitor = new DISPLAY_DEVICE(); + displayMonitor.cb = Marshal.SizeOf(); + + var displayMonitorNumber = default(uint); + while (EnumDisplayDevices(displayAdapter.DeviceName, displayMonitorNumber, ref displayMonitor, 1)) + { + var isAttached = (displayMonitor.StateFlags & DisplayDeviceStates.ATTACHED_TO_DESKTOP) == DisplayDeviceStates.ATTACHED_TO_DESKTOP; + var isMirroring = (displayMonitor.StateFlags & DisplayDeviceStates.MIRRORING_DRIVER) == DisplayDeviceStates.MIRRORING_DRIVER; + if (isAttached && !isMirroring) yield return displayMonitor; + displayMonitorNumber++; + + } + + displayAdapterNumber++; + } + } + + } } diff --git a/app/Display/ScreenNative.cs b/app/Display/ScreenNative.cs index 6d0ea5ad..b612d509 100644 --- a/app/Display/ScreenNative.cs +++ b/app/Display/ScreenNative.cs @@ -1,5 +1,8 @@ -using System.Collections; +using Microsoft.VisualBasic.Logging; +using System.Collections; +using System.Diagnostics.Metrics; using System.Runtime.InteropServices; +using System.Windows.Forms; using static GHelper.Display.ScreenInterrogatory; namespace GHelper.Display @@ -145,20 +148,12 @@ namespace GHelper.Display public const int ENUM_CURRENT_SETTINGS = -1; public const string defaultDevice = @"\\.\DISPLAY1"; - public static string? FindLaptopScreen(bool log = false) - { - string? laptopScreen = null; - var screens = Screen.AllScreens; + private static string? FindInternalName(bool log = false) + { try { var devices = GetAllDevices().ToArray(); - - Array.Sort(devices, new DeviceComparer()); - Array.Sort(screens, new ScreenComparer()); - - int count = 0; - string internalName = AppConfig.GetString("internal_display"); foreach (var device in devices) @@ -167,31 +162,68 @@ namespace GHelper.Display device.outputTechnology == DISPLAYCONFIG_VIDEO_OUTPUT_TECHNOLOGY.DISPLAYCONFIG_OUTPUT_TECHNOLOGY_DISPLAYPORT_EMBEDDED || device.monitorFriendlyDeviceName == internalName) { + if (log) Logger.WriteLine(device.monitorDevicePath + " " + device.outputTechnology); AppConfig.Set("internal_display", device.monitorFriendlyDeviceName); - - if (count < screens.Length) - { - laptopScreen = screens[count].DeviceName; - } - else - { - laptopScreen = defaultDevice; - } + var names = device.monitorDevicePath.Split("#"); + return names[1]; } - - - if (log) Logger.WriteLine(device.monitorFriendlyDeviceName + ":" + device.outputTechnology.ToString() + device.connectorInstance.ToString() + ": " + ((count < screens.Length) ? screens[count].DeviceName : "")); - count++; } - } catch (Exception ex) { Logger.WriteLine(ex.ToString()); - Logger.WriteLine("Can't detect internal screen"); - laptopScreen = Screen.PrimaryScreen.DeviceName; } + return null; + } + + static string ExtractDisplay(string input) + { + int index = input.IndexOf('\\', 4); // Start searching from index 4 to skip "" + + if (index != -1) + { + string extracted = input.Substring(0, index); + return extracted; + } + + return input; + } + + public static string? FindLaptopScreen(bool log = false) + { + string? laptopScreen = null; + string? internalName = FindInternalName(log); + + if (internalName == null) + { + Logger.WriteLine("Internal screen off"); + return null; + } + + try + { + var displays = GetDisplayDevices().ToArray(); + foreach (var display in displays) + { + if (log) Logger.WriteLine(display.DeviceID + " " + display.DeviceName); + if (display.DeviceID.Contains(internalName)) + { + laptopScreen = ExtractDisplay(display.DeviceName); + break; + } + } + } + catch (Exception ex) + { + Logger.WriteLine(ex.ToString()); + } + + if (laptopScreen is null) + { + Logger.WriteLine("Default internal screen"); + laptopScreen = Screen.PrimaryScreen.DeviceName; + } return laptopScreen; }