Pythonでwin32gui
と、win32con
を使ってWindowsアプリケーションのメニューバーを操作する
今回はフリーソフトの「サクラエディタ」を操作してみる
参考URL
##作業環境
- Windows10
- Anaconda3 2020.11
- Python3.8.5
- サクラエディタ v2.2.0.1 ←ちょっと古い
##メニューバーを操作して日付を挿入するイメージ
上記のメニューバー操作を、Pythonで自動化する
###メニューバー(タブメニュー)とそのサブメニューのハンドルを取得
メニューバーのハンドルは、子ウィンドウハンドルではなくwin32gui.GetMenu()
で取得できる
サブメニューや、サブメニューのサブメニューはwin32gui.GetSubMenu()
winapi.py
import win32gui
import win32con
def run():
p_hWnd = win32gui.FindWindow(None,"(無題)1 - sakura 2.2.0.1 ") # 親ウィンドウハンドル(識別番号)を取得
win32gui.SetForegroundWindow(p_hWnd) # アプリケーションをデスクトップの前面に表示
p_menu_hWnd = win32gui.GetMenu(p_hWnd) # メニューバーのハンドルを取得
p_menu_count = win32gui.GetMenuItemCount(p_menu_hWnd) # メニューバー内のサブメニューの個数を取得
# 各サブメニューのハンドルを取得
s_menu_dict = {}
for i in range(p_menu_count):
s_menu_dict["s_menu_pos{}".format(i)] = win32gui.GetSubMenu(p_menu_hWnd, i)
[print(k,v) for k,v in s_menu_dict.items()] # サブメニュー辞書確認
if __name__ == '__main__':
run()
- サブメニューのハンドルの例
メニューバー | 位置 | SubMenu hWnd |
---|---|---|
ファイル(F) | 0 | 15402645 |
編集(E) | 1 | 459021 |
変換(C) | 2 | 67635661 |
検索(S) | 3 | 18022831 |
ツール(T) | 4 | 31787639 |
設定(O) | 5 | 5573367 |
ウィンドウ(W) | 6 | 93652277 |
ヘルプ(H) | 7 | 62851833 |
それぞれのメニューのタブにハンドルが割り振られていることが確認できる |
###サブメニューのサブメニューを取得する
winapi.py
import win32gui
import win32con
def run():
p_hWnd = win32gui.FindWindow(None,"(無題)1 - sakura 2.2.0.1 ") # 親ウィンドウハンドル(識別番号)を取得
win32gui.SetForegroundWindow(p_hWnd) # アプリケーションをデスクトップの前面に表示
p_menu_hWnd = win32gui.GetMenu(p_hWnd) # メニューバーのハンドルを取得
p_menu_count = win32gui.GetMenuItemCount(p_menu_hWnd) # メニューバー内のサブメニューの個数を取得
# 各サブメニューのハンドルを取得
s_menu_dict = {}
for i in range(p_menu_count):
s_menu_dict["s_menu_pos{}".format(i)] = win32gui.GetSubMenu(p_menu_hWnd, i)
[print(k,v) for k,v in s_menu_dict.items()] # サブメニュー辞書確認
# 編集(E)メニューのサブメニューのIDを取得
edit_menu = s_menu_dict["s_menu_pos1"] # 編集(E)はpos1
edit_menu_count = win32gui.GetMenuItemCount(edit_menu) # 編集メニュー内のサブメニューの個数を取得
edit_menu_dict = {}
for i in range(edit_menu_count):
s_menu_list = [win32gui.GetMenuItemID(edit_menu, i), win32gui.GetSubMenu(edit_menu, i)]
edit_menu_dict["edit_menu_pos{}".format(i)] = s_menu_list
[print(k,v) for k,v in edit_menu_dict.items()]
if __name__ == '__main__':
run()
- 編集メニューのIDとサブメニューの例(存在しない場合は0)
編集メニュー | 位置 | ID | SubMenu hWnd |
---|---|---|---|
元に戻す(U) | 0 | 30210 | 0 |
やり直し(R) | 1 | 30211 | 0 |
(セパレーター) | 2 | 0 | 0 |
切り取り(T) | 3 | 30601 | 0 |
コピー(C) | 4 | 30602 | 0 |
貼り付け(P) | 5 | 30604 | 0 |
削除(D) | 6 | 30221 | 0 |
すべて選択(A) | 7 | 30401 | 0 |
(セパレーター) | 8 | 0 | 0 |
再変換(R) | 9 | 30285 | 0 |
(セパレーター) | 10 | 0 | 0 |
CRLF改行でコピー(L) | 11 | 30603 | 0 |
折り返し位置に改行をつけてコピー(H) | 12 | 30608 | 0 |
矩形貼り付け(X) | 13 | 30605 | 0 |
カーソル前を削除(B) | 14 | 30222 | 0 |
(セパレーター) | 15 | 0 | 0 |
挿入(I) | 16 | -1 | 1903099 |
高度な操作(V) | 17 | -1 | 57936345 |
移動(O) | 18 | -1 | 120392207 |
選択(S) | 19 | -1 | 56298477 |
矩形選択(F) | 20 | -1 | 290589067 |
整形(K) | 21 | -1 | 162268843 |
このIDに対してwin32com.SendMessage() が実行できる |
|||
ここでIDの取得に失敗して-1が返されているメニューはサブメニューが存在する | |||
今回は日付挿入がしたいので、挿入(I) メニューのサブメニューからIDを取得する |
###日付挿入メニューを実行する
winapi.py
import win32gui
import win32con
def run():
p_hWnd = win32gui.FindWindow(None,"(無題)1 - sakura 2.2.0.1 ") # 親ウィンドウハンドル(識別番号)を取得
win32gui.SetForegroundWindow(p_hWnd) # アプリケーションをデスクトップの前面に表示
p_menu_hWnd = win32gui.GetMenu(p_hWnd) # メニューバーのハンドルを取得
p_menu_count = win32gui.GetMenuItemCount(p_menu_hWnd) # メニューバー内のサブメニューの個数を取得
# 各サブメニューのハンドルを取得
s_menu_dict = {}
for i in range(p_menu_count):
s_menu_dict["s_menu_pos{}".format(i)] = win32gui.GetSubMenu(p_menu_hWnd, i)
[print(k,v) for k,v in s_menu_dict.items()] # サブメニュー辞書確認
# 編集(E)メニューのサブメニューのIDを取得
edit_menu = s_menu_dict["s_menu_pos1"] # 編集(E)はpos1
edit_menu_count = win32gui.GetMenuItemCount(edit_menu) # 編集メニュー内のサブメニューの個数を取得
edit_menu_dict = {}
for i in range(edit_menu_count):
s_menu_list = [win32gui.GetMenuItemID(edit_menu, i), win32gui.GetSubMenu(edit_menu, i)]
edit_menu_dict["edit_menu_pos{}".format(i)] = s_menu_list
[print(k,v) for k,v in edit_menu_dict.items()]
# 挿入(I)メニューのサブメニューのIDを取得する
ins_menu = edit_menu_dict["edit_menu_pos16"][1] # 挿入(I)はpos16
ins_menu_count = win32gui.GetMenuItemCount(ins_menu) # 挿入メニュー内のサブメニューの個数を取得
ins_menu_dict = {}
for i in range(ins_menu_count):
ins_menu_dict["ins_menu_pos{}".format(i)] = win32gui.GetMenuItemID(ins_menu,i)
[print(k,v) for k,v in ins_menu_dict.items()]
# 日付挿入を実行
win32gui.SendMessage(p_hWnd, win32con.WM_COMMAND, ins_menu_dict["ins_menu_pos0"], p_menu_hWnd) # 日付挿入(D)はpos0
if __name__ == '__main__':
run()
- 挿入メニューのIDの例
挿入メニュー | 位置 | ID |
---|---|---|
日付挿入(D) | 0 | 30790 |
時刻挿入(T) | 1 | 30791 |
コントロールコード入力(C) | 2 | 30792 |
ようやく目的のメニューIDを確認できた |
- SendMessageの引数は下記のようにする
win32gui.SendMessage([親ウィンドウハンドル],[win32con.WM_COMMAND],[対象メニューのID],[メニューバーのハンドル])
とまあ、今回はこのくらいで終わり
##まとめ
メニューバーのハンドル値やIDをprint文で確認しながらなんとかサブメニューのサブメニューまで操作する方法は確認できましたが、メニューのテキストを直接参照できたらもう少し読み易くなると思いますね
前回の記事 | [次回の記事]