タイトルを指定してウィンドウのスクリーンショットを取得するツール

概要

ウィンドウのタイトルを正規表現で与えて、画像を取得するpythonコード。
ウィンドウが他ウィンドウによって隠れている場合は、隠れた状態の画像が返ってくる。

ソース

import time
import datetime
import threading
import re

from PIL import ImageGrab
import win32gui


class CaptureWindow:
    def __init__(self, title_regex, padding=[], set_foreground=False):
        self.padding = padding
        self.set_foreground = set_foreground

        # 引数の正規表現に一致するウィンドウを探す
        def find_window(hwnd, results):
            title = win32gui.GetWindowText(hwnd)
            if re.match(title_regex, title):
                results.append((hwnd, title))

        window_info_list = []
        win32gui.EnumWindows(find_window, window_info_list)

        if not window_info_list:
            print('{} is not found.'.format(title_regex))
        else:
            window_info = window_info_list[0]

            self.handle = window_info[0]
            self.title = window_info[1]

    def __call__(self):
        if self.set_foreground:
            # noinspection PyBroadException
            try:
                win32gui.SetForegroundWindow(self.handle)
            except Exception:
                pass

        rect = win32gui.GetWindowRect(self.handle)
        new_rect = (
            rect[0] + self.padding[3],
            rect[1] + self.padding[0],
            rect[2] - self.padding[1],
            rect[3] - self.padding[2]
        )
        return ImageGrab.grab(new_rect)


# 使用例
if __name__ == '__main__':
    capture = CaptureWindow('.*?メモ帳', [0, 7, 7, 7])

    def callback():
        image = capture()
        image.save('save/{}_{}.png'.format(
            capture.title,
            datetime.datetime.now().strftime("%Y%m%d_%H%M%S")
        ))

    while True:
        # 5秒毎にキャプチャー
        t = threading.Thread(target=callback)
        t.start()
        t.join()
        time.sleep(5)

使用例

padding = [0, 0, 0, 0]の場合。
なぜか見た目より広い範囲になる。

padding = [0, 7, 7, 7]の場合。
ウィンドウの大きさぴったりで取得。(この設定は環境による可能性あり)

padding = [31, 8, 8, 8]の場合。
ウィンドウの縁も排除。