pythonでスクリーンショット(for Windows)

BlackHatPython(2nd edition)を読むpython

Black Hat Python, 2nd Edition
Python Programming for Hackers and Pentesters
by Justin Seitz and Tim Arnold
no starch press
April 2021, 216 pp.

本記事は『Black Hat Python, 2nd Edition Python Programming for Hackers and Pentesters』の要点整理及び自分の理解度確認を目的として書いたものです。ここで解説する本書中のソースコードは全てno starch pressのサイトから誰でもフリーでダウンロードできます。自分の理解が及ばず誤りが散見される可能性がありますがご了承ください。

流石に本書に書いてある文章をそのまま訳してつらつら書くわけにはいかない。

 

ここでは誰でもフリーにダウンロードできる本書中のソースコードにおいて、大切な所や少し難しい所の説明を軽く挟んでいくだけ。

はしょった部分も沢山ある。

 

重要な部分は実際に本書を読まなければ知ることができない。

 

本書をすでに購入済みの人がその本片手に参考にするような記事になっている。

 

是非『Black Hat Python, 2nd Edition Python Programming for Hackers and Pentesters』を手に取ってその周辺の重要な説明部分にも目を通すことを勧める。

スポンサーリンク

get_dimensions関数について

def get_dimensions():
    width = win32api.GetSystemMetrics(win32con.SM_CXVIRTUALSCREEN)
    height = win3api.GetSystemMetrics(win32con.SM_CYVIRTUALSCREEN)
    left = win3api.GetSystemMetrics(win32con.SM_XVIRTUALSCREEN)
    top = win32api.GetSystemMetrics(win32con.SM_YVIRTUALSCREEN)
    return (width, height, left, top)

GetSystemMetricsは、さまざまなシステムメトリックの値(表示要素の幅と高さ)とシステムの現在の構成を取得する。

表示要素とは、ウィンドウの一部、またはシステムが表示する画面の一部のこと。

 

その引数に与えてるやつらはこれ(vs=バーチャルスクリーン):

  • SM_CXVIRTUALSCREEN → vsの幅
  • SM_CYVIRTUALSCREEN → vsの高さ
  • SM_XVIRTUALSCREEN → vs左側の座標
  • SM_YVIRTUALSCREEN → vsのトップの座標
バーチャルスクリーンとは、実際に表示可能な解像度よりも大きい解像度を使用できるようにするための仮想画面のこと。
バーチャルスクリーンでは、仮想画面全体のサイズが実際のディスプレイの画面より大きくなるから、ディスプレイには常に仮想画面の一部が表示されている状態となる。
画面をスクロールすると、ディスプレイの画面上で見えていない部分を表示することができる。

screenshot関数について

(画面全体のスクリーンショットを撮ることを目的とする。)

def screenshot(name='screenshot'):
    hdesktop = win32gui.GetDesktopWindow()
    width, height, left, top = get_dimensions()

    desktop_dc = win32gui.GetWindowDC(hdesktop)
    img_dc = win32ui.CreateDCFromHandle(desktop_dc)
    mem_dc = img_dc.CreateCompatibleDC()

    screenshot = win32ui.CreateBitmap()
    screenshot.CreateCompatibleBitmap(img_dc, width, height)
    mem_dc.SelectObject(screenshot)
    mem_dc.BitBlt((0,0), (width, height), img_dc, (left, top), win32con.SRCCOPY)
    screenshot.SaveBitmapFile(mem_dc, f'{name}.bmp')

    mem_dc.DeleteDC()
    win32gui.DeleteObject(screenshot.GetHandle())

(途中で「今どこやってんだ?」って迷子になりかねないからはじめに全体像を示した。)

それぞれの説明があるから部分ごとにみていく。

 

hdesktop = win32gui.GetDesktopWindow()
width, height, left, top = get_dimensions()

まずGetDesktopWindow()でデスクトップウィンドウのハンドルを取得。

(デスクトップウィンドウはスクリーン全体を覆っており、この上にアイコンやウィンドウなどが描画される。)

 

desktop_dc = win32gui.GetWindowsDC(hdesktop)
img_dc = win32ui.CreateDCFromHandle(desktop_dc)

GetWindowsDCでタイトルバー、メニュー、スクロールバーを含む、ウィンドウ全体のデバイスコンテキスト(DC)を取得。

引数は、DCを取得したいウィンドウのハンドルを指定する。

デバイスコンテキスト(DC)とは、ディスプレイやプリンターなどのデバイスの描画属性に関する情報を含むWindows データ構造。

 

img_dcについてなんだけど、公式ドキュメントには“Creates a DC object from an integer handle.”としか書いてない。誤植?

とにかくDCオブジェクト。

 

mem_dc = img_dc.CreateCompatibleDC()

メモリDVを作成(メモリ内に作成される)。

ビットマップをファイルに書き込むまで、ここにキャプチャした画像を保管しておく。

描画処理をする前に、メモリDCに幅と高さをCreateCompatibleBitmap関数で指定し、ビットマップ オブジェクトを作成する必要がある。

screenshot = win32ui.CreateBitmap()
screenshot.CreateCompatibleBitmap(img_dc, width, height)
mem_dc.SelectObject(screenshot)

キャプチャしたデスクトップのDVと互換性のあるビットマップオブジェクトscreenshotがこれでできる(最初の2行)。

その後、メモリDVとビットマップを関連付ける(SelectObject)。

 

mem_dc.BitBlt((0, 0), (width, height),
                    img_dc, (left, top), win32con.SRCCOPY)
screenshot.SaveBitmapFile(mem_dc, f'{name}.bmp')

ビットブロック転送を行う。コピー元からコピー先のデバイスコンテキストへ、指定された長方形内の各ピクセルの色データをコピーする。

つまりメモリーデバイスコンテキストにデスクトップ画面をコピー。

BitBltの詳しい引数はこちら。)

SaveBitmapFile()で画像をファイルに書き起こす。

参考にした記事

力尽きた

調べるのに日本語・英語いろんなサイトまわった。

疲れるぅ〜〜。

 

この記事見てる人はそんなことしなくていい。

でも俺の説明不足でさらなる情報欲しい人は以下の参考リンクあたってみて:

俺頑張りすぎてるなぁ〜

タイトルとURLをコピーしました