1 (изменено: sergeant.coolagin, 2011-11-03 15:46:57)

Тема: AHK: Выполнить определенные действия по нажатию и отпусканию клавиши

В общем, вот скрипт. И до меня не доходит, что все-таки я делаю неправильно:

Joy4::
{
Send {R Down}
Sleep, 50
Send {R Up}
Sleep, 200
Send {F Down}
Sleep, 50
Send {F Up}
Sleep, 200
Send {Left Down}
Sleep, 50
Send {Down Down}
Sleep, 300
Send {Left Up}
Sleep, 50
Send {Down Up}
Sleep, 50
Send {G Down}
Keywait, Joy4, T5
Send {G Up}
}
Return

Нужно, чтобы по нажатию хоткея жалась кнопка R, через 200 мс жалась кнопка F, еще через 200 мс зажимались кнопки Left и down и через 300 мс эти две кнопка отпускались и после этого кнопка G оставалась в нажатом состоянии до отпускания  Joy4 или до истечения 5 секунд(T5). И вроде как все правильно я написал, но скрипт работает неправильно. Вместо того, чтобы зажимать кнопки(например, Left и Down зажать на 300 мс или зажать G до отпускания Joy4) они просто нажимаются один раз.
Вот что у меня нажимается в блокноте, когда я зажимаю Joy4 на 5 секунд:

RGF

А должно быть что-то вроде:

RGGGGGGGGGGGGGGF

Как я понимаю, почему-то команды "Send {кнопка Down}" работают неправильно. И вместо зажимания кнопки просто один раз тыкают её т.е. фактически посылают просто "Send {кнопка}"
Версия AHK: 1.1.05.01
Помогите решить проблему, пожалуйста.

Еще вот по-другому попробовал сделать:

SetTimer, Rr, 100


Rr:
{
    GetKeyState, JState, Joy4

    if JState = D
    {
        
        if RStart = 1
        {
            Send {R Down}
            Sleep, 100
            Send {F Down}
            Sleep, 100
            Send {T Down}{Y Down}
            Sleep, 3000
            RState = 1
            RStart = 0
        }
        Send {G Down}
    }

    else if JState = U
    {

        if RState = 1
        {
            Send {R Up}
            Send {F UP}
            Send {G Up}
            RState = 0
        }

    }
    
    else
    {
        Return
    }
    
}
Return

Joy4::
{
RStart = 1
}
Return

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

2

Re: AHK: Выполнить определенные действия по нажатию и отпусканию клавиши

sergeant.coolagin, ознакомься с первой темой на странице, исправь заголовок.

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

3 (изменено: Александр_, 2011-11-05 17:24:36)

Re: AHK: Выполнить определенные действия по нажатию и отпусканию клавиши

sergeant.coolagin, вы неверно представляете себе работу сообщений о нажатии/отпускании клавиш. На самом деле, когда вы нажимаете клавишу окно получает сообщение об этом. Затем спустя некоторое время(см. SystemParametersInfo(SPI_GETKEYBOARDDELAY)) начинает работать автоповтор. Это означает, что каждые несколько миллисекунд(см. SystemParametersInfo(SPI_GETKEYBOARDSPEED)) окно будет получать сообщение о нажатии клавиши. Приложение знает о том, что это автоповтор по 30-му биту в lParam в сообщениях клавиатуры, но блокнот это игнорирует.

4 (изменено: sergeant.coolagin, 2011-11-07 00:02:45)

Re: AHK: Выполнить определенные действия по нажатию и отпусканию клавиши

Александр_ пишет:

sergeant.coolagin, вы неверно представляете себе работу сообщений о нажатии/отпускании клавиш. На самом деле, когда вы нажимаете клавишу окно получает сообщение об этом. Затем спустя некоторое время(см. SystemParametersInfo(SPI_GETKEYBOARDDELAY)) начинает работать автоповтор. Это означает, что каждые несколько миллисекунд(см. SystemParametersInfo(SPI_GETKEYBOARDSPEED)) окно будет получать сообщение о нажатии клавиши. Приложение знает о том, что это автоповтор по 30-му биту в lParam в сообщениях клавиатуры, но блокнот это игнорирует.

Эм, и что же Вы мне посоветуете делать? Не прописывать же мне 1000 раз, чтобы кнопка нажималась и отпускалась для достижения нужного эффекта?

5 (изменено: Александр_, 2011-11-07 01:18:47)

Re: AHK: Выполнить определенные действия по нажатию и отпусканию клавиши

sergeant.coolagin пишет:

Эм, и что же Вы мне посоветуете делать? Не прописывать же мне 1000 раз, чтобы кнопка нажималась и отпускалась для достижения нужного эффекта?

Только эмулировать действия драйвера. Простейший пример:

SPI_GETKEYBOARDDELAY := 0x0016
SPI_GETKEYBOARDSPEED := 0x000A 

SystemParametersInfo(Action, Param, retParam, WinIni)
{
   return DllCall("SystemParametersInfo", "int", Action, "int", Param, "uint", retParam, "int", WinIni)
}

return

MyKeyWait()
{
   global
   VarSetCapacity(TempVar,4)
   SystemParametersInfo(SPI_GETKEYBOARDDELAY, 0, &TempVar, 0)
   KeyboardDelay := NumGet(TempVar)
   SystemParametersInfo(SPI_GETKEYBOARDSPEED, 0, &TempVar, 0)
   KeyboardSpeed := NumGet(TempVar)
   VarSetCapacity(TempVar,0)
   KeyboardDelay:=(KeyboardDelay+1)/4
   KeyboardSpeed:=1/(2.5+KeyboardSpeed*27.7/31)
   Keywait Esc, T%KeyboardDelay%
   Send {G Down}
   loop % (5-KeyboardDelay)/KeyboardSpeed ;%
   {
      Keywait Esc, T%KeyboardSpeed%
	  if(!ErrorLevel)
	     return
      Send {G Down}
   }
}

Esc::
{
   Send {R}
   Send {F}
   Send {Left}
   Send {G Down}
   MyKeyWait()
   Send {G Up}
}
Return

Но помимо того, что даже microsoft нам не гарантирует корректности возвращаемых данных об автоповторе, тут ещё и не учитываются никакие накладные расходы и отбрасывается остаток от (5-KeyboardDelay)/KeyboardSpeed. Можно повесить таймер, но при его стандартных настройках и максимальной частоте автоповтора мы получим погрешность около 25%(у этого кода примерно такая же). Самым лучшим выходом будет цикл while с ручным опросом клавиатуры(GetKeyState).