1 (изменено: lukyan, 2020-04-01 03:22:50)

Тема: AHK: Скрипт от ложных нажатий клавиатуры

Здравствуйте. На ноуте глючит клавиатура. Абсолютно произвольно вместо одного нажатия кнопки может произойти 2-3.
Поэтому нужен скрипт который отсекал бы 2е и 3е последовательное повторное нажатие кнопки если задержка между повторами менее 50 миллисекунд.
Попробовал сделать такой скрипт для Enter. Это мой первый скрипт, потратил целый день на эти несколько строк, возможно что-то сделал неправильно, поэтому прошу отнестись с пониманием.
Как этот скрипт забиндить на остальные кнопки оптимальным способом, чтобы не дублировать то, что написано для каждой кнопки явным образом?


count = 0
delay = 50
Enter::

if (A_PriorHotkey = A_ThisHotkey) && (A_TimeSincePriorHotkey < delay)
{
	count := count + 1
	if (count >= 1) && (count <= 2)
		return
}
else
	count := 0

Send {%A_ThisHotkey%}
return

2

Re: AHK: Скрипт от ложных нажатий клавиатуры

А зачем считать количество повторов? Не проще ли блокировать любые нажатия, если со времени предыдущего нажатия той же клавиши прошло менее 50 мс? 50 мс — это довольно небольшой промежуток, сделать его намеренно проблематично.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

3 (изменено: lukyan, 2020-04-01 12:08:03)

Re: AHK: Скрипт от ложных нажатий клавиатуры

teadrinker пишет:

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

Можно и не считать повторы, но тогда при зажатии кнопки повтор будет в 2 раза медленнее, а хотелось бы сохранить скорость повтора при зажатии.
Но вопрос все равно остается.
Почему-то скрипт не выполняется если Enter заменить на Space.

4

Re: AHK: Скрипт от ложных нажатий клавиатуры

В справке по горячим клавишам смотрите про префикс $. Также гляньте *, а по команде Send порекомендую {Blind}.

5

Re: AHK: Скрипт от ложных нажатий клавиатуры

Происходит зацикливание: отправляемый скриптом пробел перехватывается самим скриптом. Для клавиши Enter работает другой способ перехвата, поэтому даже без префикса с ней все ок.

6

Re: AHK: Скрипт от ложных нажатий клавиатуры

stealzy пишет:

В справке по горячим клавишам смотрите про префикс $. Также гляньте *, а по команде Send порекомендую {Blind}.

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

Делаю вот так, но все равно пробел не обрабатывается, можете подсказать, что я делаю не так?

$Space::
if (A_PriorHotkey = A_ThisHotkey) && (A_TimeSincePriorHotkey < delay)
{
	count := count + 1
	if (count >= 1) && (count <= 2)
		return
}
else
	count := 0

Send {%A_ThisHotkey%}
return

7

Re: AHK: Скрипт от ложных нажатий клавиатуры

Для всех клавиш можно так:

delay := 200

Loop 249 {
   key := Format("*vk{:X}", A_Index + 6)
   Hotkey, If, TimeTest(delay)
   Hotkey, % key, Stop, On
}

Stop() {
}

TimeTest(delay) {
   static prevKey, prevTime
   time := A_TickCount
   if (A_ThisHotkey = prevKey && (time - prevTime) < delay)
      stop := true
   prevKey := A_ThisHotkey, prevTime := time
   Return stop
}

#If TimeTest(delay)
Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

8

Re: AHK: Скрипт от ложных нажатий клавиатуры

lukyan пишет:

Делаю вот так, но все равно пробел не обрабатывается, можете подсказать, что я делаю не так?

Когда отправляете

Send {%A_ThisHotkey%}

в переменной A_ThisHotkey находится не Space, а $Space.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

9

Re: AHK: Скрипт от ложных нажатий клавиатуры

teadrinker пишет:

в переменной A_ThisHotkey находится не Space, а $Space.

Так а как тогда обойти вышеописанное зацикливание с помощью этого префикса? Или это не поможет?

10

Re: AHK: Скрипт от ложных нажатий клавиатуры

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

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

11

Re: AHK: Скрипт от ложных нажатий клавиатуры

teadrinker пишет:

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

Да вы правы. Именно это я и хочу сделать.
Подход выбран методом тыка, как сделать более правильнее, а именно блокировать я пока не знаю.

12

Re: AHK: Скрипт от ложных нажатий клавиатуры

stealzy Спасибо, ваш вариант заработал.

13

Re: AHK: Скрипт от ложных нажатий клавиатуры

lukyan пишет:

как сделать более правильнее, а именно блокировать я пока не знаю.

Я бы на вашем месте рискнул рассмотреть код из этого поста.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

14

Re: AHK: Скрипт от ложных нажатий клавиатуры

teadrinker пишет:

Я бы на вашем месте рискнул рассмотреть код из этого поста.

Я его давно рассматриваю пока ничего не понятно. По какому событию он начинает работать и что такое hotkey (в инструкциях очень скудно описано)...

15

Re: AHK: Скрипт от ложных нажатий клавиатуры

Он начинает работу сразу после загрузки. Вы его запускали?
Hotkey

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

16

Re: AHK: Скрипт от ложных нажатий клавиатуры

teadrinker пишет:

Он начинает работу сразу после загрузки. Вы его запускали?

Я не сомневаюсь что он работает. Но важно еще и понимать как он работает.
Он будет работать в бесконечном цикле?

17

Re: AHK: Скрипт от ложных нажатий клавиатуры

Так а зачем сомневаться или не сомневаться, можно же просто протестировать.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

18

Re: AHK: Скрипт от ложных нажатий клавиатуры

teadrinker пишет:

Так а зачем сомневаться или не сомневаться, можно же просто протестировать.

Если вам не сильно сложно, расскажите логику работы скрипта - это будет гораздо полезнее чем просто рабочая и не понятная программа.

19

Re: AHK: Скрипт от ложных нажатий клавиатуры

Что такое виртуальный код клавиши знаете? Если нет, почитайте об этом, иначе трудно будет пояснить.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

20

Re: AHK: Скрипт от ложных нажатий клавиатуры

teadrinker пишет:

Что такое виртуальный код клавиши знаете? Если нет, почитайте об этом, иначе трудно будет пояснить.

Примерно понимаю.
Мне не понятно по какому события запускается скрипт. Или он выполняется постоянно? Основное тело программы - это цикл?
Не понятно что делают команды HotKey. Хоть описание вы и скинули (и я его и раньше видел), но не очень доходит как она отрабатывают.

21

Re: AHK: Скрипт от ложных нажатий клавиатуры

Скрипт, как я уже сказал выше, запускается без всякого события, просто после загрузки выполняется весь код и скрипт продолжает висеть в памяти.
Команда Hotkey динамически создаёт горячую клавишу. Например, можно создать горячую клавишу Alt + C так:

!c:: MsgBox, % A_ThisHotkey

А можно с помощью команды Hotkey:

Hotkey, !c, Label, On
Return

Label:
   MsgBox, % A_ThisHotkey
   Return

Кроме того, с помощью команды Hotkey можно создать контекст запуска горячей клавиши. Обычный способ:

#If WinActive("ahk_class Notepad")
!c:: MsgBox, % A_ThisHotkey

Используя Hotkey:

Hotkey, If, WinActive("ahk_class Notepad")
Hotkey, !c, Label, On
Return

Label:
   MsgBox, % A_ThisHotkey
   Return
   
#If WinActive("ahk_class Notepad")

При этом в коде где-то обязательно должна присутствовать обычная запись того же контекста (последняя строка).
Немного подправленный код скрипта с комментариями:

delay := 200

Hotkey, If, TimeTest(delay) ; создаём контекст для всех созданных ниже горячих клавиш
                            ; контекст заключается в том, что клавиши будут срабатывать
                            ; только если функция TimeTest() вернёт true
Loop 249 { ; создаём горячие клавиши на все возможные виртуальные коды, т. е. на всю клавиатуру
   key := Format("*vk{:X}", A_Index + 6)
   Hotkey, % key, Stop, On ; если выполнится вышеуказанный контекст
}                          ; горячая клавиша выполит свою метку Stop и больше ничего не будет делать

Stop() { ; метка Stop, которая ничего не делает, т. е. просто блокирует клавишу
}

TimeTest(delay) { ; функция, проверяющая, прошёл ли таймаут с прошлого нажатия
   static prevKey, prevTime
   time := A_TickCount
   if (A_ThisHotkey = prevKey && (time - prevTime) < delay)
      stop := true ; если таймаут не прошёл, stop будет равно true, если прошёл — пустому значению
   prevKey := A_ThisHotkey, prevTime := time
   Return stop
}

#If TimeTest(delay) ; запись контекта в обычной форме (требование синтаксиса)
Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

22

Re: AHK: Скрипт от ложных нажатий клавиатуры

teadrinker Супер! Спасибо!

23

Re: AHK: Скрипт от ложных нажатий клавиатуры

lukyan, вот так будет с сохранением вашей логики:

delay := 300 ; промежуток времени c предыдущего нажатия, в котором следующее нажатие считается повторным
nFalseRepeat := 2 ; кол-во повторных нажатий после первого, которые будут отфильтрованы
for k in concatenateAssocArrays(range(6, 158), range(160, 190)) { ; диапазоны vk-кодов клавиатуры
	Hotkey If, isFalsePressRepeat()
	Hotkey % Format("*vk{:X}", k), Block
}
Return

#If isFalsePressRepeat()
isFalsePressRepeat() {
	global nFalseRepeat, delay
	static pressCount := 0, _PriorHotkey, _TimeSincePriorHotkey := A_TickCount
	if ((_PriorHotkey = A_ThisHotkey) && (A_TickCount-_TimeSincePriorHotkey < delay))
		block := inRange(1, ++pressCount, nFalseRepeat) ? true : false
	else
		pressCount := 0
	_PriorHotkey := A_ThisHotkey, _TimeSincePriorHotkey := A_TickCount
	Return block
}

Block() {
}

inRange(rangeLow, x, rangeHigh) {
	Return (x>=rangeLow && x<=rangeHigh)
}

concatenateAssocArrays(arrs*) {
	sumArr := []
	for index, arr in arrs
		for k, v in arr
			sumArr.InsertAt(k, v)
	Return sumArr
}

range(start, stop:="", step:=1) {
	static range := { _NewEnum: Func("_RangeNewEnum") }
	if !step
		throw "range(): Parameter 'step' must not be 0 or blank"
	if (stop == "")
		stop := start, start := 0
	; Formula: r[i] := start + step*i ; r = range object, i = 0-based index
	; For a postive 'step', the constraints are i >= 0 and r[i] < stop
	; For a negative 'step', the constraints are i >= 0 and r[i] > stop
	; No result is returned if r[0] does not meet the value constraint
	if (step > 0 ? start < stop : start > stop) ;// start == start + step*0
		return { base: range, start: start, stop: stop, step: step }
}
_RangeNewEnum(r) {
	static enum := { "Next": Func("_RangeEnumNext") }
	return { base: enum, r: r, i: 0 }
}
_RangeEnumNext(enum, ByRef k, ByRef v:="") {
	stop := enum.r.stop, step := enum.r.step
	, k := enum.r.start + step*enum.i
	if (ret := step > 0 ? k < stop : k > stop)
		enum.i += 1
	return ret
}

24

Re: AHK: Скрипт от ложных нажатий клавиатуры

stealzy пишет:

lukyan, вот так будет с сохранением вашей логики:

Круто, спасибо, скрипт работает.