Лаг мыши при аппаратном автокликере – почему курсор так задерживается и как это исправить?Python

Программы на Python
Ответить
Anonymous
 Лаг мыши при аппаратном автокликере – почему курсор так задерживается и как это исправить?

Сообщение Anonymous »

Что делает программа:

Программа распознает реальные физические щелчки мышью и быстро имитирует дополнительные щелчки, пока кнопка удерживается, с разной частотой для левой и правой кнопок. Он использует низкоуровневый крючок мыши Windows и функцию SendInput() для генерации щелчков мышью в режиме реального времени и обеспечивает чистый выход с помощью клавиши ALT.
Проблема:

Курсор мыши сильно запаздывает и очень медленно реагирует во время работы программы. Это происходит потому, что низкоуровневый перехватчик обрабатывает каждое событие мыши, а также отправляет быстрые имитированные щелчки, что перегружает систему. Высокие показатели CPS и потоковая модель программы создают задержки, вызывающие заметную задержку ввода. Как можно устранить эту задержку, сохранив при этом работоспособность автокликера?
Код:

Код: Выделить всё

import ctypes
import time
import threading
import win32con
from ctypes import wintypes

WH_MOUSE_LL = 14
WM_LBUTTONDOWN = 0x0201
WM_LBUTTONUP = 0x0202
WM_RBUTTONDOWN = 0x0204
WM_RBUTTONUP = 0x0205
LLMHF_INJECTED = 0x00000001

LEFT_CPS = 12
RIGHT_CPS = 8
EXIT_KEY = win32con.VK_MENU

left_button_physically_pressed = False
right_button_physically_pressed = False
running = True
hook_id = None

class POINT(ctypes.Structure):
_fields_ = [("x", ctypes.c_long), ("y", ctypes.c_long)]

class MSLLHOOKSTRUCT(ctypes.Structure):
_fields_ = [
("pt", POINT),
("mouseData", wintypes.DWORD),
("flags", wintypes.DWORD),
("time", wintypes.DWORD),
("dwExtraInfo", wintypes.WPARAM)
]

user32 = ctypes.WinDLL('user32', use_last_error=True)
kernel32 = ctypes.WinDLL('kernel32', use_last_error=True)

if ctypes.sizeof(ctypes.c_void_p) == 8:
LRESULT = ctypes.c_int64
else:
LRESULT = ctypes.c_long

user32.CallNextHookEx.argtypes = [wintypes.HHOOK, ctypes.c_int, wintypes.WPARAM, wintypes.LPARAM]
user32.CallNextHookEx.restype = LRESULT

user32.SetWindowsHookExW.argtypes = [ctypes.c_int, wintypes.HANDLE, wintypes.HINSTANCE, wintypes.DWORD]
user32.SetWindowsHookExW.restype = wintypes.HHOOK

LowLevelMouseProc = ctypes.WINFUNCTYPE(LRESULT, ctypes.c_int, wintypes.WPARAM, wintypes.LPARAM)

def low_level_mouse_callback(nCode, wParam, lParam):
global left_button_physically_pressed, right_button_physically_pressed
if nCode >= 0:
try:
mouse_event = ctypes.cast(lParam, ctypes.POINTER(MSLLHOOKSTRUCT)).contents
is_injected = (mouse_event.flags & LLMHF_INJECTED) != 0
if not is_injected:
if wParam == WM_LBUTTONDOWN:
left_button_physically_pressed = True
elif wParam == WM_LBUTTONUP:
left_button_physically_pressed = False
elif wParam == WM_RBUTTONDOWN:
right_button_physically_pressed = True
elif wParam == WM_RBUTTONUP:
right_button_physically_pressed = False
except Exception:
pass
return user32.CallNextHookEx(None, nCode, wParam, lParam)

def send_mouse_click(button):
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 INPUT(ctypes.Structure):
class _INPUT(ctypes.Union):
_fields_ = [("mi", MOUSEINPUT)]
_anonymous_ = ("_input",)
_fields_ = [("type", ctypes.c_ulong), ("_input", _INPUT)]

INPUT_MOUSE = 0
MOUSEEVENTF_LEFTDOWN = 0x0002
MOUSEEVENTF_LEFTUP = 0x0004
MOUSEEVENTF_RIGHTDOWN = 0x0008
MOUSEEVENTF_RIGHTUP = 0x0010

if button == 'left':
input_down = INPUT(); input_down.type = INPUT_MOUSE
input_down.mi = MOUSEINPUT(0, 0, 0, MOUSEEVENTF_LEFTDOWN, 0, None)
input_up = INPUT(); input_up.type = INPUT_MOUSE
input_up.mi = MOUSEINPUT(0, 0, 0, MOUSEEVENTF_LEFTUP, 0, None)
user32.SendInput(1, ctypes.byref(input_down), ctypes.sizeof(INPUT))
user32.SendInput(1, ctypes.byref(input_up), ctypes.sizeof(INPUT))
elif button == 'right':
input_down = INPUT(); input_down.type = INPUT_MOUSE
input_down.mi = MOUSEINPUT(0, 0, 0, MOUSEEVENTF_RIGHTDOWN, 0, None)
input_up = INPUT(); input_up.type = INPUT_MOUSE
input_up.mi = MOUSEINPUT(0, 0, 0, MOUSEEVENTF_RIGHTUP, 0, None)
user32.SendInput(1, ctypes.byref(input_down), ctypes.sizeof(INPUT))
user32.SendInput(1, ctypes.byref(input_up), ctypes.sizeof(INPUT))

def click_handler(button, cps):
global running, left_button_physically_pressed, right_button_physically_pressed
delay = 1.0 / cps
while running:
if ctypes.windll.user32.GetAsyncKeyState(EXIT_KEY) &  0x8000:
running = False
break
if button == 'left' and left_button_physically_pressed:
send_mouse_click('left')
time.sleep(delay)
elif button == 'right' and right_button_physically_pressed:
send_mouse_click('right')
time.sleep(delay)
else:
time.sleep(0.001)

def hook_thread():
global running, hook_id
callback = LowLevelMouseProc(low_level_mouse_callback)
hook_id = user32.SetWindowsHookExW(WH_MOUSE_LL, callback, None, 0)
if not hook_id:
return
while running:
if ctypes.windll.user32.GetAsyncKeyState(EXIT_KEY) & 0x8000:
running = False
break
msg = wintypes.MSG()
PM_REMOVE = 0x0001
while user32.PeekMessageW(ctypes.byref(msg), None, 0, 0, PM_REMOVE):
user32.TranslateMessage(ctypes.byref(msg))
user32.DispatchMessageW(ctypes.byref(msg))
time.sleep(0.001)
if hook_id:
user32.UnhookWindowsHookEx(hook_id)

def main():
global running
print("✅ Autoclicker started")
try:
hook_t = threading.Thread(target=hook_thread, daemon=True)
hook_t.start()
time.sleep(0.5)
left_thread = threading.Thread(target=click_handler, args=('left', LEFT_CPS), daemon=True)
right_thread = threading.Thread(target=click_handler, args=('right', RIGHT_CPS), daemon=True)
left_thread.start()
right_thread.start()
while running:
if ctypes.windll.user32.GetAsyncKeyState(EXIT_KEY) & 0x8000:
running = False
break
time.sleep(0.05)
finally:
running = False
time.sleep(0.5)
print("✅ Autoclicker stopped")

if __name__ == "__main__":
main()


Подробнее здесь: https://stackoverflow.com/questions/798 ... ed-and-how
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «Python»