LoginSignup
6
9

More than 3 years have passed since last update.

Windowsアプリケーションの自動化-Python編①-

Last updated at Posted at 2020-11-29

今更ですが、Pythonでwin32guiと、win32conを使ってWindowsアプリケーションを操作する手順を勉強したのでメモ

参考URL
- Pythonで子ウィンドウハンドルを取得する方法
- CComboBox クラス|Microsoft

構成環境

  • Windows10
  • Anaconda3 2019.10
  • Python3.7.4

Windowsアプリケーションの操作

win32guiは、Anaconda環境なら標準でインストール済み

一応よくあるファイル選択ダイアログのフォルダパス選択操作を想定しています

クラス名とハンドル名を取得する

winapi.py
import array
import win32gui
import win32con

def run():
    # 親ウィンドウハンドル(識別番号)とそのクラス名、ハンドル名を取得
    p_handle = win32gui.FindWindow(None,"XXX") # アプリケーションのタイトル文字列など入力
    p_class_name = win32gui.GetClassName(p_handle)
    p_handle_name = win32gui.GetWindowText(p_handle)
    handles_dict = {str(p_handle): [p_class_name,p_handle_name]}
    print('p',hex(p_handle),p_class_name,p_handle_name)

    # 親ウィンドウハンドルの子ウィンドウハンドルを配列に格納
    c_handles = array.array("i")  # 子ウィンドウハンドルは複数あることを想定し配列を作成
    win32gui.EnumChildWindows(p_handle,lambda handle,list: list.append(handle),c_handles)

    # 子ウィンドウハンドルとそのクラス名、ハンドル名を列挙
    for ch in c_handles:
        c_class_name = win32gui.GetClassName(ch)
        c_handle_name = win32gui.GetWindowText(ch)
        print('c',hex(ch),c_class_name,c_handle_name)
        handles_dict[str(ch)] = [c_class_name,c_handle_name]

    # ここでは、ComboBoxのウィンドウハンドルを操作してフォルダパスを選択する
    combobox = [k for k,v in handles_dict.items() if str(v[0]).lower() == 'combobox']  # わざわざ辞書にしなくても良いかも
    win32gui.SendMessage(handles_dict[combobox[0]], win32con.CB_SHOWDROPDOWN, True, 0)  # ドロップダウンを表示する
    win32gui.SendMessage(handles_dict[combobox[0]], win32con.CB_GETCURSEL)  # 選択されている文字列の番号
    win32gui.SendMessage(handles_dict[combobox[0]], win32con.WM_GETTEXTLENGTH)  # 選択されている文字列の長さ
    win32gui.SendMessage(handles_dict[combobox[0]], win32con.CB_FINDSTRINGEXACT, 0, "XXX")  # 指定した[文字列]の番号
    win32gui.SendMessage(handles_dict[combobox[0]], win32con.CB_SETCURSEL, XX)  # 指定した[番号]の文字列を選択する
    win32gui.SendMessage(handles_dict[combobox[0]], win32con.VK_RETURN)  # Enterキー押下してフォルダを決定する

   # このあとに[はい]のボタンを押す処理とかetc

if __name__ == '__main__':
    run()

とまあ、ざっとこんな感じですかね

EnumChildWindowsのコールバック関数の処理について

win32gui.EnumChildWindows(p_handle,lambda handle,list: list.append(handle),c_handles)
↑のラムダ式の部分は下記のようにも書けます(参考URLより)

enum_child_windows_proc.py
def enum_child_windows_proc(handle, list):
        list.append(handle)
       return 1

win32gui.EnumChildWindows(p_handle,enum_child_windows_proc,c_handles)

そういえばwin32apiライブラリは使ってなかった

まとめ

コンボボックス内の文字列を取得する方法が謎なのでコンボボックス内の文字列の番号から探す力技で実装
あと、ウィンドウハンドルを探すのに苦労した
Visual Studio の Spy++というツールがない場合にウィンドウハンドルとクラス名,ハンドル名を効率よく探す方法を検討したいですね

:arrow_backward: [前回の記事] | 次回の記事 :arrow_forward:

6
9
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
9