Pythonでホットキーを取得する方法 – pywin32とwindowprocを使った画面外ショートカットキー

この記事では、PythonでWindowsのショートカットキーを、実行画面以外から取得する方法を紹介します。pywin32とwindowprocを使った方法で、他のアプリにフォーカスが当たっていても、Pythonアプリでキー入力を取得できます。

ホットキーとは

ホットキーとは、特定のキーとウィンドウ(アプリ)でWindowsに対して登録しておくと、どのような画面にいてもそのアプリでのキー入力をキャンセルし、登録したウィンドウのWM_HOTKEYとして通知されるものです。

ショートカットキーとの違い

ホットキーは、フォーカスが当たっているアプリ内でのみ動作するキー入力イベントであるショートカットキーとは異なります。

ライブラリのインストール

今回のプログラムでは、Windowsから通知を受け取るためにpywin32ライブラリをインストールする必要があります。

pip install pywin32

プログラム全体

import threading 
from ctypes import *          # windll 使用のため
from ctypes.wintypes import * # handle取得のため
import win32api,win32gui,win32con # win32のAPI使用のため

#ホットキーIDは このプログラムで使用するための物なので適当な値を設定する
#0x0000-0xBFFFの間で設定
HOTKEY_ID_1 = 0x0001
exit_flg = False

def Regist_selfhotkey():
    global exit_flg
    try:
        hInstance  = win32api.GetModuleHandle(None)
        CLASS_NAME   = "myAppl"
        lpWindowName = CLASS_NAME
        
        wc = win32gui.WNDCLASS()
        wc.lpfnWndProc = WindowProc
        wc.hInstance = hInstance
        wc.lpszClassName = CLASS_NAME
        win32gui.RegisterClass(wc)
        
        hwnd = win32gui.CreateWindowEx(0,CLASS_NAME,lpWindowName,win32con.WS_OVERLAPPEDWINDOW,
                                       win32con.CW_USEDEFAULT,win32con.CW_USEDEFAULT,win32con.CW_USEDEFAULT,
                                       win32con.CW_USEDEFAULT,None,None,hInstance,None)
        
        if hwnd != None:
            windll.user32.RegisterHotKey(hwnd,HOTKEY_ID_1,win32con.MOD_CONTROL | win32con.MOD_SHIFT,0x41)

        msg = MSG()
        while (windll.user32.GetMessageW(pointer(msg),0,0,0)):
            windll.user32.TranslateMessage(pointer(msg))
            windll.user32.DispatchMessageW(pointer(msg))
            if exit_flg == True:
                break
    finally:
        windll.user32.UnregisterHotKey(None,HOTKEY_ID_1)    
    

def WindowProc(hwnd,uMsg,wParam,lPram):
    global exit_flg
    if uMsg == win32con.WM_HOTKEY:
        if wParam == HOTKEY_ID_1:
            print("receive Ctrl Shift A")
            exit_flg = True
    return windll.user32.DefWindowProcW(hwnd,uMsg,wParam,lPram)

def main():
    Regist_selfhotkey()
    

if __name__ == '__main__':
    main()

プログラム解説

ライブラリのインポート

今回のプログラムに必要なライブラリは以下の3つです。

  • ctypes: windll 使用のため
  • ctypes.wintypes: handle取得のため
  • win32api, win32gui, win32con: win32のAPI使用のため

ホットキーの登録

ホットキーIDの設定

# ホットキーIDは このプログラムで使用するための物なので適当な値を設定する
# 0x0000-0xBFFFの間で設定
HOTKEY_ID_1 = 0x0001

アプリの名前登録

CLASS_NAME   = "myAppl"
lpWindowName = CLASS_NAME

ホットキー登録処理

hInstance  = win32api.GetModuleHandle(None)
wc = win32gui.WNDCLASS()
wc.lpfnWndProc = WindowProc
wc.hInstance = hInstance
wc.lpszClassName = CLASS_NAME
win32gui.RegisterClass(wc)

hwnd = win32gui.CreateWindowEx(0, CLASS_NAME, lpWindowName, win32con.WS_OVERLAPPEDWINDOW,
                                win32con.CW_USEDEFAULT, win32con.CW_USEDEFAULT, win32con.CW_USEDEFAULT,
                                win32con.CW_USEDEFAULT, None, None, hInstance, None)

if hwnd != None:
    windll.user32.RegisterHotKey(hwnd, HOTKEY_ID_1,
                                win32con.MOD_CONTROL | win32con.MOD_SHIFT, 0x41)

メッセージの取得処理

msg = MSG()
while (windll.user32.GetMessageW(pointer(msg), 0, 0, 0)):
    windll.user32.TranslateMessage(pointer(msg))
    windll.user32.DispatchMessageW(pointer(msg))
    if exit_flg == True:
        break

コールバック処理

def WindowProc(hwnd, uMsg, wParam, lPram):
    global exit_flg
    if uMsg == win32con.WM_HOTKEY:
        if wParam == HOTKEY_ID_1:
            print("receive Ctrl Shift A")
            exit_flg = True
    return windll.user32.DefWindowProcW(hwnd, uMsg, wParam, lPram)

まとめ

この記事では、PythonでWindowsのショートカットキーを、実行画面以外から取得する方法を紹介しました。pywin32とwindowprocを使った方法で、他のアプリにフォーカスが当たっていても、Pythonアプリでキー入力を取得できます。


関連する記事

参考資料

注意

ホットキーの登録は、プログラムが終了するまで有効です。

このプログラムはWindowsのみで動作します。

プログラムを実行する前に、pywin32ライブラリをインストールしてください。

この記事がお役に立てれば幸いです!!

最後に、Pythonの基礎を学びたい方は以下がおすすめです。私も持っていてたまに眺めて勉強していますものですのでぜひ購入して学習してみてください。

にいやん

出身 : 関西 居住区 : 関西 職業 : 組み込み機器エンジニア (エンジニア歴13年) 年齢 : 38歳(2022年11月現在) 最近 業務の効率化で噂もありPython言語に興味を持ち勉強しています。 そこで学んだことを記事にして皆さんとシェアさせていただければと思いブログをはじめました!! 興味ある記事があれば皆さん見ていってください!! にほんブログ村