1 (изменено: Anonymous, 2017-02-05 10:32:53)

Тема: AHK: Самый быстрый способ перехвата, а также отправки нажатий клавиш?

Понадобился автокликер. Вначале набросал код дефолтного автокликера и забиндил на R:


DownTime := 80
UpTime := 10

*$~vk01:: ; LMB
LOOP
{
Send {vk52 Down} ; R key
Sleep %DownTime%
Send {vk52 Up} ; R key
Sleep %UpTime%

if !GetKeyState("vk01", "P")  ; LMB
break
}
Return

Который работает достаточно быстро в большинстве случаев, но в моем случае нужен более быстрый автокликер. Также были проблемы со стабильностью работы в приложении(в приложении используется raw input) и таймингами, то недостаточно быстро отправлялись нажатия, то наоборот нажатий было слишком много.

Изменил Send на SendInput, и скрипт начал работать намного более стабильно(на глаз - идеально в плане стабильности и таймингов нажатий), но осталась еще одна серьезная проблема - это задержка при нажатии ЛКМ т.е. при активации скрипта в сравнении с тем, когда скрипт не используется(где-то 50ms разница).

Заменил бинд с R на ЛКМ в скрипте, а также немного изменил логику работы:


DownTime := 80
UpTime := 10

*$~vk01::
LOOP
{
Sleep %DownTime%
SendInput {vk01 Up}
Sleep %UpTime%
if !GetKeyState("vk01", "P")
break
SendInput {vk01 Down}
}
Return

Чтобы AHK не блокировал нажатие ЛКМ и функция в приложении активировалась при оригинальном нажатии ЛКМ, а не при помощи скрипта.

На глаз задержка(лаг активации функции в приложении) при использовании скрипта отстутствует в сравнении с тем, когда скрипт не спользуется, работает стабильно в плане таймингов.

Но вопрос остался. Знатоки, подскажите, пожалуйста, как можно ускорить работу скрипта: уменьшить время активации скрипта(лаг) и увеличить скорость отправки нажатий(не время между отправкой нажатий)?


Всем заранее спасибо за советы! http://smiles.kolobanga.ru/standart_koloboks/standart_light_skin/drinks.gif

2 (изменено: stealzy, 2017-02-05 12:32:55)

Re: AHK: Самый быстрый способ перехвата, а также отправки нажатий клавиш?

Во-первых увеличиваем общую прозводительность:

#NoEnv
#MaxHotkeysPerInterval 200
SetBatchLines -1 ; по умолчанию между командами в скрипте задержка 10 мс
Process, priority, , High ; процесс кликера должен иметь больший приоритет
SendMode Input
SetKeyDelay 0

Во-вторых, проверять не отжатие клавиши в цикле, а некую переменную.
Просто делаем аналогичный хоткей на отжатие клавиши, в нем присваиваем некой переменной значение 1.
Конфликт, когда вы еще не отпустили кнопку мыши, а скрипт уже начал работу, возможная причина лага.
Я бы не пропускал клик дальше скрипта, а цикл начинал с Send {click down}.

3

Re: AHK: Самый быстрый способ перехвата, а также отправки нажатий клавиш?

Задам вопрос, который касается темы, как я думаю, а если не так, то скажите, больше не буду. Собственно, мне говорят, если скрипт компилировать, то его скорость работы увеличивается, так ли это?

Когда вы говорите что не можете сделать, вам всего-лишь не хватает фантазии придумать какой-нибудь костыль.

4

Re: AHK: Самый быстрый способ перехвата, а также отправки нажатий клавиш?

Как мне сравнить скорости конкретно? Если сравнивать по ощущениям, то на это время много уйдет. Кроме того, подготовить мой скрипт для компиляции тоже время займет, потому спрашиваю так.

Когда вы говорите что не можете сделать, вам всего-лишь не хватает фантазии придумать какой-нибудь костыль.

5

Re: AHK: Самый быстрый способ перехвата, а также отправки нажатий клавиш?

start := A_TickCount
; your code
MsgBox % "Time: " A_TickCount - start

У меня скрипты компилируются одной командой. Что вы там подготавливаете?

6 (изменено: Anonymous, 2017-02-06 07:23:25)

Re: AHK: Самый быстрый способ перехвата, а также отправки нажатий клавиш?

Переделал вот так:

+ открыть спойлер
#NoEnv
#MaxHotkeysPerInterval 200
SetBatchLines -1 ; по умолчанию между командами в скрипте задержка 10 мс
Process, priority, , High ; процесс кликера должен иметь больший приоритет
SendMode Input
SetKeyDelay 0


*vk01::
LMBState := 1
LOOP
{
Send {click down}
Sleep %UpTime%
if LMBState = 0
break
}
Return

*~vk01 Up::
{
	LMBState := 0
}
Return

Вроде верно относительно Ваших рекомендаций.

Лага при нажатии нет в сравнении с использованием без скрипта(на глаз), клики стабильнее в приложении в сравнении с тем, что было раньше.

stealzy пишет:

Конфликт, когда вы еще не отпустили кнопку мыши, а скрипт уже начал работу, возможная причина лага.
Я бы не пропускал клик дальше скрипта, а цикл начинал с Send {click down}.

Мне кажется, что изначально был лаг из-за того, что вначале происходил перехват нажатия клавиши, а потом отправка нажатия другой клавиши, и который был решен модификатором ~ и изменением логики скрипта.

А разве скрипт ниже не будет работать еще быстрее приведенного выше в данном посте(т.к. оригинальный клик мыши не блокируется, а пропускается)?

+ открыть спойлер
#NoEnv
#MaxHotkeysPerInterval 200
SetBatchLines -1 ; по умолчанию между командами в скрипте задержка 10 мс
Process, priority, , High ; процесс кликера должен иметь больший приоритет
SendMode Input
SetKeyDelay 0

*~vk01::
LMBState := 1
Sleep %UpTime%
Send {vk01 Up}
LOOP
{
if LMBState = 0
break
Send {click down}
Sleep %UpTime%
}
Return

*~vk01 Up::
{
	LMBState := 0
}
Return

7 (изменено: stealzy, 2017-02-05 17:03:35)

Re: AHK: Самый быстрый способ перехвата, а также отправки нажатий клавиш?

За оверквотинг модеры ругаются, первое и последнее цитирования у вас явно лишние, отредактируйте.

Раз у вас работает, то хорошо, но для порядка можно бы посылать еще и Send {click up}.
Либо использовать просто Send {click}, длительность нажатия определяет SetKeyDelay.
Как измерять скорость я написал как раз постом выше.

8 (изменено: Anonymous, 2017-02-06 13:02:30)

Re: AHK: Самый быстрый способ перехвата, а также отправки нажатий клавиш?

stealzy, переделал так с использованием Send {click up}:

+ открыть спойлер
#NoEnv
#MaxHotkeysPerInterval 200
SetBatchLines -1 ; по умолчанию между командами в скрипте задержка 10 мс
Process, priority, , High ; процесс кликера должен иметь больший приоритет
SendMode Input
SetKeyDelay 0

Global DownTime := 64
Global UpTime := 10

*vk01::
LMBState := 1
LOOP
{
Send {Click down}
Sleep %DownTime%
Send {Click up}
Sleep %UpTime%
if LMBState = 0
break
}
Return

*~vk01 Up::
{
	LMBState := 0
}
Return
stealzy пишет:

Либо использовать просто Send {click}, длительность нажатия определяет SetKeyDelay.

В оф. документации говорится:"Note: SetKeyDelay is not obeyed by SendInput; there is no delay between keystrokes in that mode. This same is true for Send when SendMode Input is in effect".

После этого совета переделал так:

+ открыть спойлер

#NoEnv
#MaxHotkeysPerInterval 200
SetBatchLines -1 ; по умолчанию между командами в скрипте задержка 10 мс
Process, priority, , High ; процесс кликера должен иметь больший приоритет
SendMode Input
SetKeyDelay 100, 100 ; Delay, Duration



*vk01::
LMBState := 1
LOOP
{
Send {Click}
if LMBState = 0
break
}
Return

*~vk01 Up::
{
	LMBState := 0
}
Return

numpad8::
{
	SetKeyDelay 500, 500
}
Return

NumpadMult::
MsgBox, KeyDelay: %A_KeyDelay% ms, KeyDuration: %A_KeyDuration% ms

Но при 'замене' Sleep на SetKeyDelay, SetKeyDelay не имеет никакого эффекта(спам ЛКМ с максимальной скоростью) даже если закомментировать строку ;SendMode Input вначале т.е. SetKeyDelay не имеет никакого эффекта вне зависимости от типа ввода.

Также при попытке изменить SetKeyDelay при помощи хоткея, это не влияет ни на сами Delay и PressDuration, ни на встроенные переменные A_KeyDelay, A_KeyDuration. Например, если запустить последний скрипт, то при нажатии на ЛКМ, кнопка будет спамится с максимальной скоростью(а не 5 нажатий в секунду 100/100), после нажатия на numpad8 не изменится ровным ничего, а при нажатии на NumpadMult показывается данный MsgBox:
http://i.imgur.com/eVD2wdx.png

Разве при нажатии на numpad8 значения переменных A_KeyDelay и A_KeyDuration не должны измениться на 500/500?

Я никак не могу понять, где я допустил ошибку.

9 (изменено: stealzy, 2017-02-06 14:35:25)

Re: AHK: Самый быстрый способ перехвата, а также отправки нажатий клавиш?

Моя ошибка, никогда не пользовался задержкой для мыши, надо было брать SetMouseDelay.
Вот, кстати, преимущество локального файла справки AutoHotkey.chm: когда я убедился, что задержка не появляется, я открыл SetKeyDelay в справке и увидел, что слева, в списке комманд, за сразу за ней идет SetMouseDelay ;-).

10 (изменено: Anonymous, 2017-02-08 13:38:25)

Re: AHK: Самый быстрый способ перехвата, а также отправки нажатий клавиш?

Пока сделал так:

#NoEnv
#MaxHotkeysPerInterval 200
SetBatchLines -1 ; по умолчанию между командами в скрипте задержка 10 мс
Process, priority, , High ; процесс кликера должен иметь больший приоритет
SendMode Input
SetKeyDelay -1, -1
SetMouseDelay, -1, -1

Global UpTime := 16
Global DownTime := 58

*~vk01::
LMBState := 1
Sleep %DownTime%
Send {vk01 up}
Sleep %UpTime%
LOOP
{
if LMBState = 0
break
Send {click down}
Sleep %DownTime%
Send {click up}
Sleep %UpTime%
}
Return

*~vk01 Up::
{
	LMBState := 0
}
Return

Активация без видимого на глаз лага, кликает стабильно. Разница между стартовым скриптом и этим огромная, первый неиграбельный, проще руками затыкать.

Всем ответившим спасибо за помощь. Если кто еще знает, как ускорить перехват и нажатие клавиш(а также как ускорить работу конкретно этого скрипта) - пишите, не стесняйтесь.

11 (изменено: stealzy, 2017-02-08 20:50:45)

Re: AHK: Самый быстрый способ перехвата, а также отправки нажатий клавиш?

#NoEnv
#MaxHotkeysPerInterval 200
SetBatchLines -1
Process priority,, High
Global UpTime := 20, DownTime := 10
SetMouseDelay % DownTime
Return

*$LButton::autoClick(LMBState := True)
*$LButton Up::LMBState := False
Esc & LButton::Suspend

autoClick(ByRef LMBState) {
	While LMBState {
		Send {vk01}
		Sleep % UpTime
	}
}

12 (изменено: Anonymous, 2017-02-09 08:28:36)

Re: AHK: Самый быстрый способ перехвата, а также отправки нажатий клавиш?

+ открыть спойлер
stealzy пишет:
#NoEnv
#MaxHotkeysPerInterval 200
SetBatchLines -1
Process priority,, High
UpTime := 50, DownTime := 20
SetMouseDelay % DownTime
Return

*$LButton::autoClick(LMBState := True, UpTime)
*$LButton Up::LMBState := False
Esc & LButton::Suspend

autoClick(ByRef LMBState, UpTime) {
	While LMBState {
		Send {vk01}
		Sleep % UpTime
	}
}

Попробовал, работает, но SendInput и Sleep работает гораздо стабильнее, чем Send, SetMouseDelay и Sleep в приложении, в котором я использую автокликер. Возможно это каким-то образом связано с тем, что в приложении чувствительность мыши зависит от FPS(я тестирую на ~200 FPS), а также на низком FPS(~24) приходится даже ЛКМ зажимать где-то на 100-200 мс, чтобы стрелять начало(без автокликера).


belyankin12 пишет:

Как мне сравнить скорости конкретно?

stealzy пишет:
start := A_TickCount
; your code
MsgBox % "Time: " A_TickCount - start

Я заметил, что в некоторых приложениях лучше работает просто Send {click} и Sleep, в других - {click Down}, Sleep, {click Up} и т.д.
Еще одним неплохим тестом является видеокамера, чтобы сравнить лаг между физическим нажатием клавиши и моментом, когда видно, что функция в приложении была активирована.

И еще интересует такой вопрос. Я заметил, что если перебиндить кнопки мыши(в софте от производителя), например, Mouse4 и Mouse5 на Backspace и ALT+Right соответственно(аналоги Mouse4 и Mouse5 в windows, браузерах и т.д.), то при нажатии на кнопки(4,5) мыши, функции(назад, вперед) в Windows и в браузерах активируются гораздо быстрее.
Именно поэтому изначально я и забиндил скрипт на отправку "R", а не ЛКМ.

Кроме того, в самом AHK существует очень много различных способов отправить нажатие:



Send {R Down}
Send {vk52 Down} ; R Key
Send {LButton Down}
Send {vk01 Down}
Send {click Down}
Click
Click Down
MouseClick, left
DllCall("mouse_event", "UInt", 0x02) ; left button down

И еще, наверняка, есть множество способов, о которых я не знаю(дополните список, пожалуйста, кто знает).