Как можно эмулировать нажатие клавиши мыши в Python, не используя при этом основной курсор?

Всем привет! У меня возникла следующая ситуация: я разрабатываю программное обеспечение для эмуляторов, и для выполнения нажатий по координатам использую следующую функцию. Она прекрасно работает на эмуляторе Nox и в обычных окнах, но на LD Player 9 (который похож на Nox, но более производительный для Android) клики по какой-то причине не регистрируются. 

Вот код функции:

<pre><code class="python">def click_on_telegram(loc, bbox, hwnd):
    if loc is None:
        print("Координаты не найдены для клика.")
        return

    x, y = loc
    window_x = bbox[0]
    window_y = bbox[1]

    click_x = window_x + x
    click_y = window_y + y

    if bbox[0] &lt;= click_x &lt;= bbox[2] and bbox[1] &lt;= click_y &lt;= bbox[3]:

        local_x = click_x - window_x
        local_y = click_y - window_y

        l_param = win32api.MAKELONG(local_x, local_y)

        win32gui.PostMessage(hwnd, win32con.WM_LBUTTONDOWN, win32con.MK_LBUTTON, l_param)
        win32gui.PostMessage(hwnd, win32con.WM_LBUTTONUP, 0, l_param)
        
        print(f"Клик по координатам внутри окна: ({local_x}, {local_y})")
    else:
        print("Координаты клика выходят за пределы окна.")</code></pre>

Я также пробовал использовать SendMessage и выполнил все основные проверки. При этом высокоуровневые библиотеки, такие как pyautogui и pynput, которые перемещают курсор к координате и выполняют клик, работают нормально. Но мне необходимо реализовать это без взаимодействия с основным курсором.

В данный момент я исследую с помощью spy++ поведение мыши и пытаюсь понять, какого параметра не хватает в win32api, чтобы клики регистрировались. Может, кто-то знает, как можно решить эту проблему? Или, возможно, потребуется написать модуль на C++?
  • 12 октября 2024 г. 11:12
Ответы на вопрос 2
Эмуляция нажатия клавиш мыши без использования основного курсора может быть сложной задачей, особенно в контексте виртуальных эмуляторов, таких как LD Player. Эти эмуляторы могут использовать собственные методы обработки ввода, которые не реагируют на стандартные оснастки Windows для эмуляции кликов. Вот несколько подходов, которые вы можете попробовать:

### 1. Использование `SendInput`
Попробуйте использовать функцию `SendInput`, которая позволяет отправлять события ввода непосредственно в систему, минуя стандартные механизмы обработки сообщений. Вот пример использования `SendInput` для выполнения кликов:

```python
import ctypes
import time

# Определите структуры для событий ввода
class INPUT(ctypes.Structure):
    _fields_ = [("type", ctypes.c_ulong),
                ("mi", ctypes.wintypes.MOUSEINPUT)]

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.c_ulong)]

# Константы для ключевых событий
INPUT_MOUSE = 0
MOUSEEVENTF_LEFTDOWN = 0x0002
MOUSEEVENTF_LEFTUP = 0x0004

def click_at(x, y):
    # Создайте событие для нажатия левой кнопки мыши
    input_down = INPUT()
    input_down.type = INPUT_MOUSE
    input_down.mi.dx = x
    input_down.mi.dy = y
    input_down.mi.dwFlags = MOUSEEVENTF_LEFTDOWN

    input_up = INPUT()
    input_up.type = INPUT_MOUSE
    input_up.mi.dx = x
    input_up.mi.dy = y
    input_up.mi.dwFlags = MOUSEEVENTF_LEFTUP

    # Отправьте события ввода
    ctypes.windll.user32.SendInput(1, ctypes.byref(input_down), ctypes.sizeof(input_down))
    ctypes.windll.user32.SendInput(1, ctypes.byref(input_up), ctypes.sizeof(input_up))

# Пример вызова по координатам
click_at(100, 100)  # Замените на нужные координаты
```

### 2. Проверка HWND и правильности координат
Убедитесь, что `hwnd` указывает на правильное окно, и что вы передаете координаты относительно этого окна. Возможно, стоит также проверить, правильно ли вы рассчитываете локальные координаты.

### 3. Использование сторонних библиотек
Если вы не против использования сторонних библиотек, `pynput`, `pyautogui` и другие могут быть хорошими вариантами, хотя они могут перемещать курсор. Возможно, придется написать собственную библиотеку на C++ для более глубокого доступа к системе (если это необходимо).

### 4. Проверьте настройки эмулятора
Проверьте, нет ли специальных настроек в вашем эмуляторе LD Player, которые могут блокировать события ввода, такие как режимы безопасности или фильтры.

### 5. Низкоуровневый доступ (C/C++)
Если ничего из вышеперечисленного не сработало, возможно, действительно стоит рассмотреть написание низкоуровневого кода на C/C++, особенно если вы хотите обойти ограничения, накладываемые эмулятором. Это может потребовать дополнительных усилий, но предоставит вам больше контроля за вводом.

Каждый из этих подходов потребует дальнейших тестирований и возможной адаптации в зависимости от вашего конкретного случая и особенностей эмулятора.
Но вот нужно именно без взаимодействием с основным курсором.

Только в виртуальной машине.
Похожие вопросы