Python

Pythonで選択したウィンドウのスクリーンショットを撮るには?

Pythonで選択したウィンドウのスクリーンショットを撮るには?

Pythonでスクリーンショットを撮ることができることは分かりました。
ただ、できるのは、全体だったり、領域を座標で指定したり。
ショートカットキー「Alt + PrintScreen」の、選択したウィンドウだけのスクリーンショットを撮ることがPythonでもできたら便利だなぁと感じたので、やり方をまとめました。

 

用意するものは?

外部ライブラリ「win32gui」を使います。
これはウィンドウの情報を得るためのもの。
「pywin32」をインストールすると使えるようになります。
Windowsであれば、コマンドプロンプトで下記のコマンドを実行するとインストールできます。

pip install pywin32

 

コードの書き方は?

「win32gui.GetWindowRect()」でウィンドウサイズを取得できるので、その引数であるウィンドウのハンドルをまずは取得します。
ウィンドウサイズが取得できたら、「ImageGrab.grab()」の引数に入れてスクリーンショットを撮影する、という流れです。
入力したウィンドウのタイトルが存在しない場合、「win32gui.FindWindow()」は「0」を返すので、if文で判定しています。

from PIL import ImageGrab
import win32gui, time
 
# ウィンドウのハンドルを取得
hwnd = win32gui.FindWindow(None, '【スクリーンショットを撮りたいウィンドウのタイトル】')
if hwnd:
    # 前面に移動
    win32gui.SetForegroundWindow(hwnd)
 
    # 1秒待つ
    time.sleep(1)
 
    # ウィンドウサイズを取得
    window_size = win32gui.GetWindowRect(hwnd)
 
    # 取得したウィンドウサイズでスクリーンショットを撮る
    image = ImageGrab.grab(window_size)
    image.show()
else:
    print('入力したタイトルに一致するウィンドウがありません')

 

撮影したスクリーンショットのサイズがずれている場合は?

私の環境では、取ったスクリーンショットが微妙にずれていました。
Pythonで選択したウィンドウのスクリーンショットを撮るには?

これはOSによる問題らしいです。
解決方法は、「ctypes」を使います。
勉強不足でコードの内容は分かりませんが、結果はウィンドウサイズピッタリでスクリーンショットが撮れました。

from PIL import ImageGrab
import win32gui, ctypes, time
from ctypes import wintypes
 
# ウィンドウのハンドルを取得
hwnd = win32gui.FindWindow(None, '【サイズを取得したいウィンドウのタイトル】')
if hwnd:
    # 前面に移動
    win32gui.SetForegroundWindow(hwnd)
 
    # 1秒待つ
    time.sleep(1)
 
    # ずれを調整
    f = ctypes.windll.dwmapi.DwmGetWindowAttribute
    rect = ctypes.wintypes.RECT()
    DWMWA_EXTENDED_FRAME_BOUNDS = 9
    f(  ctypes.wintypes.HWND(hwnd),
        ctypes.wintypes.DWORD(DWMWA_EXTENDED_FRAME_BOUNDS),
        ctypes.byref(rect),
        ctypes.sizeof(rect)
    )
 
    # 取得したウィンドウサイズでスクリーンショットを撮る
    image = ImageGrab.grab((rect.left, rect.top, rect.right, rect.bottom))
    image.show()
else:
    print('タイトルが一致するウィンドウがありません')

コードの実行結果はこちら
Pythonで選択したウィンドウのスクリーンショットを撮るには?
キレイに撮れていますね。

 

まとめ

Pythonで選択したウィンドウのスクリーンショットを撮るには、外部ライブラリ「win32gui」を使ってウィンドウサイズを取得し、「ImageGrab.grab()」を実行します。
OSによってはズレるので、「ctypes」を使って調整すると上手く撮影できます。
ちょうど1000枚単位で撮影する作業があったので、家事の合間にプログラムを実行させて終わらせることができました。

-Python
-, , , , , , , , , , , , ,