1

Тема: AHK: Перебор меток после удержания горячей клавиши

Помогите, пожалуйста, реализовать следующее: спустя секунду после удержания горячей клавиши и до момента ее отжатия, отправляются нажатия клавиш "1", "2", "3" по кругу с заданным интервалом времени между каждым отправлением, например, в 0,2 секунды. Если горячая клавиша была отпущена ранее, чем за секунду после нажатия, то отправляет саму себя, т.е. работает как обычно.

Пытался самостоятельно реализовать данный сценарий на основе имеющихся примеров, однако, не получилось добиться необходимого результата.

Спасибо!

Win10x64, AHK v1.1.25

2

Re: AHK: Перебор меток после удержания горячей клавиши

#UseHook
q::
  KeyWait, %A_ThisHotkey%, T1
  If ErrorLevel
      While GetKeyState(A_ThisHotkey,"P") {
    SendInput {1}
    Sleep 200
    SendInput {2}
    Sleep 200
    SendInput {3}
    Sleep 200
  }
  Else
      SendInput % A_ThisHotkey
Return

3

Re: AHK: Перебор меток после удержания горячей клавиши

F1::
If f1_is_pressed != 1 ;игнорирует автоповтор
	{
	f1_is_pressed := 1
	start_time := A_TickCount
	Sleep, 1000
	While GetKeyState("F1","P")
 	{
	SoundBeep, 300, 30 ;действия при удержании F1 более секунды
	}
	}
Return



F1 Up::
f1_is_pressed := 0
elapsed_time := A_TickCount - start_time
If (elapsed_time < 1000)
SoundBeep, 1000, 100
;Send F1 ; F1 отправляет себя
Return

4

Re: AHK: Перебор меток после удержания горячей клавиши

F1::

KeyWait %A_ThisHotkey%, T1
#If ErrorLevel = 0
  n = 0
  Loop
    { n := n + 1
      If n = 4
         n = 1
      GetKeyState, state, %A_ThisHotkey%, P
      If state = U
         Return
      Send, % n
      Sleep, 200
    }
#If

5

Re: AHK: Перебор меток после удержания горячей клавиши

#UseHook
F1::
   KeyWait, % A_ThisHotkey, T1
   if !ErrorLevel
      SendInput, {%A_ThisHotkey%}
   else  {
      while GetKeyState(A_ThisHotkey, "P")  {
         SendInput, % (k := mod(A_Index, 3)) ? k : 3
         Sleep, 200
      }
   }
   Return
Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Skype dmitry_fiveg

6 (изменено: becauseim, 2016-11-09 13:29:43)

Re: AHK: Перебор меток после удержания горячей клавиши

Спасибо! Не ожидал такой отзывчивости!
Вариант от teadrinker работает именно так, как задумывалось, т.к. если я отпускаю клавишу в момент отправления клавиши "2", то на этом перебор останавливается. Однако, мне не понятно, как редактировать сценарий, чтобы отправлялись по кругу совершенно иные клавиши, либо происходили иные действия.

Вариант от Nikva в этом смысле легко редактируется, однако перебирает все метки, вне зависимости от момента прекращения удерживания горячей клавиши.

Win10x64, AHK v1.1.25

7

Re: AHK: Перебор меток после удержания горячей клавиши

becauseim пишет:

Вариант от teadrinker работает именно так, как задумывалось, т.к. если я отпускаю клавишу в момент отправления клавиши "2", то на этом перебор останавливается.

Для моего скрипта, нужно добавлять, после каждого send, проверку удерживается ли клавиша, чтобы добиться такого эффекта:

#UseHook
q::
  KeyWait, %A_ThisHotkey%, T1
  If ErrorLevel
      While GetKeyState(A_ThisHotkey,"P") {
    SendInput {1}
    If !GetKeyState(A_ThisHotkey,"P")
    Break
    Sleep 200
    SendInput {2}
    If !GetKeyState(A_ThisHotkey,"P")
    Break
    Sleep 200
    SendInput {3}
    If !GetKeyState(A_ThisHotkey,"P")
    Break
    Sleep 200
  }
  Else
      SendInput % A_ThisHotkey
Return

Для варианта teadrinker, можно использовать массив, чтобы легче было добавлять\изменять посылаемые клавиши:

#UseHook
Array := Array("1", "2", "3") ; список посылаемых клавиш
for i in Array ; перебор массива, для подсчета количества элементов
ArrayCount++

F1::
   KeyWait, % A_ThisHotkey, T1
   if !ErrorLevel
      SendInput, {%A_ThisHotkey%}
   else  {
      while GetKeyState(A_ThisHotkey, "P")  {
         SendInput, % Array[(k := mod(A_Index, ArrayCount)) ? k : ArrayCount]
         Sleep, 200
      }
   }
   Return

8

Re: AHK: Перебор меток после удержания горячей клавиши

SetKeyDelay, 200 ; пауза между отправленными клавишами

F1::
If f1_is_pressed != 1 ;игнорирует автоповтор
	{
	f1_is_pressed := 1
	start_time := A_TickCount
	Sleep, 1000
	While GetKeyState("F1","P")
	Send 123 ;действия при удержании F1 более секунды
	}
Return

F1 Up::
f1_is_pressed := 0
elapsed_time := A_TickCount - start_time
If (elapsed_time < 1000)
Send {F1} ;F1 отправляет себя
Return

9

Re: AHK: Перебор меток после удержания горячей клавиши

Nikva, спасибо! Ваш вариант, а также вариант от ypppu, немного не подходит, т.к. после отпускания горячей клавиши выполняется еще одна (идущая следом) метка. А вариант от teadrinker прекращает работу моментально, как и необходимо.

Заметил в моем случае неудобный момент. После длительного удержания (нескольких циклов перебора меток), модификаторы из массива переходят к горячей клавише. Т.е. проскакивает нажатие ^+m. Как от этого избавиться?

#UseHook
Array := Array("^+{f1}", "^+{f2}")
for i in Array ; перебор массива, для подсчета количества элементов
ArrayCount++

m::
   KeyWait, % A_ThisHotkey, T0.3
   if !ErrorLevel
      SendInput, {%A_ThisHotkey%}
   else  {
      while GetKeyState(A_ThisHotkey, "P")  {
         SendInput, % Array[(k := mod(A_Index, ArrayCount)) ? k : ArrayCount]
         Sleep, 500
      }
   }
   Return
Win10x64, AHK v1.1.25

10

Re: AHK: Перебор меток после удержания горячей клавиши

#UseHook
Array := ["^+{f1}", "^+{f2}"], max := Array.MaxIndex()
Return

#If processing
*sc32:: Return
#If

sc32::   ; m
   KeyWait, % A_ThisHotkey, T0.3
   if !ErrorLevel
      SendInput, {%A_ThisHotkey%}
   else  {
      while GetKeyState(A_ThisHotkey, "P") && processing := 1  {
         SendInput, % Array[(k := mod(A_Index, max)) ? k : max]
         Sleep, 500
      }
      processing := ""
   }
   Return
Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Skype dmitry_fiveg

11

Re: AHK: Перебор меток после удержания горячей клавиши

teadrinker, Спасибо! Не получается задать условие работы клавиши в определенном контроле. В чем ошибка?

timeline()
{
	Global
	IfWinActive ahk_class Premiere Pro
	{
		MouseGetPos,,,, Ctrl, 2
		ControlGetPos, xCtrl, yCtrl,,,, ahk_id %ctrl%
		if ((yCtrl != 80) and (StateEditing = 520))
			{
				return !ErrorLevel
			}
	}
}

#UseHook
Array := ["^+{f2}", "^+{f7}", "^+{f5}", "^+{f6}", "^+{f1}"], max := Array.MaxIndex()
Return

#If processing
*sc32:: Return
#If

#if timeline()
sc32::   ; m
   KeyWait, % A_ThisHotkey, T0.3
   if !ErrorLevel
      SendInput, {%A_ThisHotkey%}
   else  {
      while GetKeyState(A_ThisHotkey, "P") && processing := 1  {
         SendInput, % Array[(k := mod(A_Index, max)) ? k : max]
         Sleep, 500
      }
      processing := ""
   }
   Return
Win10x64, AHK v1.1.25

12

Re: AHK: Перебор меток после удержания горячей клавиши

Давайте придерживаться темы.

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

13

Re: AHK: Перебор меток после удержания горячей клавиши

teadrinker, а как преобразовать Ваш вариант в функцию? Чтобы можно было задавать горячие клавиши примерно следующим образом:

sc32:: ; m
Hold("^+{f2}", "^+{f7}", "^+{f5}", "^+{f6}", "^+{f1}")
return
Win10x64, AHK v1.1.25

14 (изменено: teadrinker, 2017-03-20 20:33:13)

Re: AHK: Перебор меток после удержания горячей клавиши

#Persistent
Hold("sc32", "0.3", 500, "+{a}", "+{b}")

Hold(MyHotkey := "", TimeOut := "", SleepTime := "", HeldKeys*)  {
   static processing
   
   if (MyHotkey = "")
      Return
   
   else if (MyHotkey != "HotkeyFunc")  {
      HotkeyFunc := Func(A_ThisFunc).Bind("HotkeyFunc", TimeOut, SleepTime, HeldKeys*)
      Hotkey, % MyHotkey, % HotkeyFunc, On
      Hotkey, If, processing
      Hotkey, % "*" . MyHotkey, % A_ThisFunc, On
   }
   else  {
      KeyWait, % A_ThisHotkey, T%TimeOut%
      if !ErrorLevel
         SendInput, {%A_ThisHotkey%}
      else  {
         max := HeldKeys.MaxIndex()
         while GetKeyState(A_ThisHotkey, "P") && processing := 1  {
            SendInput, % HeldKeys[(k := mod(A_Index, max)) ? k : max]
            Sleep, SleepTime
         }
         processing := ""
      }
   }
   #If processing
   #If
}
Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Skype dmitry_fiveg

15

Re: AHK: Перебор меток после удержания горячей клавиши

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

Win10x64, AHK v1.1.25

16

Re: AHK: Перебор меток после удержания горячей клавиши

Да есть такое, подумаю, как исправить.

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

17

Re: AHK: Перебор меток после удержания горячей клавиши

#Persistent
Hold("sc32", "0.3", 100, "+{a}", "+{b}")

Hold(MyHotkey := "", TimeOut := "", SleepTime := "", HeldKeys*)  {
   if (MyHotkey != "HotkeyFunc")  {
      HotkeyFunc := Func(A_ThisFunc).Bind("HotkeyFunc", TimeOut, SleepTime, HeldKeys*)
      Hotkey, % "*" . MyHotkey, % HotkeyFunc, On
   }
   else  {
      key := SubStr(A_ThisHotkey, 2)
      KeyWait, % key, T%TimeOut%
      if !ErrorLevel
         SendInput, {%key%}
      else  {
         max := HeldKeys.MaxIndex()
         while GetKeyState(key, "P")  {
            SendInput, % HeldKeys[(k := mod(A_Index, max)) ? k : max]
            Sleep, SleepTime
         }
      }
   }
}
Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Skype dmitry_fiveg

18

Re: AHK: Перебор меток после удержания горячей клавиши

teadrinker, спасибо! Не то, чтобы есть в этом необходимость, но интересно, почему клавиши A и B отправляются в малом регистре, если активна раскладка клавиатуры на русском языке?

Win10x64, AHK v1.1.25

19

Re: AHK: Перебор меток после удержания горячей клавиши

Сочетание Shift+b имеет смысл, только если эмулировано нажатие клавиши «b», а когда в данной раскладке такой клавиши нет, отправка осуществляется по-другому, читайте справку по Send.

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

20

Re: AHK: Перебор меток после удержания горячей клавиши

teadrinker, спасибо! А как исключить работу гк из других сочетаний? Например, функция срабатывает даже при зажатии Ctrl+Shift+M.

Win10x64, AHK v1.1.25

21 (изменено: teadrinker, 2017-03-21 23:13:14)

Re: AHK: Перебор меток после удержания горячей клавиши

У меня так вроде работает:

#Persistent
Hold( "sc32"  ; m
     , 300, 100
     , "+{m}", "{y}", "+{s}", "{c}", "{r}", "{i}", "{p}", "{t}", "{sc39}" )
Return

Hold(MyHotkey, TimeOut, SleepTime, HeldKeys*)  {
   static oInfo, WH_KEYBOARD_LL := 13
   oInfo := { MyHotkey: MyHotkey, MyHotkeySC: "0x" . SubStr(MyHotkey, 3)
            , TimeOut: TimeOut, SleepTime: SleepTime, HeldKeys: HeldKeys }
   
   DllCall("SetWindowsHookEx", Int, WH_KEYBOARD_LL
      , Ptr, RegisterCallback("LowLevelKeyboardProc", "Fast", 3, pInfo := Object(oInfo))
      , Ptr, DllCall("GetModuleHandle", UInt, 0, Ptr), UInt, 0, Ptr)
   ObjRelease(pInfo)
}

LowLevelKeyboardProc(nCode, wParam, lParam)  {
   static LLKHF_INJECTED := 0x10, WM_KEYDOWN := 0x100, WM_KEYUP := 0x101, timer
   
   Critical
   msg   := wParam
   flags := NumGet(lParam + 8, "UInt")
   ext   := flags & 1
   sc    := NumGet(lParam + 4, "UInt") | ext << 8
   time  := NumGet(lParam + 12, "UInt")
   INJECTED := (flags & LLKHF_INJECTED) >> 4
   oInfo := Object(A_EventInfo)
   
   if (!INJECTED && msg = WM_KEYDOWN && oInfo.KeyDownTime != "")
      Return 1
   
   if (!INJECTED && msg = WM_KEYDOWN && sc = oInfo.MyHotkeySC && oInfo.KeyDownTime = "")  {
      if GetKeyState("Shift", "P") || GetKeyState("Alt", "P") || GetKeyState("Ctrl", "P")
         Return DllCall("CallNextHookEx", Ptr, 0, Int, nCode, Ptr, wParam, Ptr, lParam)
      
      oInfo.KeyDownTime := time
      timer := Func("SendKeys").Bind(oInfo)
      SetTimer, % timer, % "-" . oInfo.TimeOut
      Return 1
   }
   
   if (!INJECTED && msg = WM_KEYUP && sc = oInfo.MyHotkeySC && oInfo.KeyDownTime != "")  {
      SetTimer, % timer, Delete
      if (A_TickCount - oInfo.KeyDownTime <= oInfo.TimeOut)
         SendInput, % "{" oInfo.MyHotkey "}"
      oInfo.KeyDownTime := ""
      Return 1
   }
   Return DllCall("CallNextHookEx", Ptr, 0, Int, nCode, Ptr, wParam, Ptr, lParam)
}

SendKeys(oInfo)  {
   max := oInfo.HeldKeys.MaxIndex()
   while oInfo.KeyDownTime  {
      SendInput, % oInfo.HeldKeys[(k := mod(A_Index, max)) ? k : max]
      Sleep, oInfo.SleepTime
   }
}
Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Skype dmitry_fiveg

22

Re: AHK: Перебор меток после удержания горячей клавиши

teadrinker, да, вроде работает. Спасибо! Скажите, а почему же последний вариант столь сильно увеличился в объеме в сравнении с вариантом без оформления в функцию?

Win10x64, AHK v1.1.25

23

Re: AHK: Перебор меток после удержания горячей клавиши

becauseim, если вы заметили, тут совсем другой подход.

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

24

Re: AHK: Перебор меток после удержания горячей клавиши

teadrinker, да, я заметил, что здесь задействованы системные функции, но не понял, для чего, если предыдущий вариант работал с той же скоростью и столь же стабильно, как мне кажется. Или первый вариант не возможно заключить в функцию без изенения подхода?

Win10x64, AHK v1.1.25

25

Re: AHK: Перебор меток после удержания горячей клавиши

becauseim, я уже запутался, какой именно первый? Ничего невозможного нет, просто я нашёл такое решение в соответствии с задачей, кто-то, может, нашёл бы более короткое.

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