1 (изменено: Gutalin, 2020-02-24 20:02:39)

Тема: AHK: Скрипт для зацикливания клавиш

Предлагаю вашему вниманию мой скрипт.
Прошу сообщать о всевозможных багах и ошибках в данную тему (или мне на почту).
Скрипт способен зациклить клавишу(и) или сочетания клавиш в активном окне.
Чтобы начать работу:
1)Снимите блокировку ввода, нажав на замочек;
2)В поле "Горячая клавиша" введите клавишу(и) для зацикливания;
(Для определения Левой Кнопки Мыши необходимо: зажать правую кнопку -> зажать левую кнопку -> отпустить правую кнопку или, удерживая левую кнопку, щёлкнуть правой. Двойной клик по строке ввода клавиш сбрасывает определённые в нём данные.)
3)В поле "Задержка" выберете в выпадающем списке выберете единицу времени, а в поле ввода - количество времени, через которое будет нажиматься клавиша.
Старт: F2.
Стоп(Сброс): F3 (Таймер скрипта будет запускаться заново).
Закрыть программу: Esc.

В прикреплённом архиве содержится скомпилированный скрипт и 2 картинки замка для не скомпилированного кода (картинки скопировать в %A_Temp%\Биндик\).

Если вы работаете с ahk файлом:
1)Создайте папку;
2)Переместите в неё ahk файл данного скрипта;
3)Поместите туда же  библиотеку для Hotkey от serzh82saratov версии  2.06 под названием Hotkey.ahk ;

В скомпилированной версии (exe файл) данной процедуры проводить не нужно!

ini файл хранит в себе настройки программы и  находится в директории(папке) со скриптом. Чтобы настройки не сбросились его лучше не удалять!

Код:

+ V1.8


#NoEnv
#SingleInstance Force
#NoTrayIcon

FileInstall, D:\unlock.png, %A_Temp%\Биндик\unlock.png 
FileInstall, D:\lock.png, %A_Temp%\Биндик\lock.png ;  Вшиваем картинки в exe

#include %A_ScriptDir%/Hotkey.ahk ;  Подключаем библиотеку Hotkey

SaveFile = %A_ScriptDir%/info.ini 
Hotkey_IniPath(SaveFile)
Hotkey_IniSection("Keys")
Hotkey_Arr("KillFocus", true) ;  см. библиотеку Hotkey
GoSub Restore

{ ;  Считывание данных из ini файла
IniRead, MyHotkey1, %SaveFile%, Keys, MyHotkey1
b1 := WhatKey(MyHotkey1)
IniRead, MyHotkey2, %SaveFile%, Keys, MyHotkey2
b2 := WhatKey(MyHotkey2)
IniRead, BToggle, %SaveFile%, Keys, BToggle
IniRead, BStop, %SaveFile%, Keys, BStop
IniRead, BExit, %SaveFile%, Keys, BExit
IniRead, Ind, %SaveFile%, Settings, Ind
IniRead, Num1, %SaveFile%, Time, Num1
IniRead, Delay1, %SaveFile%, Time, Delay1
IniRead, Num2, %SaveFile%, Time, Num2
IniRead, Delay2, %SaveFile%, Time, Delay2
IniRead, NameWin, %SaveFile%, Settings, NameWin
If NameWin is space
	NameWin := "Во всех окнах"
IniRead, size, %SaveFile%, Settings, IndSize
IfNotExist, %A_Temp%\Биндик
	FileCreateDir, %A_Temp%\Биндик
}

{ ;  Main
Gui, +hwndhGui
Menu, HelpMenu, Add, Настройки, Settings
Menu, HelpMenu, Add, Связь с разработчиком, Link
Menu, HelpMenu, Add, О программе, MenuHandler
Menu, MyMenuBar, Add, Помощь, :HelpMenu
Gui, Menu, MyMenuBar
Gui, font, cRed s8
Gui, Add, Text, Center x0 y-2 h15 w220 hwndWindowCheck,
Gui, font, cRed s15
if NameWin != Во всех окнах
	GuiControl, Text, %WindowCheck%, Установленно определённое окно
Gui, Add, Text, Center x10 y10 w210 h25 vSt, Скрипт остановлен
Gui, Add, Picture, x220 y0 w22 h39 vState1 gLock, %A_Temp%\Биндик\unlock.png
Gui, Add, Picture, x220 y0 w22 h39 vState0 gLock, %A_Temp%\Биндик\lock.png
Gui, font
Gui, Add, GroupBox, x10 y40 w240 h63, #1
Gui, Add, Text, xp+10 yp+15, Горячая клавиша:
Hotkey_Add("Center x140 yp-3 w100 h15 -ReadOnly", "MyHotkey1", "KMLDRJNG1", Hotkey_Read("MyHotkey1"), "Save")
Gui, Add, Text, x20 yp+27, Задержка                 :
Gui, Add, DropDownList, xp+55 yp-3 w45 vDelay1 gDropDownList1 AltSubmit Choose%Delay1%, мс.|сек.|мин.
Gui, Add, Edit, Number Center x140 yp+1 w100 h20 vNum1 hwndhEdit1 gEdit1,
GuiControl, , Num1, %Num1%
Gui, Add, GroupBox, x10 yp+30 w240 h63, #2
Gui, Add, Text, x20 yp+15, Горячая клавиша:
Hotkey_Add("Center x140 yp-3 w100 h15 -ReadOnly", "MyHotkey2", "KMLDRJNG1", Hotkey_Read("MyHotkey2"), "Save")
Gui, Add, Text, x20 yp+27, Задержка                 :
Gui, Add, DropDownList, xp+55 yp-3 w45 vDelay2 gDropDownList2 AltSubmit Choose%Delay2%, мс.|сек.|мин.
Gui, Add, Edit, Center number x140 yp+1 w100 h20 vNum2 hwndhEdit2 gEdit2
GuiControl, , Num2, %Num2%
Gui, font, cBlack
ControlFocus, , % "ahk_id" Hotkey_Arr("Focus")[hGui] 
T := "off"
l := "unlock"
GoSub Lock
Gui, Show, Restore  w260 h175, Биндик

GoSub Ind
WinActivate, Биндик

SwitchHotKeys("on") ;  Включаем Хоткеи

}return

Restore: ;  Проверяет есть ли ini файл в дериктории скрипта. Если его нет, оно его создаёт.
{
	IfNotExist, %SaveFile%
	{
		IniWrite, %A_Space%, %SaveFile%, Keys, MyHotkey1
		IniWrite, %A_Space%, %SaveFile%, Keys, MyHotkey2
		IniWrite, vk71, %SaveFile%, Keys, BToggle
		IniWrite, vk72, %SaveFile%, Keys, BStop
		IniWrite, Esc, %SaveFile%, Keys, BExit
		IniWrite, 0, %SaveFile%, Time, Num1
		IniWrite, 2, %SaveFile%, Time, Delay1
		IniWrite, 0, %SaveFile%, Time, Num2
		IniWrite, 2, %SaveFile%, Time, Delay2
		IniWrite, 1, %SaveFile%, Settings, Ind
		IniWrite, %A_Space%, %SaveFile%, Settings, NameWin
		IniWrite, 10, %SaveFile%, Settings, IndSize
	}
}return

DropDownList1:
{
	GuiControlGet, Delay1, , Delay1
	IniWrite, %Delay1%, %SaveFile%, Time, Delay1
	goto Edit1
}return


DropDownList2:
{
	GuiControlGet, Delay2, , Delay2
	IniWrite, %Delay2%, %SaveFile%, Time, Delay2
	goto Edit2
}return


Edit1:
{
	GuiControlGet, Num1, , Num1
	if (Num1 = "" || 0)
		SendMessage, EM_SETCUEBANNER := 0x1501, 0, "0", , ahk_id %hEdit1%
	if Delay1 = 1
		Rezz1 := Num1
	if Delay1 = 2
		Rezz1:= Num1*1000
	if Delay1 = 3
		Rezz1 := Num1*60000
	IniWrite, %Num1%, %SaveFile%, Time, Num1
}return

Edit2:
{
	GuiControlGet, Num2, , Num2
	if Num2 is space 
		SendMessage, EM_SETCUEBANNER := 0x1501, 0, "0", , ahk_id %hEdit2%
	if Delay2 = 1
		Rezz2 := Num2
	if Delay2 = 2
		Rezz2:= Num1*1000
	if Delay2 = 3
		Rezz2 := Num2*60000
	IniWrite, %Num2%, %SaveFile%, Time, Num2
}return

Save(Name) { ;  см. библиотеку Hotkey 
	HotKey := Hotkey_Write(Name)
}

Ind: ;  Окно индикатора скрипта 
{
	Gui, Settings: Submit, NoHide
	IniWrite, %Ind%, %SaveFile%, Settings, Ind
	IniWrite, %size%, %SaveFile%, Settings, IndSize
	If (Ind = 1){
		Gui, Indicator: New, -Caption +ToolWindow +AlwaysOnTop +Border
		If (T = "off")
			Gui,Indicator: Color, Red
		If (T = "on")
			Gui, Indicator: Color, Blue
		Gui, Indicator: Show, Restore x0 y0 w%size% h%size%, Биндик - Индикатор
		GuiControl, Settings: Enable, size
		GuiControl, Settings: Enable, InfoIndSize
		GuiControl, Settings: Enable, Размер индикатора:
		Guicontrol, Settings:, InfoIndSize, %size%
		WinActivate, Биндик - Настройки
	}
	else{
		Gui, Indicator: Destroy
		GuiControl, Settings: Disabled, size
		GuiControl, Settings: Disabled, InfoIndSize
		GuiControl, Settings: Disabled, Размер индикатора:
	}
}return

Lock: ; Блокировка ввода
{
	if (T = "on") ; Остановить скрипт при разблокировке замочка
		gosub, Stop
	if (l = "lock"){ ; Если заблокировано
		GuiControl, Hide, State0
		for name in Hotkey_Arr("AllHotkeys") 
			Hotkey_Disable(Name, 0) 
		GuiControl, -Disabled, Num1
		if Num1 = 0
			GuiControl, , Num1, 
		GuiControl, -Disabled, Num2
		if Num2 = 0
			GuiControl, , Num2, 
		GuiControl, -Disabled, Delay1
		GuiControl, -Disabled, Delay2
		l := "unlock"
	}else if (l = "unlock"){ ; Если разблокировано
	   GuiControl, Show, State0
		for name in Hotkey_Arr("AllHotkeys") 
			Hotkey_Disable(Name) 
		GuiControl, +Disabled, Num1
		if Num1 is space
			GuiControl, , Num1, 0
		GuiControl, +Disabled, Num2
		if Num2 is space
			GuiControl, , Num2, 0
		GuiControl, +Disabled, Delay1
		GuiControl, +Disabled, Delay2
	    l := "lock"
	}
}return

Settings: ; Окно настроек
{
	if (T = "on") ;  Останавлвиваем скрипт при открытии окна настроек
		GoSub, Stop
	SwitchHotKeys("off") ;  Отключаем хоткеи
	Gui, Settings: New
	Gui, Settings: Add, Button, x30 w140 gHelpRestore, Перезаписать ini файл
	Gui, Settings: Add, GroupBox, w180 h90 x10 yp+25, Индикатор:
	Gui, Settings: Add, Checkbox, x20 yp+20 Checked%Ind% vInd gInd, Использовать индикатор?
	Gui, Settings: Add, Text, , Размер индикатора:
	Gui, Settings: Add, Text, w20 xp yp+20 vInfoIndSize, %size%
	Gui, Settings: Add, Slider, altsubmit yp-5 xp+15 w150 gInd vsize TickInterval3 ToolTip range5-20, %size%
	If (Ind = 0){
		GuiControl, Settings: Disabled, size
		GuiControl, Settings: Disabled, InfoIndSize
		GuiControl, Settings: Disabled, Размер индикатора:	
	}
	
	Gui, Settings: Add, Text, x200 y10 h110 0x11
	
	Gui, Settings: Add, GroupBox, w180 h100 y15 x210, Настройка клавиш:
	Gui, Settings: Add, Text, x220 yp+20, Старт:
	Hotkey_Add("Center x280 yp-3 w100 h20 -ReadOnly", "BToggle", "KMLDRJNG1", Hotkey_Read("BToggle"), "Save")
	Gui, Settings: Add, Text, x220 yp+30, Стоп:
	Hotkey_Add("Center x280 yp-3 w100 h15 -ReadOnly", "BStop", "KMLDRJNG1", Hotkey_Read("BStop"), "Save")
	Gui, Settings: Add, Text, x220 yp+23 r2 w60, Закрыть программу:
	Hotkey_Add("Center x280 yp+5 w100 h15 -ReadOnly", "BExit", "KMLDRJNG1", Hotkey_Read("BExit"), "Save")
	
	
	
	Gui, Settings: Add, GroupBox, w380 h215 yp+40 x10, Работает в окне:
	Gui, Settings: Add, Edit, ReadOnly r1 w220 xp+10 yp+17 vNameWin, %NameWin%
	Gui, Settings: Add, Button, gClear xp+230 yp-1, Очистить
	Gui, Settings: Add, Button, gGetInfoAboutWindows xp+70 yp, Обновить
	Gui, Settings: Add, ListView, x20 yp+27 w360 h160 gWindowsListView -Multi, Окна|Процесс
	GetInfoAboutWindows()
	
	Gui, Settings: Show, Restore w400 h350, Биндик - Настройки
	Gui, %hGui%: +Disabled 
}return

Clear: ; Очистка переменной с окном
{
	MsgBox, 4, Внимание!
	, Скрипт будет работать в любом активном окне`nПродолжить?
	IfMsgBox Yes
	{
		IniWrite, %A_Space%, %SaveFile%, Settings, NameWin
		NameWin := "Во всех окнах"
		GuiControl, , NameWin, %NameWin%
		GuiControl, Text, %WindowCheck%,
	}
}return

WindowsListView:
{
	if A_GuiEvent = DoubleClick
	{
		LV_GetText(RowText, A_EventInfo)
		MsgBox, 4, Внимание!
		, Скрипт будет работать только в окне "%RowText%"`nПродолжить?
		IfMsgBox Yes
		{
			NameWin := RowText
			IniWrite, %NameWin%, %SaveFile%, Settings, NameWin
			GuiControl, , NameWin, %NameWin%
			GuiControl, , %WindowCheck%, Установленно определённое окно
		}
	}
}return

GetInfoAboutWindows(){
	LV_Delete()
	WinGet, Windows, List 
	Loop, % Windows
	{
		f := Windows%A_Index%
		WinGetTitle, title, ahk_id %f%
		WinGet, proc, ProcessName, ahk_id %f%
		if title <> Биндик - Настройки
			if title <> Биндик
				if title <> Биндик - Индикатор
					if title <> Program Manager
						if title <>
							LV_Add("", title, proc) ;  Оставим пока так
	}
	LV_ModifyCol()
}return

Link: ;  Связь с разработчиком
	Run, http://forum.script-coding.com/viewtopic.php?pid=123303
return

MenuHandler: ;  О программе
{
	MsgBox, , О программе,
(
Спасибо за помощь в разработке форуму forum.script-coding.com`nОтдельное спасибо пользователям:
serzh82saratov
stealzy
teadrinker
---------------------------------------------------------------------------------
Скрипт способен зациклить клавишу(и) или сочетания клавиш в активном окне.
Чтобы начать работу:
1)Снимите блокировку ввода, нажав на замочек;
2)В поле "Горячая клавиша" введите клавишу(и) для зацикливания;
(Левая кнопка мыши, для определения необходимо: зажать правую кнопку - зажать левую кнопку - отпустить правую кнопку или удерживать левую кнопку и щёлкнуть правой)
Двойной клик по строке ввода клавиш сбрасывает определённые в нём данные.)
3)В поле "Задержка" выберете в выпадающем списке выберете единицу времени, а в поле ввода - количество времени, через которое будет нажиматься клавиша.
Старт: F2.
Стоп(Сброс): F3 (Таймер скрипта будет запускаться заново).
Закрыть программу: Esc.
---------------------------------------------------------------------------------
Версия программы - v1.8
)
}return

HelpRestore: ;  MsgBox перезаписи ini файла
{
MsgBox, 4, Внимание!
, Это действие перезапишет файл Info.ini!`nВсе ваши настройки будут сброшены!`nВы хотите продолжить?
IfMsgBox Yes
{
	Filedelete, %SaveFile%
	GoSub Restore
	Reload
}
}return

;T = on работает
;T = off остановлен

Stop:
{
	T := "off"
	SetTimer, Knopka1, off
	SetTimer, Knopka2, off
	Gui, font, cRed s15
	GuiControl, Font, St
	Guicontrol, , St, Скрипт остановлен
	Gui, Indicator: Color, Red
}return

Start:
{	
	if (l = "unlock") ;  Если разблокировано
		Gosub, lock
	T := "on"
		
	Gui, font, cBlue s15
	Guicontrol, , St, Скрипт работает
	GuiControl, Font, St
	Gui, Indicator: Color, Blue
		
	IniRead, MyHotkey1, %SaveFile%, Keys, MyHotkey1
	b1 := WhatKey(Myhotkey1)
	IniRead, MyHotkey2, %SaveFile%, Keys, MyHotkey2
	b2 := WhatKey(Myhotkey2)
	SetTimer, Loop, -1
	gosub, Knopka1
	gosub, Knopka2 ;  Чтобы при нажатии кнопки %Start% первый символ печатался сразу,а не через прошествие таймера
	Loop:
	{
		SetTimer, Knopka1, %Rezz1%
		SetTimer, Knopka2, %Rezz2%
		return
	}
}return

Knopka1:
{
	If NameWin = Во всех окнах
	{
		IfWinNotActive, Биндик
			SendInput, %b1%
	}else
		IfWinActive, %NameWin%
			SendInput, %b1%
}return

Knopka2:
{
	If NameWin = Во всех окнах
	{
		IfWinNotActive, Биндик
			SendInput, %b2%
	}else
		IfWinActive, % NameWin
			SendInput, %b2%
}return

WhatKey(Name){
	a := "{1 DownTemp}{2 DownTemp}{3 DownTemp}{4 DownTemp}{5 DownTemp}{6 DownTemp}{7 DownTemp}{8 DownTemp}{0}{8 Up}{7 Up}{6 Up}{5 Up}{4 Up}{3 Up}{2 Up}{1 Up}"
	If Instr(Name, "<^")
		StringReplace, a, a, 1, LCtrl, all
	If Instr(Name, ">^")
		StringReplace, a, a, 2, RCtrl, all
	If Instr(Name, "<+")
		StringReplace, a, a, 3, LShift, all
	If Instr(Name, ">+")
		StringReplace, a, a, 4, RShift, all
	If Instr(Name, "<!")
		StringReplace, a, a, 5, LAlt, all
	If Instr(Name, ">!")
		StringReplace, a, a, 6, RAlt, all
	If Instr(Name, "<#")
		StringReplace, a, a, 7, LWin, all
	If Instr(Name, ">#")
		StringReplace, a, a, 8, RWin, all
	loop, 16
	{
		a := RegExReplace(a, "U)[1-8].*p", "", , 1)
	}
	RegExMatch(Name, "[a-zA-Z0-9_].*", K)
	StringReplace, a, a, 0, %K%, 1
	return a
}

SwitchHotKeys(str){ ;  вкл/выкл хоткеев
	global BToggle, BStop, BExit
	if (str = "on"){
		Hotkey %BToggle%, Start, on
		Hotkey %BStop%, Stop, on
		Hotkey %BExit%, Exit, on
	}else{
		Hotkey %BToggle%, Start, off
		Hotkey %BStop%, Stop, off
		Hotkey %BExit%, Exit, off
	}
}return

Exit:
	ExitApp

SettingsGuiClose:
	if BToggle = ""
		BToggle := "vk71"
		IniWrite, vk71, %SaveFile%, Keys, BToggle
	if BStop = ""
		BStop := "vk72"
		IniWrite, vk72, %SaveFile%, Keys, BStop
	if BExit = ""
		BExit := "Esc"
		IniWrite, Esc, %SaveFile%, Keys, BExit ; Переменные с горячими клавишами не должны быть пустыми
	SwitchHotKeys("on")
	Hotkey_Delete("BToggle", Destroy = 1) 
	Hotkey_Delete("BStop", Destroy = 1)
	Hotkey_Delete("BExit", Destroy = 1) ;  см. библиотеку Hotkey
	Gui, Settings: Destroy
	Gui, %hGui%: -Disabled 
	WinActivate, Биндик
	return

Guiclose:
	ExitApp

Ini файл:

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

[Keys]
MyHotkey1=
MyHotkey2=
BToggle=vk71
BStop=vk72
BExit=Esc
[Time]
Num1=0
Delay1=2
Num2=0
Delay2=2
[Settings]
Ind=1
NameWin=
IndSize=10

Нововведения/Исправления:

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

v0.1 (08.08.18)
- Ini файл создаётся сам, если его нет;
- Ini файл можно перезаписать.
v0.2 (09.08.18)
-Убраны кнопки "+" и "-" для большей стабильности (Всегда отображается возможность выбрать 2 кнопки);
-Скрипт сам определяет нажатые кнопки.
v0.3 (10.08.18)
-Убраны лишние строки из кода;
-Использована библиотека для Hotkey от serzh82saratov;
-Убраны кнопки "Сохранить" и "Отмена". Теперь всё сохраняется во время ввода данных.
v0.5 (12.08.18)
-Добавлена блокировка ввода (вкл\выкл на замочек);
-Улучшение самого кода;
-Мелкие улучшения интерфейса.
v1.0 (14.08.18)
-Доработан скрипт зацикливания для сочетаний клавиш.
-Мелкие улучшения интерфейса.
v1.2 (16.08.18)
-Добавлена возможность ставить на паузу;
-Убран значок в трее за ненадобность;
-Добавлен индикатор работы скрипта. (Поверх всех окон);
-Убрана возможность блокировки ввода во время работы скрипта (после нескольких вкл\выкл скрипта он зависал).
v1.3 (17.08.18)
-Добавлена возможность вкл\выкл индикатор в меню Помощь>Настройки;
-Меню "Сбросить ini файл" перенесено в Помощь>Настройки;
-Мелкие улучшения интерфейса.
v1.4 (20.08.18)
-Исправления в работе скрипта;
-Вернулась блокировка ввода;
V1.5(01.12.18)
-Улучшение ввода значения задержки;
-Добавлена возможность настройки зацикливания в определённое окно;
-Небольшие изменения интерфейса.
V1.6(03.04.19)
-Добавлена возможность изменения размера индикатора работы скрипта;
-Изменено расположение ini файла (теперь в директории скрипта);
-Отказ от интеграции в код простым копированием библиотеки Hotkey.ahk от serzh82saratov. Теперь это работает как и должно подразумеваться;
-Отформатирован код с целью улучшить его читаемость (может и до переменных дойду);
V1.7(04.04.19)
-Исправление багов;
-Улучшение интерфейса;
v1.8(24.02.2020)
-Новый интерфейс настроек;
-Добавлена возможность самому задать клавиши Старт/Стоп/Выход из программы;
-Добавлена возможность более точно настроить время;
-Убрана пауза;

Скачать Биндик_x32_x64_v1.8+Pic.rar (Google Drive)

AutoHotkey - 1.1.32.00

2 (изменено: svoboden, 2018-01-23 03:24:31)

Re: AHK: Скрипт для зацикливания клавиш

Забыли Readme.txt еще написать. А если серьезно, то для новичка, наверное, будет полезна данная высокоинтеллектуально развитая программа.

3 (изменено: Gutalin, 2018-08-12 21:11:16)

Re: AHK: Скрипт для зацикливания клавиш

svoboden, если кто не хочет изучать AHK, а просто зациклить пару клавиш... Правда моя программа очень, очень узко раскрывает функционал AHK, но для единичного дела подойдёт.

AutoHotkey - 1.1.32.00

4 (изменено: stealzy, 2018-01-23 17:26:43)

Re: AHK: Скрипт для зацикливания клавиш

Поставить таймер на отправку неких клавиш можно так:

CreateBindSend("bu", 1000)
Sleep 10000

CreateBindSend(sendKeys, period) {
	fnSendKeys := Func("Send").Bind(sendKeys)
	SetTimer % fnSendKeys, % period
}

Send(keys) {
	Send % keys
}

Если делать с возможностью отключения таймера и установки горячих клавиш код становится сложнее, потому что надо сохранять состояния и проверять их.

HotkeyBindTimerSend("F2", ";-]{Space}", 500)
Sleep 7000
HotkeyBindTimerSend("F2") ; выкл
Sleep 7000
HotkeyBindTimerSend("F3", ":o{Space}", 1000)
Return

HotkeyBindTimerSend(hotkey, sendKeys:="", period:=0, winTitle:="") {
	static aExistBinds := {}

	If aExistBinds.HasKey(hotkey)
	{
		fnSendKeysHotkey := aExistBinds[hotkey].fnSendKeys
		Hotkey % hotkey, Off
		fnToggleHotkey := aExistBinds[hotkey].fnToggle
		fnToggleHotkey.Call("Delete")
		SetTimer % fnSendKeysHotkey, Delete

		aExistBinds.Delete(hotkey)		
	}

	If (sendKeys != "" And period)
	{
		fnSendKeys := Func("Send").Bind(sendKeys, winTitle)
		SetTimer % fnSendKeys, % period
		SetTimer % fnSendKeys, Off ; таймер должен начать работать только по ГК, поэтому сразу отключаем
		fnToggle := Func("ToggleSendTimer").Bind(fnSendKeys)
		Hotkey IfWinActive, % winTitle
		Hotkey % hotkey, % fnToggle, On

		aExistBinds[hotkey] := {fnSendKeys: fnSendKeys, fnToggle: fnToggle}
	}
}

ToggleSendTimer(fnSendKeys, deleteTimerRecord := false) { ;
	; SetTimer % fnSendKeys, Toggle ; если бы таймер можно было переключить, достаточно было бы одной этой строки
	static aStateOftimer := {} ; здесь будем хранить состояния таймеров

	If !aStateOftimer.HasKey(fnSendKeys)
		aStateOftimer[fnSendKeys] := false ; начальное состояние таймера

	If deleteTimerRecord
		Return aStateOftimer.Delete(fnSendKeys)

	If ( aStateOftimer[fnSendKeys]  :=  Not aStateOftimer[fnSendKeys] )
	{
		fnSendKeys.Call() ; чтобы не ждать %period% после включения таймера
		SetTimer % fnSendKeys, On
	}
	Else
		SetTimer % fnSendKeys, Off
}

Send(keys, winTitle) {
	If !winTitle OR WinActive(winTitle)
		Send % keys
}

Esc::ExitApp

5

Re: AHK: Скрипт для зацикливания клавиш

stealzy, тогда нужна будет ещё одна кнопка, запускающая скрипт с начала. Спасибо за совет.

AutoHotkey - 1.1.32.00

6

Re: AHK: Скрипт для зацикливания клавиш

stealzy, помогите разобраться пожалуйста.

HotkeyBindTimerSend("F2", ";-]{Space}", 500)

Как я понял это переменная, но почему она имеет такую запись? Почему и что в скобках?

aExistBinds.Delete(hotkey)

и

fnSendKeys := Func("Send").Bind(sendKeys, winTitle)

Что это всё?

AutoHotkey - 1.1.32.00

7

Re: AHK: Скрипт для зацикливания клавиш

Функция, массив и объект-функция.