Pythonでウィンドウのタイトルから爆速で位置を取得【Windows】


なぜ書いたか

Pythonでマウスクリックしたい!アプリが起動しているのか?起動しているならどこにあるのか?
PyAutoGUIや、PyWinAutoWindows App Driverなど試したが、どれも欠点が目立ち上手くいきませんでした。

個人的に最適と思った答えを見つけたので、幸せを共有しようと思いました。
みんなで自動化してサボりましょう。

既存ライブラリの未熟なところ

これらの欠点から、基本的にはPyAutoGUIを使い、できない部分のウィンドウ操作系は独自実装として補う使い方にしました。
独自実装した部分はそのうちプルリクしようと思っています。

  • PyAutoGUI / Sikulix / Lackey
  • ウィンドウ操作系はロードマップに開発中と書いてあたったりする
  • コンセプトが画像認識なので広範囲から探すと遅い
  • PyWinAuto
  • HowToに掲載されているアプリケーションの起動方法で起動できないものがある。
  • 結局Pythonからcmdコマンドを使う羽目に。
  • Windows App Driver
  • 判断が遅い
  • Xpathで探したりして、とにかく遅い。大規模なERP系アプリケーションのXpathとか、めっちゃ遅い。

あらすじ

Python で Windows API を使って、ウィンドウの位置を返す関数を作りました。
ウィンドウのタイトルを基にして、Top・Left・Bottom・Rightの数値を取れます。
数値は画面の左上隅を原点とした正の数です。

コード

いきなりコードです。

def GetWindowRectFromName(TargetWindowTitle:str)-> tuple:
    TargetWindowHandle = ctypes.windll.user32.FindWindowW(0, TargetWindowTitle)
    Rectangle = ctypes.wintypes.RECT()
    ctypes.windll.user32.GetWindowRect(TargetWindowHandle, ctypes.pointer(Rectangle))
    return (Rectangle.left, Rectangle.top, Rectangle.right, Rectangle.bottom)

if __name__ == "__main__":
    print(GetWindowRectFromName('CALC'))
    pass

動作

引数は、日本語でも何でもいいですが、ウィンドウのタイトルがそのまんま入ります。

FindWindowW を使って、ウィンドウハンドルを取得します。

次に、このハンドルが示すウィンドウから GetWindowRectRECT 構造体に位置を取得します。

このRECTの中身でタプルを再構築したものを戻り値として返します。

※サンプルコードではCALCを引数に入れていますが、日本語環境では電卓と入れるとOKです。

環境

Python 3.8.2 | packaged by conda-forge | (default, Apr 24 2020, 07:34:03) [MSC v.1916 64 bit (AMD64)] on win32 Windows 10 Pro 1909

参考

まとめ

ネイティブな関数をラップしているだけなので爆速。

Excelsior!