Как в питоне имитировать нажатие на клавиатуре кнопок со стрелками

Пытаюсь сделать скрипт для автоматизации действий в компьютерной игре. Короче - скрипт должен жать кнопки вместо меня, в результате в игре (которую не я написал, я просто игрок) происходят некие действия.

Вот такой код:

    import time
    import keyboard
    time.sleep(1)
    keyboard.send('enter')
    time.sleep(0.2)
    keyboard.press('down')
    time.sleep(0.2)
    keyboard.release('down')
    time.sleep(0.2)
    keyboard.press('down')
    time.sleep(0.2)
    keyboard.release('down')
    time.sleep(0.2)

работает некорректно. Игра воспринимает стрелки как стрелки, нажатые на цифровой клавиатуре. А нужны обычные стрелки.

Что можно сделать? Может быть стоит использовать другой модуль эмуляции клавиатуры?


Ответы (5 шт):

Автор решения: Amgarak

Как вариант, попробуйте использовать event

Если защита в игре так себе, то может и сработать...а может и не сработать.

import ctypes
import time

# Константы для keybd_event
VK_UP = 0x26  # Клавиша вверх
VK_DOWN = 0x28  # Клавиша вниз

# Эмуляция нажатия и отпускания клавиши вверх
ctypes.windll.user32.keybd_event(VK_UP, 0, 0, 0)
time.sleep(0.1)
ctypes.windll.user32.keybd_event(VK_UP, 0, 2, 0)

time.sleep(0.1)

# Эмуляция нажатия и отпускания клавиши вниз
ctypes.windll.user32.keybd_event(VK_DOWN, 0, 0, 0)
time.sleep(0.1)
ctypes.windll.user32.keybd_event(VK_DOWN, 0, 2, 0)

Для других клавиш используйте соответствующие коды: https://narvell.nl/keys

→ Ссылка
Автор решения: Amgarak

Можно попробовать использовать SendInput, для этих целей у меня есть вот такой класс:

import ctypes
import time

class InputSimulator:
    def __init__(self):
        # Константы для ввода мыши
        self.WHEEL_DELTA = 120
        self.XBUTTON1 = 0x0001
        self.XBUTTON2 = 0x0002
        self.MOUSEEVENTF_ABSOLUTE = 0x8000
        self.MOUSEEVENTF_HWHEEL = 0x01000
        self.MOUSEEVENTF_MOVE = 0x0001
        self.MOUSEEVENTF_MOVE_NOCOALESCE = 0x2000
        self.MOUSEEVENTF_LEFTDOWN = 0x0002
        self.MOUSEEVENTF_LEFTUP = 0x0004
        self.MOUSEEVENTF_RIGHTDOWN = 0x0008
        self.MOUSEEVENTF_RIGHTUP = 0x0010
        self.MOUSEEVENTF_MIDDLEDOWN = 0x0020
        self.MOUSEEVENTF_MIDDLEUP = 0x0040
        self.MOUSEEVENTF_VIRTUALDESK = 0x4000
        self.MOUSEEVENTF_WHEEL = 0x0800
        self.MOUSEEVENTF_XDOWN = 0x0080
        self.MOUSEEVENTF_XUP = 0x0100

        # Константы для типов ввода
        self.INPUT_MOUSE = 0
        self.INPUT_KEYBOARD = 1
        self.INPUT_HARDWARE = 2

        # Коды клавиш
        self.VK_LBUTTON = 0x01               # Left mouse button
        self.VK_RBUTTON = 0x02               # Right mouse button
        self.VK_CANCEL = 0x03                # Control-break processing
        self.VK_MBUTTON = 0x04               # Middle mouse button (three-button mouse)
        self.VK_XBUTTON1 = 0x05              # X1 mouse button
        self.VK_XBUTTON2 = 0x06              # X2 mouse button
        self.VK_BACK = 0x08                  # BACKSPACE key
        self.VK_TAB = 0x09                   # TAB key
        self.VK_CLEAR = 0x0C                 # CLEAR key
        self.VK_RETURN = 0x0D                # ENTER key
        self.VK_SHIFT = 0x10                 # SHIFT key
        self.VK_CONTROL = 0x11               # CTRL key
        self.VK_MENU = 0x12                  # ALT key
        self.VK_PAUSE = 0x13                 # PAUSE key
        self.VK_CAPITAL = 0x14               # CAPS LOCK key
        self.VK_KANA = 0x15                  # IME Kana mode
        self.VK_HANGUL = 0x15                # IME Hangul mode
        self.VK_JUNJA = 0x17                 # IME Junja mode
        self.VK_FINAL = 0x18                 # IME final mode
        self.VK_HANJA = 0x19                 # IME Hanja mode
        self.VK_KANJI = 0x19                 # IME Kanji mode
        self.VK_ESCAPE = 0x1B                # ESC key
        self.VK_CONVERT = 0x1C               # IME convert
        self.VK_NONCONVERT = 0x1D            # IME nonconvert
        self.VK_ACCEPT = 0x1E                # IME accept
        self.VK_MODECHANGE = 0x1F            # IME mode change request
        self.VK_SPACE = 0x20                 # SPACEBAR
        self.VK_PRIOR = 0x21                 # PAGE UP key
        self.VK_NEXT = 0x22                  # PAGE DOWN key
        self.VK_END = 0x23                   # END key
        self.VK_HOME = 0x24                  # HOME key
        self.VK_LEFT = 0x25                  # LEFT ARROW key
        self.VK_UP = 0x26                    # UP ARROW key
        self.VK_RIGHT = 0x27                 # RIGHT ARROW key
        self.VK_DOWN = 0x28                  # DOWN ARROW key
        self.VK_SELECT = 0x29                # SELECT key
        self.VK_PRINT = 0x2A                 # PRINT key
        self.VK_EXECUTE = 0x2B               # EXECUTE key
        self.VK_SNAPSHOT = 0x2C              # PRINT SCREEN key
        self.VK_INSERT = 0x2D                # INS key
        self.VK_DELETE = 0x2E                # DEL key
        self.VK_HELP = 0x2F                  # HELP key
        self.VK_LWIN = 0x5B                  # Left Windows key (Natural keyboard)
        self.VK_RWIN = 0x5C                  # Right Windows key (Natural keyboard)
        self.VK_APPS = 0x5D                  # Applications key (Natural keyboard)
        self.VK_SLEEP = 0x5F                 # Computer Sleep key
        self.VK_NUMPAD0 = 0x60               # Numeric keypad 0 key
        self.VK_NUMPAD1 = 0x61               # Numeric keypad 1 key
        self.VK_NUMPAD2 = 0x62               # Numeric keypad 2 key
        self.VK_NUMPAD3 = 0x63               # Numeric keypad 3 key
        self.VK_NUMPAD4 = 0x64               # Numeric keypad 4 key
        self.VK_NUMPAD5 = 0x65               # Numeric keypad 5 key
        self.VK_NUMPAD6 = 0x66               # Numeric keypad 6 key
        self.VK_NUMPAD7 = 0x67               # Numeric keypad 7 key
        self.VK_NUMPAD8 = 0x68               # Numeric keypad 8 key
        self.VK_NUMPAD9 = 0x69               # Numeric keypad 9 key
        self.VK_MULTIPLY = 0x6A              # Multiply key
        self.VK_ADD = 0x6B                   # Add key
        self.VK_SEPARATOR = 0x6C             # Separator key
        self.VK_SUBTRACT = 0x6D              # Subtract key
        self.VK_DECIMAL = 0x6E               # Decimal key
        self.VK_DIVIDE = 0x6F                # Divide key
        self.VK_F1 = 0x70                    # F1 key
        self.VK_F2 = 0x71                    # F2 key
        self.VK_F3 = 0x72                    # F3 key
        self.VK_F4 = 0x73                    # F4 key
        self.VK_F5 = 0x74                    # F5 key
        self.VK_F6 = 0x75                    # F6 key
        self.VK_F7 = 0x76                    # F7 key
        self.VK_F8 = 0x77                    # F8 key
        self.VK_F9 = 0x78                    # F9 key
        self.VK_F10 = 0x79                   # F10 key
        self.VK_F11 = 0x7A                   # F11 key
        self.VK_F12 = 0x7B                   # F12 key
        self.VK_F13 = 0x7C                   # F13 key
        self.VK_F14 = 0x7D                   # F14 key
        self.VK_F15 = 0x7E                   # F15 key
        self.VK_F16 = 0x7F                   # F16 key
        self.VK_F17 = 0x80                   # F17 key
        self.VK_F18 = 0x81                   # F18 key
        self.VK_F19 = 0x82                   # F19 key
        self.VK_F20 = 0x83                   # F20 key
        self.VK_F21 = 0x84                   # F21 key
        self.VK_F22 = 0x85                   # F22 key
        self.VK_F23 = 0x86                   # F23 key
        self.VK_F24 = 0x87                   # F24 key
        self.VK_NUMLOCK = 0x90               # NUM LOCK key
        self.VK_SCROLL = 0x91                # SCROLL LOCK key
        self.VK_LSHIFT = 0xA0                # Left SHIFT key
        self.VK_RSHIFT = 0xA1                # Right SHIFT key
        self.VK_LCONTROL = 0xA2              # Left CONTROL key
        self.VK_RCONTROL = 0xA3              # Right CONTROL key
        self.VK_LMENU = 0xA4                 # Left MENU key
        self.VK_RMENU = 0xA5                 # Right MENU key
        self.VK_BROWSER_BACK = 0xA6          # Browser Back key
        self.VK_BROWSER_FORWARD = 0xA7       # Browser Forward key
        self.VK_BROWSER_REFRESH = 0xA8       # Browser Refresh key
        self.VK_BROWSER_STOP = 0xA9          # Browser Stop key
        self.VK_BROWSER_SEARCH = 0xAA        # Browser Search key
        self.VK_BROWSER_FAVORITES = 0xAB     # Browser Favorites key
        self.VK_BROWSER_HOME = 0xAC          # Browser Start and Home key
        self.VK_VOLUME_MUTE = 0xAD           # Volume Mute key
        self.VK_VOLUME_DOWN = 0xAE           # Volume Down key
        self.VK_VOLUME_UP = 0xAF             # Volume Up key
        self.VK_MEDIA_NEXT_TRACK = 0xB0      # Next Track key
        self.VK_MEDIA_PREV_TRACK = 0xB1      # Previous Track key
        self.VK_MEDIA_STOP = 0xB2            # Stop Media key
        self.VK_MEDIA_PLAY_PAUSE = 0xB3      # Play/Pause Media key
        self.VK_LAUNCH_MAIL = 0xB4           # Start Mail key
        self.VK_LAUNCH_MEDIA_SELECT = 0xB5   # Select Media key
        self.VK_LAUNCH_APP1 = 0xB6           # Start Application 1 key
        self.VK_LAUNCH_APP2 = 0xB7           # Start Application 2 key
        self.VK_OEM_1 = 0xBA                 # Used for miscellaneous characters; it can vary by keyboard.
                                        # For the US standard keyboard, the ';:' key
        self.VK_OEM_PLUS = 0xBB              # For any country/region, the '+' key
        self.VK_OEM_COMMA = 0xBC             # For any country/region, the ',' key
        self.VK_OEM_MINUS = 0xBD             # For any country/region, the '-' key
        self.VK_OEM_PERIOD = 0xBE            # For any country/region, the '.' key
        self.VK_OEM_2 = 0xBF                 # Used for miscellaneous characters; it can vary by keyboard.
                                        # For the US standard keyboard, the '/?' key
        self.VK_OEM_3 = 0xC0                 # Used for miscellaneous characters; it can vary by keyboard.
                                        # For the US standard keyboard, the '`~' key
        self.VK_OEM_4 = 0xDB                 # Used for miscellaneous characters; it can vary by keyboard.
                                        # For the US standard keyboard, the '[{' key
        self.VK_OEM_5 = 0xDC                 # Used for miscellaneous characters; it can vary by keyboard.
                                        # For the US standard keyboard, the '\|' key
        self.VK_OEM_6 = 0xDD                 # Used for miscellaneous characters; it can vary by keyboard.
                                        # For the US standard keyboard, the ']}' key
        self.VK_OEM_7 = 0xDE                 # Used for miscellaneous characters; it can vary by keyboard.
                                        # For the US standard keyboard, the 'single-quote/double-quote' key
        self.VK_OEM_8 = 0xDF                 # Used for miscellaneous characters; it can vary by keyboard.
        self.VK_OEM_102 = 0xE2               # Either the angle bracket key or the backslash key on the RT 102-key keyboard
        self.VK_PROCESSKEY = 0xE5            # IME PROCESS key
        self.VK_PACKET = 0xE7                # Used to pass Unicode characters as if they were keystrokes. The VK_PACKET key is the low word of a 32-bit Virtual Key value used for non-keyboard input methods. For more information, see Remark in KEYBDINPUT, SendInput, WM_KEYDOWN, and WM_KEYUP
        self.VK_ATTN = 0xF6                  # Attn key
        self.VK_CRSEL = 0xF7                 # CrSel key
        self.VK_EXSEL = 0xF8                 # ExSel key
        self.VK_EREOF = 0xF9                 # Erase EOF key
        self.VK_PLAY = 0xFA                  # Play key
        self.VK_ZOOM = 0xFB                  # Zoom key
        self.VK_PA1 = 0xFD                   # PA1 key
        self.VK_OEM_CLEAR = 0xFE             # Clear key

        # Константы для ввода клавиатуры
        self.KEYEVENTF_EXTENDEDKEY = 0x0001
        self.KEYEVENTF_KEYUP = 0x0002
        self.KEYEVENTF_SCANCODE = 0x0008
        self.KEYEVENTF_UNICODE = 0x0004

        self.KEY_0 = 0x30
        self.KEY_1 = 0x31
        self.KEY_2 = 0x32
        self.KEY_3 = 0x33
        self.KEY_4 = 0x34
        self.KEY_5 = 0x35
        self.KEY_6 = 0x36
        self.KEY_7 = 0x37
        self.KEY_8 = 0x38
        self.KEY_9 = 0x39
        self.KEY_A = 0x41
        self.KEY_B = 0x42
        self.KEY_C = 0x43
        self.KEY_D = 0x44
        self.KEY_E = 0x45
        self.KEY_F = 0x46
        self.KEY_G = 0x47
        self.KEY_H = 0x48
        self.KEY_I = 0x49
        self.KEY_J = 0x4A
        self.KEY_K = 0x4B
        self.KEY_L = 0x4C
        self.KEY_M = 0x4D
        self.KEY_N = 0x4E
        self.KEY_O = 0x4F
        self.KEY_P = 0x50
        self.KEY_Q = 0x51
        self.KEY_R = 0x52
        self.KEY_S = 0x53
        self.KEY_T = 0x54
        self.KEY_U = 0x55
        self.KEY_V = 0x56
        self.KEY_W = 0x57
        self.KEY_X = 0x58
        self.KEY_Y = 0x59
        self.KEY_Z = 0x5A

        # Объявление структур
        class MOUSEINPUT(ctypes.Structure):
            _fields_ = [
                ('dx', ctypes.c_long),
                ('dy', ctypes.c_long),
                ('mouseData', ctypes.c_ulong),
                ('dwFlags', ctypes.c_ulong),
                ('time', ctypes.c_ulong),
                ('dwExtraInfo', ctypes.POINTER(ctypes.c_ulong))
            ]

        class KEYBDINPUT(ctypes.Structure):
            _fields_ = [
                ('wVk', ctypes.c_ushort),
                ('wScan', ctypes.c_ushort),
                ('dwFlags', ctypes.c_ulong),
                ('time', ctypes.c_ulong),
                ('dwExtraInfo', ctypes.POINTER(ctypes.c_ulong))
            ]

        class HARDWAREINPUT(ctypes.Structure):
            _fields_ = [
                ('uMsg', ctypes.c_ulong),
                ('wParamL', ctypes.c_ushort),
                ('wParamH', ctypes.c_ushort)
            ]

        class _INPUTunion(ctypes.Union):
            _fields_ = [
                ('mi', MOUSEINPUT),
                ('ki', KEYBDINPUT),
                ('hi', HARDWAREINPUT)
            ]

        class INPUT(ctypes.Structure):
            _fields_ = [
                ('type', ctypes.c_ulong),
                ('union', _INPUTunion)
            ]

        self.MOUSEINPUT = MOUSEINPUT
        self.KEYBDINPUT = KEYBDINPUT
        self.HARDWAREINPUT = HARDWAREINPUT
        self._INPUTunion = _INPUTunion
        self.INPUT = INPUT

    def SendInput(self, *inputs):
        nInputs = len(inputs)
        LPINPUT = self.INPUT * nInputs
        pInputs = LPINPUT(*inputs)
        cbSize = ctypes.c_int(ctypes.sizeof(inputs[0]))
        return ctypes.windll.user32.SendInput(nInputs, pInputs, cbSize)

    def MouseInput(self, flags, x, y, data):
        return self.MOUSEINPUT(x, y, data, flags, 0, None)

    def KeybdInput(self, code, flags):
        return self.KEYBDINPUT(code, code, flags, 0, None)

    def HardwareInput(self, message, parameter):
        return self.HARDWAREINPUT(message & 0xFFFFFFFF, parameter & 0xFFFF, parameter >> 16 & 0xFFFF)

    def Mouse(self, flags, x=0, y=0, data=0):
        return self.INPUT(self.INPUT_MOUSE, self._INPUTunion(mi=self.MouseInput(flags, x, y, data)))

    def Keyboard(self, code, flags=0):
        return self.INPUT(self.INPUT_KEYBOARD, self._INPUTunion(ki=self.KeybdInput(code, flags)))

    def Hardware(self, message, parameter=0):
        return self.INPUT(self.INPUT_HARDWARE, self._INPUTunion(hi=self.HardwareInput(message, parameter)))

input_simulator = InputSimulator()

# Ожидание некоторого времени перед выполнением симуляции, чтобы у вас было время подвести мышь
time.sleep(5)
# Симуляция нажатия левой кнопки мыши
input_simulator.SendInput(input_simulator.Mouse(input_simulator.MOUSEEVENTF_LEFTDOWN))
# Ожидание перед отпусканием кнопки мыши
time.sleep(0.1)
# Симуляция отпускания левой кнопки мыши
input_simulator.SendInput(input_simulator.Mouse(input_simulator.MOUSEEVENTF_LEFTUP))
time.sleep(0.1)
# Симуляция нажатия левой кнопки мыши
input_simulator.SendInput(input_simulator.Mouse(input_simulator.MOUSEEVENTF_LEFTDOWN))
# Ожидание перед отпусканием кнопки мыши
time.sleep(0.1)
# Симуляция отпускания левой кнопки мыши
input_simulator.SendInput(input_simulator.Mouse(input_simulator.MOUSEEVENTF_LEFTUP))

# Ожидание перед симуляцией движения мыши (абсолютное)
time.sleep(0.1)
# Симуляция абсолютного движения мыши в точку (500, 500)
input_simulator.SendInput(input_simulator.Mouse(input_simulator.MOUSEEVENTF_MOVE | input_simulator.MOUSEEVENTF_ABSOLUTE, 500, 500, 0))

# Ожидание перед симуляцией относительного движения мыши
time.sleep(0.1)
# Симуляция относительного движения мыши на 50 пикселей вправо и 50 пикселей вниз от текущей позиции
input_simulator.SendInput(input_simulator.Mouse(input_simulator.MOUSEEVENTF_MOVE, 50, 50, 0))

# Ожидание перед симуляцией нажатия клавиши вверх
time.sleep(0.1)
# Симуляция нажатия клавиши вверх
input_simulator.SendInput(input_simulator.Keyboard(input_simulator.VK_UP))
# Ожидание перед отпусканием клавиши вверх
time.sleep(0.1)
# Симуляция отпускания клавиши вверх
input_simulator.SendInput(input_simulator.Keyboard(input_simulator.VK_UP, input_simulator.KEYEVENTF_KEYUP))

# Ожидание перед симуляцией нажатия клавиши вниз
time.sleep(0.1)
# Симуляция нажатия клавиши вниз
input_simulator.SendInput(input_simulator.Keyboard(input_simulator.VK_DOWN))
# Ожидание перед отпусканием клавиши вниз
time.sleep(0.1)
# Симуляция отпускания клавиши вниз
input_simulator.SendInput(input_simulator.Keyboard(input_simulator.VK_DOWN, input_simulator.KEYEVENTF_KEYUP))

→ Ссылка
Автор решения: Amgarak

Есть интересный проект AutoHotkey

Для версии 1.1 есть библиотека на питоне pip install ahk

Вот вам небольшой пример как можно с ней работать:

import ahk

# Скрипт AutoHotKey в переменной
ahk_script = """
Menu, Tray, NoIcon ;

#Persistent ; Скрипт остается активным

; Ждем 5 секунд
Sleep, 5000

Send, {F1 down}
Sleep, 2000 ; Удерживаем 'F1' в течение 2 секунд

Send, {F1 up}

; Завершаем скрипт
ExitApp
"""

# Запустите скрипт AutoHotKey
ahk.run_script(ahk_script)
→ Ссылка
Автор решения: Amgarak

Последний вариант - это использовать дескриптор окна и посылать команды непосредственно в него:

pip install pywin32

import win32gui
import win32api
import win32con

set_hwnd = "Notepad"
hwnd = win32gui.FindWindow(None, set_hwnd)
if hwnd == 0:
    print("Окно не найдено!\n")

lParam = win32api.MAKELONG(0, 0)
win32api.PostMessage(hwnd, win32con.WM_LBUTTONDOWN, win32con.MK_LBUTTON, lParam)
win32api.PostMessage(hwnd, win32con.WM_LBUTTONUP, 0, lParam)

Вместо PostMessage можно использовать SendMessage.

win32api.SendMessage(hwnd, win32con.WM_MOUSEMOVE, 0, lParam)

Разница между ними в том, что SendMessage отправляет сообщение и ожидает, пока окно-получатель сообщение обработает, а PostMessage просто установит сообщение в очередь.

Примерно так же, можно отправлять нажатия клавиш клавиатуры.

→ Ссылка
Автор решения: Amgarak

Самым крайним решением можно считать usb-устройство, которое можно запрограммировать на подачу нужного сигнала — Digispark.

pip install digispark

введите сюда описание изображения

Цена вопроса: ~500р

→ Ссылка