From fa6c6399f13dbba56829ce472a5d33029ae4f866 Mon Sep 17 00:00:00 2001 From: Carterpersall Date: Tue, 20 Sep 2022 13:06:55 -0500 Subject: [PATCH 1/3] Fix Resolution Bug - Gets the current resolution scale by getting DisplayTransferCharacteristic from WmiMonitorBasicDisplayParams - Divides by 96 to get the scale from the given PPI - ~2x Slower than the current (but broken) implementation w/o PowerShell bottleneck - 34 ms -> 84 ms - ~2.7x Faster than #131 w/o PowerShell bottleneck - 230 ms --- winfetch.ps1 | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/winfetch.ps1 b/winfetch.ps1 index aadf9ac..8b81ee5 100644 --- a/winfetch.ps1 +++ b/winfetch.ps1 @@ -617,8 +617,11 @@ function info_uptime { # ===== RESOLUTION ===== function info_resolution { Add-Type -AssemblyName System.Windows.Forms - $displays = foreach ($monitor in [System.Windows.Forms.Screen]::AllScreens) { - "$($monitor.Bounds.Size.Width)x$($monitor.Bounds.Size.Height)" + $monitors = [System.Windows.Forms.Screen]::AllScreens + $scale = (Get-CimInstance -Namespace root\wmi -ClassName WmiMonitorBasicDisplayParams -CimSession $cimSession).DisplayTransferCharacteristic / 96 + + $displays = for($i = 0;$i -lt $monitors.Length;$i++){ + "$($monitors[$i].Bounds.Size.Width * $scale[$i])x$($monitors[$i].Bounds.Size.Height * $scale[$i])" } return @{ From 111cd1cf9340ac348af2d8309112f4e20200c00d Mon Sep 17 00:00:00 2001 From: Carterpersall Date: Wed, 21 Sep 2022 11:02:38 -0500 Subject: [PATCH 2/3] Fix Bug --- winfetch.ps1 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/winfetch.ps1 b/winfetch.ps1 index 8b81ee5..8d24ec7 100644 --- a/winfetch.ps1 +++ b/winfetch.ps1 @@ -618,10 +618,10 @@ function info_uptime { function info_resolution { Add-Type -AssemblyName System.Windows.Forms $monitors = [System.Windows.Forms.Screen]::AllScreens - $scale = (Get-CimInstance -Namespace root\wmi -ClassName WmiMonitorBasicDisplayParams -CimSession $cimSession).DisplayTransferCharacteristic / 96 + $scale = (Get-CimInstance -Namespace root\wmi -ClassName WmiMonitorBasicDisplayParams -CimSession $cimSession).DisplayTransferCharacteristic $displays = for($i = 0;$i -lt $monitors.Length;$i++){ - "$($monitors[$i].Bounds.Size.Width * $scale[$i])x$($monitors[$i].Bounds.Size.Height * $scale[$i])" + "$($monitors[$i].Bounds.Size.Width * ($scale[$i] / 96))x$($monitors[$i].Bounds.Size.Height * ($scale[$i] / 96))" } return @{ From 7533641ead7bc4f73fa9ea053e935f2046d84b40 Mon Sep 17 00:00:00 2001 From: Carterpersall Date: Thu, 22 Sep 2022 11:25:28 -0500 Subject: [PATCH 3/3] Actually Fix this Time - Added two methods of getting screen resolution - First one runs if running as admin, and gets the screen information from HKLM:\SYSTEM\CurrentControlSet\Control\GraphicsDrivers\Configuration\ - Location contains refresh rate, so I added that in too - Second method uses implementation in #131 which is about 4x slower for me, but seems to be the only way to get it working that I can find --- winfetch.ps1 | 90 +++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 86 insertions(+), 4 deletions(-) diff --git a/winfetch.ps1 b/winfetch.ps1 index 8d24ec7..b57679d 100644 --- a/winfetch.ps1 +++ b/winfetch.ps1 @@ -617,11 +617,93 @@ function info_uptime { # ===== RESOLUTION ===== function info_resolution { Add-Type -AssemblyName System.Windows.Forms - $monitors = [System.Windows.Forms.Screen]::AllScreens - $scale = (Get-CimInstance -Namespace root\wmi -ClassName WmiMonitorBasicDisplayParams -CimSession $cimSession).DisplayTransferCharacteristic + + # Checks if running as admin + if((New-Object Security.Principal.WindowsPrincipal([Security.Principal.WindowsIdentity]::GetCurrent())).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)){ + [System.Collections.ArrayList]$displays = @() + # Gets the current screen layout from the registry + Get-ChildItem -path HKLM:\SYSTEM\CurrentControlSet\Control\GraphicsDrivers\Configuration\ | Get-ItemProperty | ForEach-Object{ + if($_.Timestamp -gt $timestamp){ + $layout = $_ + $timestamp = $_.timestamp + } + } - $displays = for($i = 0;$i -lt $monitors.Length;$i++){ - "$($monitors[$i].Bounds.Size.Width * ($scale[$i] / 96))x$($monitors[$i].Bounds.Size.Height * ($scale[$i] / 96))" + # Gets resolution and refresh rate for each display + $displays = $layout | Get-ChildItem | Get-ChildItem | Get-ItemProperty | ForEach-Object{ + "$($_."ActiveSize.cx")x$($_."ActiveSize.cy")@$($_."VSyncFreq.Numerator"/$_."VSyncFreq.Denominator")Hz" + } + }else{ + # Use Add-Type Method (at least 4x slower) + Add-Type @" + using System.Runtime.InteropServices; + using System.Collections.Generic; + using System; + using System.Linq; + namespace WinAPI + { + public class MonitorMethods + { + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] + struct MONITORINFOEX + { + public int Size; + public Rect Monitor; + public Rect WorkArea; + public uint Flags; + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)] + public string DeviceName; + } + + [DllImport("Shcore.dll")] + static public extern bool SetProcessDpiAwareness(int value); + [DllImport("user32.dll")] + static extern bool EnumDisplayMonitors( + IntPtr hdc, + IntPtr lprcClip, + EnumMonitorsDelegate lpfnEnum, + IntPtr dwData + ); + [DllImport("user32.dll", CharSet = CharSet.Auto)] + static extern bool GetMonitorInfo(IntPtr hMonitor, ref MONITORINFOEX lpmi); + [StructLayout(LayoutKind.Sequential)] + public struct Rect + { + public int left; + public int top; + public int right; + public int bottom; + } + delegate bool EnumMonitorsDelegate(IntPtr hMonitor, IntPtr hdcMonitor, ref Rect lprcMonitor, IntPtr dwData); + static private List m_displays = new List(); + + static bool EnumProc(IntPtr hMonitor, IntPtr hdcMonitor, ref Rect lprcMonitor, IntPtr dwData) + { + MONITORINFOEX mONITORINFOEX = new MONITORINFOEX(); + mONITORINFOEX.Size = Marshal.SizeOf(typeof(MONITORINFOEX)); + GetMonitorInfo(hMonitor, ref mONITORINFOEX); + var displayInfo = new DisplayInfo(); + displayInfo.X = (int)((mONITORINFOEX.Monitor.right - mONITORINFOEX.Monitor.left)); + displayInfo.Y = (int)((mONITORINFOEX.Monitor.bottom - mONITORINFOEX.Monitor.top)); + m_displays.Add(displayInfo); + return true; + } + public class DisplayInfo + { + public int X; + public int Y; + } + public static string GetResolution() + { + SetProcessDpiAwareness(2); + m_displays = new List(); + EnumDisplayMonitors(IntPtr.Zero, IntPtr.Zero, EnumProc, IntPtr.Zero); + return String.Join(", ", m_displays.Select(displayInfo => displayInfo.X.ToString() + "x" + displayInfo.Y.ToString())); + } + } + } +"@ + $displays = [WinAPI.MonitorMethods]::GetResolution() } return @{