Created
March 15, 2025 16:57
-
-
Save dudewheresmycode/8fc5d100a0ef44fad8bb684fa82dc403 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Define the P/Invoke signatures | |
Add-Type @" | |
using System; | |
using System.Runtime.InteropServices; | |
using System.Text; | |
public class WindowTools { | |
[StructLayout(LayoutKind.Sequential)] | |
public struct RECT { | |
public int Left; | |
public int Top; | |
public int Right; | |
public int Bottom; | |
} | |
[StructLayout(LayoutKind.Sequential)] | |
public struct POINT { | |
public int X; | |
public int Y; | |
} | |
[StructLayout(LayoutKind.Sequential)] | |
public struct WINDOWPLACEMENT { | |
public uint length; | |
public uint flags; | |
public uint showCmd; | |
public POINT ptMinPosition; | |
public POINT ptMaxPosition; | |
public RECT rcNormalPosition; | |
} | |
public delegate bool EnumWindowsProc(IntPtr hWnd, IntPtr lParam); | |
[DllImport("user32.dll", SetLastError = true)] | |
public static extern bool EnumWindows(EnumWindowsProc lpEnumFunc, IntPtr lParam); | |
[DllImport("user32.dll", SetLastError = true)] | |
public static extern int GetWindowText(IntPtr hWnd, StringBuilder lpString, int nMaxCount); | |
[DllImport("user32.dll", SetLastError = true)] | |
public static extern int GetWindowTextLength(IntPtr hWnd); | |
[DllImport("user32.dll", SetLastError = true)] | |
public static extern bool GetWindowRect(IntPtr hWnd, out RECT lpRect); | |
[DllImport("user32.dll", SetLastError = true)] | |
public static extern bool GetWindowPlacement(IntPtr hWnd, ref WINDOWPLACEMENT lpwndpl); | |
[DllImport("user32.dll")] | |
public static extern IntPtr MonitorFromWindow(IntPtr hwnd, uint dwFlags); | |
[DllImport("user32.dll")] | |
public static extern bool EnumDisplayMonitors(IntPtr hdc, IntPtr lprcClip, MonitorEnumProc lpfnEnum, IntPtr dwData); | |
public delegate bool MonitorEnumProc(IntPtr hMonitor, IntPtr hdcMonitor, ref RECT lprcMonitor, IntPtr dwData); | |
[DllImport("user32.dll")] | |
public static extern IntPtr GetDC(IntPtr hWnd); | |
[DllImport("gdi32.dll")] | |
public static extern int GetDeviceCaps(IntPtr hdc, int nIndex); | |
[DllImport("user32.dll")] | |
public static extern int ReleaseDC(IntPtr hWnd, IntPtr hDC); | |
public const int LOGPIXELSX = 88; | |
public const int LOGPIXELSY = 90; | |
} | |
public class Shcore { | |
[DllImport("shcore.dll")] | |
public static extern int GetScaleFactorForMonitor(IntPtr hmon, out int pScale); | |
} | |
"@ | |
Add-Type -AssemblyName System.Windows.Forms | |
# Constants for DPI | |
$MONITOR_DEFAULTTONEAREST = 2 | |
function Get-DisplayDPI { | |
$hDC = [WindowTools]::GetDC([IntPtr]::Zero) | |
if ($hDC -eq [IntPtr]::Zero) { | |
Write-Error "Failed to get device context" | |
return | |
} | |
$dpiX = [WindowTools]::GetDeviceCaps($hDC, [WindowTools]::LOGPIXELSX) | |
$dpiY = [WindowTools]::GetDeviceCaps($hDC, [WindowTools]::LOGPIXELSY) | |
[WindowTools]::ReleaseDC([IntPtr]::Zero, $hDC) | |
return @{ | |
DPI_X = $dpiX | |
DPI_Y = $dpiY | |
} | |
} | |
# Function to get the window handle by title | |
function Get-WindowHandleByTitle { | |
param ( | |
[string]$windowTitle | |
) | |
$windowHandle = [IntPtr]::Zero | |
$callback = { | |
param ( | |
[IntPtr]$hWnd, | |
[IntPtr]$lParam | |
) | |
$length = [WindowTools]::GetWindowTextLength($hWnd) | |
if ($length -gt 0) { | |
$builder = New-Object Text.StringBuilder $length | |
[WindowTools]::GetWindowText($hWnd, $builder, $builder.Capacity + 1) | Out-Null | |
$currentTitle = $builder.ToString() | |
Write-Host $currentTitle | |
if ($currentTitle -eq $windowTitle) { | |
$script:windowHandle = $hWnd | |
return $false | |
} | |
} | |
return $true | |
} | |
$enumProc = [WindowTools+EnumWindowsProc]$callback | |
[WindowTools]::EnumWindows($enumProc, [IntPtr]::Zero) | Out-Null | |
return $windowHandle | |
} | |
# Function to get the window position and size | |
function Get-WindowPositionAndSize { | |
param ( | |
[IntPtr]$windowHandle | |
) | |
$rect = New-Object WindowTools+RECT | |
if (-not [WindowTools]::GetWindowRect($windowHandle, [ref]$rect)) { | |
Write-Error "Failed to get window rectangle" | |
return | |
} | |
$width = $rect.Right - $rect.Left | |
$height = $rect.Bottom - $rect.Top | |
$monitorHandle = [WindowTools]::MonitorFromWindow($windowHandle, $MONITOR_DEFAULTTONEAREST) | |
if ($monitorHandle -eq [IntPtr]::Zero) { | |
Write-Error "Failed to get monitor handle" | |
return | |
} | |
$scaleFactor = 0 | |
$result = [Shcore]::GetScaleFactorForMonitor($monitorHandle, [ref]$scaleFactor) | |
if ($result -ne 0) { | |
Write-Error "Failed to get scale factor for monitor" | |
return | |
} | |
$scaleFactor = $scaleFactor / 100.0 | |
[PSCustomObject]@{ | |
left = $rect.Left | |
right = $rect.Right | |
top = $rect.Top | |
width = $width | |
height = $height | |
# FullScreen = $isFullScreen | |
scaleFactor = [math]::Round($scaleFactor, 3) | |
} | |
} | |
function Get-MonitorForWindow { | |
param ( | |
[Drawing.Rectangle]$rect | |
) | |
Add-Type -AssemblyName System.Windows.Forms | |
$monitor = [System.Windows.Forms.Screen]::FromRectangle($rect) | |
if ($monitor) { | |
# Get the graphics object from the screen | |
# $graphics = [System.Drawing.Graphics]::FromHwnd($monitor.Handle) | |
$displayDPI = Get-DisplayDPI | |
[PSCustomObject]@{ | |
name = $monitor.DeviceName | |
primary = $monitor.Primary | |
x = $monitor.Bounds.X | |
y = $monitor.Bounds.Y | |
# dpiX = $graphics.DpiX | |
# dpiY = $graphics.DpiY | |
height = $monitor.Bounds.Height | |
width = $monitor.Bounds.Width | |
dpiX = $displayDPI.DPI_X | |
dpiY = $displayDPI.DPI_Y | |
workingAreaX = $monitor.WorkingArea.X | |
workingAreaY = $monitor.WorkingArea.Y | |
workingAreaWidth = $monitor.WorkingArea.Width | |
workingAreaHeight = $monitor.WorkingArea.Height | |
} | |
# $graphics.Dispose() | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment