mirror of
https://github.com/ksyasuda/dotfiles.git
synced 2026-02-28 00:22:41 -08:00
update
This commit is contained in:
163
.agents/skills/screenshot/scripts/take_screenshot.ps1
Normal file
163
.agents/skills/screenshot/scripts/take_screenshot.ps1
Normal file
@@ -0,0 +1,163 @@
|
||||
param(
|
||||
[string]$Path,
|
||||
[ValidateSet("default", "temp")][string]$Mode = "default",
|
||||
[string]$Format = "png",
|
||||
[string]$Region,
|
||||
[switch]$ActiveWindow,
|
||||
[int]$WindowHandle
|
||||
)
|
||||
|
||||
Set-StrictMode -Version Latest
|
||||
$ErrorActionPreference = "Stop"
|
||||
|
||||
function Get-Timestamp {
|
||||
Get-Date -Format "yyyy-MM-dd_HH-mm-ss"
|
||||
}
|
||||
|
||||
function Get-DefaultDirectory {
|
||||
$home = [Environment]::GetFolderPath("UserProfile")
|
||||
$pictures = Join-Path $home "Pictures"
|
||||
$screenshots = Join-Path $pictures "Screenshots"
|
||||
if (Test-Path $screenshots) { return $screenshots }
|
||||
if (Test-Path $pictures) { return $pictures }
|
||||
return $home
|
||||
}
|
||||
|
||||
function New-DefaultFilename {
|
||||
param([string]$Prefix)
|
||||
if (-not $Prefix) { $Prefix = "screenshot" }
|
||||
"$Prefix-$(Get-Timestamp).$Format"
|
||||
}
|
||||
|
||||
function Resolve-OutputPath {
|
||||
if ($Path) {
|
||||
$expanded = [Environment]::ExpandEnvironmentVariables($Path)
|
||||
$homeDir = [Environment]::GetFolderPath("UserProfile")
|
||||
if ($expanded -eq "~") {
|
||||
$expanded = $homeDir
|
||||
} elseif ($expanded.StartsWith("~/") -or $expanded.StartsWith("~\\")) {
|
||||
$expanded = Join-Path $homeDir $expanded.Substring(2)
|
||||
}
|
||||
$full = [System.IO.Path]::GetFullPath($expanded)
|
||||
if ((Test-Path $full) -and (Get-Item $full).PSIsContainer) {
|
||||
$full = Join-Path $full (New-DefaultFilename "")
|
||||
} elseif (($expanded.EndsWith("\") -or $expanded.EndsWith("/")) -and -not (Test-Path $full)) {
|
||||
New-Item -ItemType Directory -Path $full -Force | Out-Null
|
||||
$full = Join-Path $full (New-DefaultFilename "")
|
||||
} elseif ([System.IO.Path]::GetExtension($full) -eq "") {
|
||||
$full = "$full.$Format"
|
||||
}
|
||||
$parent = Split-Path -Parent $full
|
||||
if ($parent) {
|
||||
New-Item -ItemType Directory -Path $parent -Force | Out-Null
|
||||
}
|
||||
return $full
|
||||
}
|
||||
|
||||
if ($Mode -eq "temp") {
|
||||
$tmp = [System.IO.Path]::GetTempPath()
|
||||
return Join-Path $tmp (New-DefaultFilename "codex-shot")
|
||||
}
|
||||
|
||||
$dest = Get-DefaultDirectory
|
||||
return Join-Path $dest (New-DefaultFilename "")
|
||||
}
|
||||
|
||||
function Parse-Region {
|
||||
if (-not $Region) { return $null }
|
||||
$parts = $Region.Split(",") | ForEach-Object { $_.Trim() }
|
||||
if ($parts.Length -ne 4) {
|
||||
throw "Region must be x,y,w,h"
|
||||
}
|
||||
$values = $parts | ForEach-Object {
|
||||
$out = 0
|
||||
if (-not [int]::TryParse($_, [ref]$out)) {
|
||||
throw "Region values must be integers"
|
||||
}
|
||||
$out
|
||||
}
|
||||
if ($values[2] -le 0 -or $values[3] -le 0) {
|
||||
throw "Region width and height must be positive"
|
||||
}
|
||||
return $values
|
||||
}
|
||||
|
||||
if ($Region -and $ActiveWindow) {
|
||||
throw "Choose either -Region or -ActiveWindow"
|
||||
}
|
||||
if ($Region -and $WindowHandle) {
|
||||
throw "Choose either -Region or -WindowHandle"
|
||||
}
|
||||
if ($ActiveWindow -and $WindowHandle) {
|
||||
throw "Choose either -ActiveWindow or -WindowHandle"
|
||||
}
|
||||
|
||||
$regionValues = Parse-Region
|
||||
$outputPath = Resolve-OutputPath
|
||||
|
||||
Add-Type -AssemblyName System.Windows.Forms
|
||||
Add-Type -AssemblyName System.Drawing
|
||||
|
||||
$imageFormat = switch ($Format.ToLowerInvariant()) {
|
||||
"png" { [System.Drawing.Imaging.ImageFormat]::Png }
|
||||
"jpg" { [System.Drawing.Imaging.ImageFormat]::Jpeg }
|
||||
"jpeg" { [System.Drawing.Imaging.ImageFormat]::Jpeg }
|
||||
"bmp" { [System.Drawing.Imaging.ImageFormat]::Bmp }
|
||||
default { throw "Unsupported format: $Format" }
|
||||
}
|
||||
|
||||
Add-Type @"
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
public static class NativeMethods {
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct RECT {
|
||||
public int Left;
|
||||
public int Top;
|
||||
public int Right;
|
||||
public int Bottom;
|
||||
}
|
||||
|
||||
[DllImport("user32.dll")]
|
||||
public static extern IntPtr GetForegroundWindow();
|
||||
|
||||
[DllImport("user32.dll")]
|
||||
public static extern bool GetWindowRect(IntPtr hWnd, out RECT rect);
|
||||
}
|
||||
"@
|
||||
|
||||
if ($regionValues) {
|
||||
$x = $regionValues[0]
|
||||
$y = $regionValues[1]
|
||||
$w = $regionValues[2]
|
||||
$h = $regionValues[3]
|
||||
$bounds = New-Object System.Drawing.Rectangle($x, $y, $w, $h)
|
||||
} elseif ($ActiveWindow -or $WindowHandle) {
|
||||
$handle = if ($WindowHandle) { [IntPtr]$WindowHandle } else { [NativeMethods]::GetForegroundWindow() }
|
||||
$rect = New-Object NativeMethods+RECT
|
||||
if (-not [NativeMethods]::GetWindowRect($handle, [ref]$rect)) {
|
||||
throw "Failed to get window bounds"
|
||||
}
|
||||
$width = $rect.Right - $rect.Left
|
||||
$height = $rect.Bottom - $rect.Top
|
||||
$bounds = New-Object System.Drawing.Rectangle($rect.Left, $rect.Top, $width, $height)
|
||||
} else {
|
||||
$vs = [System.Windows.Forms.SystemInformation]::VirtualScreen
|
||||
$bounds = New-Object System.Drawing.Rectangle($vs.Left, $vs.Top, $vs.Width, $vs.Height)
|
||||
}
|
||||
|
||||
$bitmap = New-Object System.Drawing.Bitmap($bounds.Width, $bounds.Height)
|
||||
$graphics = [System.Drawing.Graphics]::FromImage($bitmap)
|
||||
|
||||
try {
|
||||
$source = New-Object System.Drawing.Point($bounds.Left, $bounds.Top)
|
||||
$target = [System.Drawing.Point]::Empty
|
||||
$size = New-Object System.Drawing.Size($bounds.Width, $bounds.Height)
|
||||
$graphics.CopyFromScreen($source, $target, $size)
|
||||
$bitmap.Save($outputPath, $imageFormat)
|
||||
} finally {
|
||||
$graphics.Dispose()
|
||||
$bitmap.Dispose()
|
||||
}
|
||||
|
||||
Write-Output $outputPath
|
||||
Reference in New Issue
Block a user