ちょっと欲しくなったので調べてみました。
How can I do a screen capture in Windows PowerShell? - Stack Overflow の Jacob Colvin さんの回答が一番簡潔だったのでそれを元にいくつか用意してみました。
まずはマルチモニターを含めた全領域。
# screenshot-all.ps1 # From https://stackoverflow.com/questions/2969321/how-can-i-do-a-screen-capture-in-windows-powershell Add-Type -AssemblyName System.Windows.Forms,System.Drawing $screens = [Windows.Forms.Screen]::AllScreens $top = ($screens.Bounds.Top | Measure-Object -Minimum).Minimum $left = ($screens.Bounds.Left | Measure-Object -Minimum).Minimum $width = ($screens.Bounds.Right | Measure-Object -Maximum).Maximum $height = ($screens.Bounds.Bottom | Measure-Object -Maximum).Maximum $bounds = [Drawing.Rectangle]::FromLTRB($left, $top, $width, $height) $bmp = New-Object System.Drawing.Bitmap ([int]$bounds.width), ([int]$bounds.height) $graphics = [Drawing.Graphics]::FromImage($bmp) $graphics.CopyFromScreen($bounds.Location, [Drawing.Point]::Empty, $bounds.size) $bmp.Save($Args[0]) $graphics.Dispose() $bmp.Dispose()
次にプライマリースクリーンのみ。
# screenshot-primary.ps1 # From https://stackoverflow.com/questions/2969321/how-can-i-do-a-screen-capture-in-windows-powershell Add-Type -AssemblyName System.Windows.Forms,System.Drawing $screen = [Windows.Forms.Screen]::PrimaryScreen $top = $screen.Bounds.Top $left = $screen.Bounds.Left $right = $screen.Bounds.Right $bottom = $screen.Bounds.Bottom $bounds = [Drawing.Rectangle]::FromLTRB($left, $top, $right, $bottom) $bmp = New-Object System.Drawing.Bitmap ([int]$bounds.width), ([int]$bounds.height) $graphics = [Drawing.Graphics]::FromImage($bmp) $graphics.CopyFromScreen($bounds.Location, [Drawing.Point]::Empty, $bounds.size) $bmp.Save($Args[0]) $graphics.Dispose() $bmp.Dispose()
最後にアクティブウィンドウのみ。
# screenshot-activewin.ps1 # Get Foreground Window's Rect Add-Type -Type @' using System; using System.Runtime.InteropServices; namespace Win32Util { public struct RECT { public int Left, Top, Right, Bottom; } public class Utils { [DllImport("user32.dll")] public static extern IntPtr GetForegroundWindow(); // [DllImport("user32.dll")] // public static extern int GetWindowRect(IntPtr hWnd, out RECT lpRect); [DllImport("dwmapi.dll")] public static extern int DwmGetWindowAttribute(IntPtr hWnd, uint dwAttribute, out RECT lpRect, int cbAttribute); public static uint DWMWA_EXTENDED_FRAME_BOUNDS = 0x09; public static RECT GetForegroundWindowRect(){ IntPtr hwnd = GetForegroundWindow(); // RECT rect = new RECT(); // GetWindowRect(hwnd, out rect); RECT rect = new RECT(); DwmGetWindowAttribute(hwnd, DWMWA_EXTENDED_FRAME_BOUNDS, out rect, Marshal.SizeOf(typeof(RECT))); return rect; } } } '@ $rect = [Win32Util.Utils]::GetForegroundWindowRect() # https://stackoverflow.com/questions/2969321/how-can-i-do-a-screen-capture-in-windows-powershell Add-Type -AssemblyName System.Windows.Forms,System.Drawing $top = $rect.Top $left = $rect.Left $right = $rect.Right $bottom = $rect.Bottom $bounds = [Drawing.Rectangle]::FromLTRB($left, $top, $right, $bottom) $bmp = New-Object System.Drawing.Bitmap ([int]$bounds.width), ([int]$bounds.height) $graphics = [Drawing.Graphics]::FromImage($bmp) $graphics.CopyFromScreen($bounds.Location, [Drawing.Point]::Empty, $bounds.size) $bmp.Save($Args[0]) $graphics.Dispose() $bmp.Dispose()
実行は powershell screenshot-activewin.ps1 test.png
のようにします。
それにしても久しぶりのWin32がまさかこんな形だとは。Windows10でGetWindowRectだと左右下に7ピクセルずつ余分に広い矩形を返してしまうだとか。影とかの効果の分でしょうか? なので今はDwmGetWindowAttributeを使うんだそうです。
あ、ちなみにEmacsのorg-downloadからを使うには次のように設定すればいいんです。使用頻度が少なそうなのでHydraが無いと覚えられる気がしませんね。まぁ、別に全部クリップボードからでもいいじゃんって思ったりもしますが。
(when (eq system-type 'windows-nt) (defun my-org-download-screenshot (script-name) (let ((org-download-screenshot-method (format "powershell %s %%s" (expand-file-name (format "<path-to-script-dir>/%s" script-name))))) (org-download-screenshot))) (defun my-org-download-screenshot-all () (interactive) (my-org-download-screenshot "screenshot-all.ps1")) (defun my-org-download-screenshot-primary () (interactive) (my-org-download-screenshot "screenshot-primary.ps1")) (defun my-org-download-screenshot-active-window () (interactive) (my-org-download-screenshot "screenshot-activewin.ps1")) ;; Key bind help (when (featurep 'hydra) (define-key org-mode-map (kbd "C-c d") (defhydra my-org-download-hydra (:color red :exit t :hint nil) " org-download copy from: _c_: Clipboard _y_: Full-path or URL on kill-ring _a_: All monitors _p_: Primary monitor _f_: Foreground window or drop from a local image file. " ("c" org-download-clipboard) ("y" org-download-yank) ("a" my-org-download-screenshot-all) ("p" my-org-download-screenshot-primary) ("f" my-org-download-screenshot-active-window)))))
[…] WindowsなのでPowerShellを使用してスクリーンショットを撮っていますが、スクリプトはWindowsのコマンドラインからスクリーンショットを撮る(PowerShell)で紹介したものです。 […]