みやまのアトリエ

スマホアプリ開発 ペンタブ備忘録 お絵描き

pyautoguiで押したキーボードイベントが異なる記号になる問題の解決方法

 pyautoguiを使用していると、「@」「^」「:」のキーボードイベント入力が「`」 「~」「*」になる場合があります。

 

 例えば、Pythonコード中で、

keyDown('@')

 

 と記述すると、当然メモ帳等で「@」と入力してほしいのですが…

 実際には「`」が入力されてしまったり…。「シフトキー」が押された状態で入力されているようです。

 

この問題、日本語キーボードを使用している場合に発生するようです。

 

 

解決方法

 以下のファイルを修正します。IDLEなどのエディタで開いてください。

 

C:\Users\(ユーザー名)\AppData\Local\Programs\Python\ (Pythonのバージョン)\Lib\site-packages\pyautogui\_pyautogui_win.py

 

修正箇所

 関数「def _keyDown(key):」の中身を修正します。

 

(略)

    needsShift = pyautogui.isShiftCharacter(key)

 

    # 以下の3文を追加します----------

    if key == '@': needsShift = False

    if key == '^': needsShift = False

    if key == ':': needsShift = False  

    #追加、ここまで--------------------

 

(略)

 

 

関数「def_keyDown(key)」全体は以下のようになります。


修正前 

def _keyDown(key):
    """Performs a keyboard key press without the release. This will put that
    key in a held down state.

 

    NOTE: For some reason, this does not seem to cause key repeats like would
    happen if a keyboard key was held down on a text field.          Args:
        key (str): The key to be pressed down. The valid names are listed in
        pyautogui.KEY_NAMES.

 

    Returns:
        None
    """
    if key not in keyboardMapping or keyboardMapping[key] is None:
        return

 

    needsShift = pyautogui.isShiftCharacter(key)  
    """
    # OLD CODE: The new code relies on having all keys be loaded in   keyboardMapping from the start.
    if key in keyboardMapping.keys():
        vkCode = keyboardMapping[key]
    elif len(key) == 1:
# note: I could use this case to update keyboardMapping to cache the VkKeyScan results, but I've decided not to just to make any possible bugs easier to reproduce.
        vkCode = ctypes.windll.user32.VkKeyScanW(ctypes.wintypes.WCHAR(key))
        if vkCode == -1:
            raise ValueError('There is no VK code for key "%s"' % (key))
        if vkCode > 0x100: # the vk code will be > 0x100 if it needs shift
            vkCode -= 0x100
            needsShift = True
   """
    mods, vkCode = divmod(keyboardMapping[key], 0x100)

 

    for apply_mod, vk_mod in [(mods & 4, 0x12), (mods & 2, 0x11),
        (mods & 1 or needsShift, 0x10)]: #HANKAKU not suported! mods & 8
        if apply_mod:
            ctypes.windll.user32.keybd_event(vk_mod, 0, 0, 0) #
    ctypes.windll.user32.keybd_event(vkCode, 0, 0, 0)
    for apply_mod, vk_mod in [(mods & 1 or needsShift, 0x10), (mods & 2, 0x11),
        (mods & 4, 0x12)]: #HANKAKU not suported! mods & 8
        if apply_mod:
            ctypes.windll.user32.keybd_event(vk_mod, 0, KEYEVENTF_KEYUP, 0)

 


修正後

 def _keyDown(key):
    """Performs a keyboard key press without the release. This will put that
    key in a held down state.

 

    NOTE: For some reason, this does not seem to cause key repeats like would
    happen if a keyboard key was held down on a text field.

 

    Args:
        key (str): The key to be pressed down. The valid names are listed in
        pyautogui.KEY_NAMES.

 

    Returns:
        None
    """
    if key not in keyboardMapping or keyboardMapping[key] is None:
        return

 

    needsShift = pyautogui.isShiftCharacter(key)

 

    # 以下の3文を追加します----------
    if key == '@': needsShift = False
    if key == '^': needsShift = False
    if key == ':': needsShift = False  
    #追加、ここまで--------------------


    """
    # OLD CODE: The new code relies on having all keys be loaded in   keyboardMapping from the start.
    if key in keyboardMapping.keys():
        vkCode = keyboardMapping[key]
    elif len(key) == 1:
# note: I could use this case to update keyboardMapping to cache the VkKeyScan results, but I've decided not to just to make any possible bugs easier to reproduce.
        vkCode = ctypes.windll.user32.VkKeyScanW(ctypes.wintypes.WCHAR(key))
        if vkCode == -1:
            raise ValueError('There is no VK code for key "%s"' % (key))
        if vkCode > 0x100: # the vk code will be > 0x100 if it needs shift
            vkCode -= 0x100
            needsShift = True
   """
    mods, vkCode = divmod(keyboardMapping[key], 0x100)

 

    for apply_mod, vk_mod in [(mods & 4, 0x12), (mods & 2, 0x11),
        (mods & 1 or needsShift, 0x10)]: #HANKAKU not suported! mods & 8
        if apply_mod:
            ctypes.windll.user32.keybd_event(vk_mod, 0, 0, 0) #
    ctypes.windll.user32.keybd_event(vkCode, 0, 0, 0)
    for apply_mod, vk_mod in [(mods & 1 or needsShift, 0x10), (mods & 2, 0x11),
        (mods & 4, 0x12)]: #HANKAKU not suported! mods & 8
        if apply_mod:
            ctypes.windll.user32.keybd_event(vk_mod, 0, KEYEVENTF_KEYUP, 0) #

 

 これでpyautoguiを使って「@」「^」「:」のキーボードイベント入力が正常にできるようになります。

 

以上です。