1 (изменено: serzh82saratov, 2018-08-11 19:23:19)

Тема: AHK: Замена gui контролу "Hotkey"

+ Здесь содержится старая версия, она более не поддерживается.

Смысл в устранении таких недостатков:
- Буквенные клавиши сохраняются по имени, и потом могут не работать при другой языковой раскладке (есть обходной путь, на данный момент эта проблема решена в AutoHotkey).

- Определяются не все клавиши клавиатуры
- Не определяются кнопки мыши и джойстиков
- Не определяется клавиша модификатор "Win"
- Не определяются левые и правые модификаторы
- Не определяются двойные хоткеи вида "RControl & RShift"

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



https://ic.pics.livejournal.com/the_bestseller/49384395/14190/14190_900.png

----------------------------------------------

Тема для обсуждения

----------------------------------------------

Библиотека Hotkey.ahk

  (правка: 20:58 26.07.2018)

----------------------------------------------

Описание в комментариях примера:


#NoEnv
#SingleInstance Force
Gui, +AlwaysOnTop
; Сохраняем в переменную путь к ини файлу.
PathIni = %A_ScriptDir%\Hotkey.ini
; Создаём Edit, указываем переменную после "hwnd" для сохранения хэндла контрола.
; После "g" указываем функцию которая будет вызыватся при нажатиях клавиш.
; r1 - чтобы не было переноса строки, это обязательно.
; Hotkey_Read(p1[, p2, p3]) - p1 ключ ини файла, p2 секция, p3 путь к ини файлу.
; Читает из ини файла ранее записанный хоткей, и возвращает в понятном виде для отображения в Edit.
; Также cохраняет значение внутри библиотеки в виде хоткея, для дальнейшего извлечения по ID.
; Если надо отобразить хоткей не из файла, читайте ниже про Hotkey_Set.
Gui, Add, Edit, Center w300 r1 hwndhMyHotkey1 gWriteIni, % Hotkey_Read("MyHotkey1", "Section", PathIni)
Gui, Add, Edit, Center wp y+10 r1 hwndhMyHotkey2 gWriteIni, % Hotkey_Read("MyHotkey2", "Section", PathIni)

; Регистрируем Edit`ы, передавая в массивах:
; Первое - связанное уникальное имя (не может быть числом!), которое понадобится например для записи в ини файл, или чтобы по имени узнать текущее значение хоткея.
; Второе - hwnd контрола.
; Третье - опции (необязательно):
; Указываем строку из возможных букв "KMLRJDSWNG1", в любой последовательности:
; если не указано то - "K".

; K - Определять клавиши клавиатуры
; M - Кнопки мыши без левой и правой.
; L - Левая кнопка мыши, для определения необходимо: зажать правую кнопку - зажать левую кнопку - отпустить правую кнопку.
; R - Правая кнопка мыши, определяется при отпускании кнопки.
; J - Кнопки джойстика, определяются без модификаторов, и без опции W.
; D - Определять модификаторы как левые и правые.
; S - Определять только одну нажатую клавишу, то есть без комбинации с модификаторами. С этим параметром опция "D" не имеет смысла.
; W - Определять как двойной хоткей вида "RControl & RShift". С этим параметром опции "D" и "S" не имеют смысла.
; N - 11 Numpad клавиш зависящих от состояния Numlock сохраняются по виртуальному коду, иначе как скан код,
; желательно её наличие или отсутствие во всех контролах внутри группы, так как при разнных опциях есть конфликт их сравнения при повторах.
; Gn - Указываем "G" и сразу за ней номер группы (целое положительное число больше нуля). В контролах из одной группы не могут быть назначены одинаковые ГК.
; Для страховки, при закрытии и\или показе окна с уже созданными контролами, можно запускать Hotkey_Group("CheckAll") для дополнительной проверки повторов.
; Двойной клик по контролу сбрасывает определённые в нём клавиши.

Hotkey_Register(["MyHotkey1",hMyHotkey1,"KD"], ["MyHotkey2",hMyHotkey2,"KMLRJ"])

; Демонстрационный контрол.
Gui, Add, Edit, Center vText wp
Gui, Show
Return

; Функция указанная при создании контролов, в первом параметре указана переменная для передачи Hwnd контрола.
WriteIni(CtrlHwnd) {
    ; Делаем переменную с путём к ини файлу, доступной внутри функции.
    Global PathIni
    ; Получаем из Hwnd связанное с ним имя который вызвал функцию.
	; Имя используем как одноимённый ключ в ини файле.
    Name := Hotkey_ID(CtrlHwnd)
    ; Получаем из Hwnd текущее значение ввиде строки хоткея.
    ; Строка пригодна для записи в ини файл, или установки хоткея.
    Value := Hotkey_Value(CtrlHwnd)
    ; Записываем в ини файл.
    IniWrite, % Value, % PathIni, Section, % Name
    ; Просто для демонстрации.
    GuiControl, , Text, % Name " = " Value
}

GuiClose() { 
    ExitApp
}
+ Тоже без комментариев:
#NoEnv
#SingleInstance Force
Gui, +AlwaysOnTop  
PathIni = %A_ScriptDir%\Hotkey.ini  
Gui, Add, Edit, Center w300 r1 hwndhMyHotkey1 gWriteIni, % Hotkey_Read("MyHotkey1", "Section", PathIni)
Gui, Add, Edit, Center wp y+10 r1 hwndhMyHotkey2 gWriteIni, % Hotkey_Read("MyHotkey2", "Section", PathIni)
Hotkey_Register(["MyHotkey1",hMyHotkey1,"KD"], ["MyHotkey2",hMyHotkey2,"KMLRJ"])
Gui, Add, Edit, Center vText wp
Gui, Show
Return

WriteIni(CtrlHwnd) { 
    Global PathIni 
    Name := Hotkey_ID(CtrlHwnd) 
    Value := Hotkey_Value(CtrlHwnd) 
    IniWrite, % Value, % PathIni, Section, % Name 
    GuiControl, , Text, % Name " = " Value
}

GuiClose() { 
    ExitApp
}

Другие возможности:

Если требуется выводить имена символьных клавиш только как при английской раскладке.

Hotkey_Arr("OnlyEngSym", True)  ; Запускать перед созданием контролов.

Если нужно изменить текст (по умолчанию - "Нет") который выводится при отсутствии нажатых клавиш, указываем новый текст во втором параметре.

Hotkey_Arr("Empty", Text)  ; Запускать перед созданием контролов.

Для удобства можно сохранить путь к ини файлу:

Hotkey_IniPath(Path)

В этом случае при вызове Hotkey_Read или Hotkey_IniWrite можно не указывать третий параметр.
Аналогично можно сохранить секцию ини файла, и также далее её не указывать.

Hotkey_IniSection(Section)

Указав ID, можно записать в ини файл. 
ID - это Hwnd или связанное имя. Напомню, что имя не может быть числом.

Hotkey_IniWrite(ID[, Section, FilePath])

Секцию и путь к инифайлу можно не указывать, если вы их сохранили в библиотеке.
Прочитать из ини файла как есть.

Hotkey_IniRead(Name[, Section, FilePath])

Преобразует строку хоткея для использования с командой Send.

Hotkey_HKToSend(p1[, p2, p3])

MsgBox % Hotkey_HKToSend("~*$>^<+vk53") ; {RCtrl Down}{LShift Down}{vk53}{RCtrl Up}{LShift Up} 
MsgBox % Hotkey_HKToSend("^vk53") ; {LCtrl Down}{vk53}{LCtrl Up}
MsgBox % Hotkey_HKToSend("vk53") ; {vk53}
MsgBox % Hotkey_HKToSend("Enter") ; {Enter}
MsgBox % Hotkey_HKToSend("sc19 & Enter")  ;	{sc19 Down}{Enter Down}{sc19 Up}{Enter Up}

Hotkey_HKToSendShort вернёт краткую версию


MsgBox % Hotkey_HKToSendShort("~*$>^<+vk53") ; ^+{vk53}
MsgBox % Hotkey_HKToSendShort("^vk53") ; ^{vk53}
MsgBox % Hotkey_HKToSendShort("vk53") ; {vk53}
MsgBox % Hotkey_HKToSendShort("Enter") ; {Enter}
MsgBox % Hotkey_HKToSendShort("sc19 & Enter")  ; {sc19}{Enter}

В этих функциях можно прочитать сразу из ини файла, надо указать в p1 ключ, в p2 секцию, p3 путь к файлу. Если путь был установлен с помощью Hotkey_IniPath, то p3 можно не указывать, но если секция была указана с помощью Hotkey_IniSection, то в р2 всё таки придётся указать имя секции или как вызов Hotkey_IniSection().

Получить из ID текущее значение ввиде строки хоткея.

Hotkey_Value(ID)

Получить Hwnd из имени.

Hotkey_ID(Name)

Или имя из Hwnd.

Hotkey_ID(Hwnd)

Получить из строки хоткея, строку такого же вида, как и при отображении в контроле.

Hotkey_HKToStr(HK)

Если требуется отобразить свои клавиши (например при создании контрола) , укажите связанное имя и строку хоткея (вида: "<^vk57", или "+Space" и.т.п.). Также будет назначено значение связанному имени, чего не  произойдёт при использовании Hotkey_HKToStr.

Hotkey_Set(Name, Hotkey)

Если требуется в ходе работы скрипта изменить опции контрола.

Hotkey_ChangeOption(ID, Option)

Удалить контрол и данные о нём. Если указать второй параметр равным нулю, то контрол не будет удалён.

Hotkey_Delete(ID[, Destroy = 1])

0 - отключить все хоткеи библиотеки при скрытии окна, на случай если обнаружен конфликт со своими хоткеями.
1 - включить после отключения при показе окна, при запуске скрипта это не требуется.

Hotkey_InitHotkeys(bool)

----------------------------------------------
Примеры:

+ Назначение хоткеев из назначенных клавиш:

После старта надо кликнуть по иконке скрипта в трее, появится окно, вводим хоткеи, закрываем окно, когда окно закрыто, установленными хоткеями должны вызыватся MsgBoxы. Можно снова кликнуть по иконке показав окно, и изменить хоткеи.


#NoEnv
#SingleInstance Force
OnExit("ExitApp")
Menu, Tray, Click, 1
Menu, Tray, NoStandard
Menu, Tray, Add, Hide/Show, GuiClose
Menu, Tray, Add, ExitApp, ExitApp
Menu, Tray, Default, Hide/Show
Hotkey_IniPath(A_ScriptDir "\Hotkey.ini"), Hotkey_IniSection("Hotkeys")
#IF !GuiShow   ; по данному алгоритму условие не требуется, я добавил чтобы проще было менять на своё.
#IF
GuiShow := 1
Gui, Add, Edit, Center w300 r1 hwndhMyHotkey1, % Hotkey_Read("MyHotkey1")
Gui, Add, Edit, Center wp y+10 r1 hwndhMyHotkey2, % Hotkey_Read("MyHotkey2")
Gui, Add, Edit, Center wp y+10 r1 hwndhMyHotkey3, % Hotkey_Read("MyHotkey3")
Hotkey_Register(["MyHotkey1",hMyHotkey1,"KMJG1"], ["MyHotkey2",hMyHotkey2,"KMJDG1"], ["MyHotkey3",hMyHotkey3,"KMJWG1"])

GuiClose:
	HotkeySet(GuiShow := !GuiShow)
	Gui, Show, % GuiShow ? "" : "Hide"
	Return
	
HotkeySet(Reset=0) {
	Hotkey, IF, !GuiShow   ; по данному алгоритму условие не требуется, я добавил чтобы проще было менять на своё.
	Loop, 3
	{
		IF Reset
			Hotkey, % Hotkey_Value("MyHotkey" A_Index), Off, UseErrorLevel
		Else IF (1, Hotkey_IniWrite("MyHotkey" A_Index))
			Hotkey, % Hotkey_Value("MyHotkey" A_Index), Action%A_Index%, UseErrorLevel On
	}
	Hotkey, IF
}

ExitApp() {
	HotkeySet()
    ExitApp
}

Action1:
	MsgBox, , , % A_ThisLabel "`n" A_ThisHotkey, 0.6
	Return

Action2:
	MsgBox, , , % A_ThisLabel "`n" A_ThisHotkey, 0.6
	Return

Action3:
	MsgBox, , , % A_ThisLabel "`n" A_ThisHotkey, 0.6
	Return
+ Работа с несколькими окнами, контролы объединены в группу (нельзя назначить одинаковые ГК):

#NoEnv
#SingleInstance Force 

Hotkey_Arr("Empty", "NO")
Hotkey_Arr("OnlyEngSym", True)
Hotkey_IniPath(A_ScriptDir "\Hotkey.ini")
Hotkey_IniSection("Hotkeys")

Loop 4
    GuiCreate(A_Index)

GuiCreate(I) {
    Gui, %I%:-DPIScale +AlwaysOnTop +LabelGui
    Gui, %I%:Add, Edit, Center xm ym w300 r1 hwndh1 gSave, % Hotkey_Read(I "Hotkey1")
    Gui, %I%:Add, Edit, Center wp y+10 r1 hwndh2 gSave, % Hotkey_Read(I "Hotkey2")
    Gui, %I%:Add, Edit, Center wp y+10 r1 hwndh3 gSave, % Hotkey_Read(I "Hotkey3")
	Hotkey_Register([I "Hotkey1",h1,"KMLRJG1W"], [I "Hotkey2",h2,"KMLRJDG1"], [I "Hotkey3",h3,"KMLRJG1"])
    Gui, %I%:Show, % "y100 x" 100+(I-1)*350, Hotkey Gui %I%
}

Save(Hwnd) {
    Hotkey_IniWrite(Hwnd)
}

GuiClose() { 
    ExitApp
}
+ Обработка повторов в группах:

В ключе GroupEvents указываем имя своей функции

Hotkey_Arr("GroupEvents", "GroupEventsProc") 

которая в случае совпадения принимает массив с ключами:
names - массив имён в которых есть совпадения.
this - имя в который хотели ввести хоткей.
value - введённый хоткей.
group - номер группы.



#NoEnv
#SingleInstance Force

Hotkey_Group("CheckAll")
Hotkey_Arr("GroupEvents", "GroupEventsProc")
Hotkey_IniPath(A_ScriptDir "\Hotkey.ini")
Hotkey_IniSection("Hotkeys")

Loop 4
    GuiCreate(A_Index)
Return

GroupEventsProc(arr) {
 	for k, v in arr.names
		names .= "`n" v
	WinGetPos, x, y, w, h, % "ahk_id" Hotkey_ID(arr.this)
	S_CoordModeToolTip := A_CoordModeToolTip
	CoordMode, ToolTip, Screen
	ToolTip, % "'" Hotkey_HKToStr(arr.value) "' уже назначено в группе номер: " arr.group names, x + w + 2, y + h + 2, 20
	CoordMode, ToolTip, %S_CoordModeToolTip%
	SetTimer HideTooltip20, -500
	Return

	HideTooltip20:
		ToolTip,,,, 20
		Return
}

GuiCreate(I) {
    Gui, %I%:-DPIScale +AlwaysOnTop +LabelGui
    Gui, %I%:Add, Edit, Center xm ym w300 r1 hwndh1 gSave, % Hotkey_Read(I "Hotkey1")
    Gui, %I%:Add, Edit, Center wp y+10 r1 hwndh2 gSave, % Hotkey_Read(I "Hotkey2")
    Gui, %I%:Add, Edit, Center wp y+10 r1 hwndh3 gSave, % Hotkey_Read(I "Hotkey3")
	Hotkey_Register([I "Hotkey1",h1,"KMLRJG1W"], [I "Hotkey2",h2,"KMLRJDG1"], [I "Hotkey3",h3,"KMLRJG1"])
    Gui, %I%:Show, % "y100 x" 100+(I-1)*350, Hotkey Gui %I%
}

Save(Hwnd) {
    Hotkey_IniWrite(Hwnd)
}

GuiClose() {
    ExitApp
}
По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru Telegram: https://t.me/sergiol982
Win10x64 AhkSpy, Hotkey, ClockGui

2 (изменено: serzh82saratov, 2020-10-19 17:18:45)

Re: AHK: Замена gui контролу "Hotkey"

Новая версия.

Преимущества перед стандартным контролом:

  • Определяются все клавиши клавиатуры

  • Определяются кнопки мыши и джойстиков

  • Определяется клавиша модификатор "Windows"

  • Модификаторы определяются как левые и правые

  • Определяются двойные хоткеи вида "RControl & RShift"

  • Исключение указанных кнопок во всех или указанных контролах

  • Исключение ввода одинаковых хоткеев между указанными контролами

Все приведённые возможности опциональны.

https://raw.githubusercontent.com/serzh82saratov/Hotkey/master/16535_900.png

----------------------------------------------

Тема для обсуждения

----------------------------------------------

Библиотека Hotkey.ahk

 
v2.08        16:33 19.10.2020

----------------------------------------------

Основные функции и опции в комментариях примера:


#NoEnv
#SingleInstance Force
Gui, +AlwaysOnTop

; Сохраняем в библиотеке путь и секцию в ини файле, для удобства использования Hotkey_Read и Hotkey_Write.
Hotkey_IniPath(A_ScriptDir "\Hotkey.ini")
Hotkey_IniSection("Hotkeys")

/*
Создаём контролы, это стандартные контролы Edit, в которые при их фокусе можно будет вводить свои горячие клавиши:

Hotkey_Add(ControlOption, Name, Option = "", Hotkey = "", Func = "", BindString = "", ByRef Hwnd = "")

ControlOption - Такие же опции как и для Gui контрола Edit. По умолчанию применяются опции r1 +ReadOnly +Center.
	Далее прописываются общие для всех контролов опции, если Вы их указали в Hotkey_Arr("ControlOption"),
	далее то что укажите в ControlOption, то есть если Вы где то укажите -Center, то +Center по умолчанию будет отменён.
	ReadOnly выключать не желательно, иначе при некоторых условиях пользователь сможет что то написать.
	В конце поста есть ссылка как изменить цвет фона и текста.
	Если у вас несколько окон, укажите в самом начале имя окна и двоеточие "GuiName:", или проще перед созданием сделайте
	окно по умолчанию с помощью команды "Gui, GuiName:Default" или "Gui, New".

Name - Ваше уникальное имя для контрола. Имя не может быть числом.

Option - Опции определяющие определяемые клавиши, и поведение при этом.
	Указываем строку из возможных букв "KMLRJDSWZNG1", в любой последовательности и регистре:
	если не указано, то - "K".

	K - Определять клавиши клавиатуры
	M - Кнопки мыши без левой и правой.
	L - Левая кнопка мыши, для определения необходимо: при зажатой левой отпустить правую кнопку.
	R - Правая кнопка мыши, определяется при отпускании кнопки.
	J - Кнопки джойстика, определяются без модификаторов, и без опции W.

	N - 11 Numpad клавиш зависящих от состояния Numlock сохраняются по виртуальному коду. Без неё, как скан код, то есть сработают при любом состоянии Numlock.
		Желательно наличие или отсутствие этой опции во всех контролах внутри группы, так как при разнных опциях есть конфликт их сравнения при повторах.

	D - Определять модификаторы как левые и правые.
	S - Определять только одну нажатую клавишу, то есть без комбинации с модификаторами. С этим параметром опция "D" и "Z" не имеет смысла.
	W - Определять как двойной хоткей вида "RControl & RShift". С этим параметром опции "D", "Z" и "S" не имеют смысла. Первой в паре не может быть колёсико мыши и джойстик.
	Z - Можно задать обычный хоткей с модификаторами, или один модификатор.

	Gn - Указываем "G" и сразу за ней номер группы (целое положительное число больше нуля). В контролах из одной группы не могут быть назначены одинаковые ГК.
		При повторе, поле ввода очищается, те контролы в которых назначен аналогичный хоткей, обозначаются миганием.
		Можно получать сообщение в своей функции, о том в каких контролах было совпадение, см. спойлер "Обработка повторов в группах".
		Для страховки, при закрытии и\или показе окна с уже созданными контролами, можно запускать Hotkey_Group("CheckAll") для дополнительной проверки повторов.

	Двойной клик по контролу очищает определённые в нём клавиши.

Hotkey - Указываем хоткей для отображения в контроле, в данном случае читаем из файла.
	Hotkey должен быть вида: "<^vk57", или "+Space" и.т.п. а не как строка в контроле.
	Учтите, что указав свой хоткей в виде строки он не будет сохранён в ини файл.
	Вы можете после создания контрола использовать Hotkey_Write, или первым символом в хоткее указать ":",
	в этом случае запись будет произведена в ключ с именем указанным в Name, и только если путь и секция 
	уже сохранены в Hotkey_IniPath и Hotkey_IniSection.
	Также если путь и секция уже сохранены, можно передать Hotkey как символ "*", в этом случае  он будет
	прочитан с помощью Hotkey_Read с переданным вами именем во втором параметре (т.е. результат будет таким же как в этом примере). 
	Модификаторы указываются в порядке ^+!#.
	Как правильно указать клавишу, см. ссылку "Синтаксис указания хоткеев" в конце поста.

Func - Указываем имя функции которая в первом параметре принимает Name, во втором (необязательном) Hwnd контрола.
	Функция вызывается при вводе хоткея пользователем и после проверки повторов.

BindString - Вы можете сохранить для себя строку привязанную к контролу по его имени.

Hwnd - Вы можете указать имя своей переменной (без кавычек), для сохранения хэндла контрола. Но Вы всегда можете получить хэндл контрола из его имени - Hotkey_ID(имя).
	В этой версии сделано так, что хэндл контрола вам не должен понадобится, все обращения к функциям контролов производятся по имени.
*/

Hotkey_Add("w300", "MyHotkey1", "G1KD", Hotkey_Read("MyHotkey1"), "Save")
Hotkey_Add("wp y+10", "MyHotkey2", "G1KMLRJ", Hotkey_Read("MyHotkey2"), "Save")

; Демо контрол.
Gui, Add, Edit, Center vText wp
Gui, Show
Return

Save(Name) {
    ; Записываем в ини файл. Путь и секция используются из Hotkey_IniPath и Hotkey_IniSection которые указали в начале.
    ; Hotkey_Write возвращает то что записал.
	HotKey := Hotkey_Write(Name)
    ; Просто для демонстрации.
    GuiControl, , Text, % Name " = " HotKey
}

GuiClose() {
    ExitApp
}
+ Тоже без комментариев, и по короче.

#NoEnv
#SingleInstance Force
Gui, +AlwaysOnTop
Hotkey_IniPath(A_ScriptDir "\Hotkey.ini"), Hotkey_IniSection("Hotkeys")
Hotkey_Add("w300", "MyHotkey1", "G1KD", "*", "Save")
Hotkey_Add("wp y+10", "MyHotkey2", "G1KMLRJ", "*", "Save")
Gui, Add, Edit, Center vText wp
Gui, Show
Return

Save(Name) { 
    GuiControl, , Text, % Name " = " Hotkey_Write(Name)
}

GuiClose() {
    ExitApp
}

----------------------------------------------

Горячие клавиши установленные вами в вашем скрипте, могут не работать если они установлены не по скан коду,
а такие же в библиотеке по скан коду, вообщем см. ссылку "Синтаксис указания хоткеев" в конце поста.

Если нужно запретить для ввода некоторые клавиши, Вы можете передать их строкой через разделитель |.
Вторым параметром можно указать имя контрола, если эти клавиши надо запретить именно в нём, если второй
параметр пуст, указанные клавиши будут запрещены во всех контролах.
Если введена запрещённая клавиша, хоткей сбрасывается также как при двойном клике по контролу.
Как правильно указать кнопки, см. ссылку "Синтаксис указания хоткеев" в конце поста.

Hotkey_BanKey("LAlt|RAlt")  ;	Запретить Alt для всех контролов

Прочитать из ини файла. Name - имя ключа в ини файле. Функция возвращает прочтённую строку.

Hotkey_Read(Name, Section = "", FilePath = "")

Записать в ини файл. Name - имя контрола, записан будет хоткей извлечённый из Hotkey_Value по переданному имени,
в ключ с указанным именем. Функция возвращает записанную строку.

Hotkey_Write(Name, Section = "", FilePath = "")

Для удобства можно сохранить путь к ини файлу:

Hotkey_IniPath(Path)

В этом случае при вызове Hotkey_Read или Hotkey_Write можно не указывать третий параметр.
Аналогично можно сохранить секцию ини файла, и не указывать второй параметр при чтении и записи.

Hotkey_IniSection(Section)

Вместо Hotkey_Read или Hotkey_Write Вы можете использовать свои методы работы с ини файлом.

Преобразует строку хоткея для использования с командой Send. Count - количество нажатий.

Hotkey_HKToSend(HK, Count = "")

MsgBox % Hotkey_HKToSend("~*$>^<+vk53") ; ^+{vk53}
MsgBox % Hotkey_HKToSend("^vk53") ; ^{vk53}
MsgBox % Hotkey_HKToSend("vk53") ; {vk53}
MsgBox % Hotkey_HKToSend("Enter") ; {Enter}
MsgBox % Hotkey_HKToSend("sc19 & Enter")  ; {sc19}{Enter}

HKToSendEx преобразует модификаторы в нажатия и отпускания, по собственному опыту так они реже залипают.

Hotkey_HKToSendEx(HK, Count = "")

MsgBox % Hotkey_HKToSendEx("~*$>^<+vk53") ; {RCtrl Down}{LShift Down}{vk53}{RCtrl Up}{LShift Up}
MsgBox % Hotkey_HKToSendEx("^vk53") ; {LCtrl Down}{vk53}{LCtrl Up}
MsgBox % Hotkey_HKToSendEx("vk53") ; {vk53}
MsgBox % Hotkey_HKToSendEx("Enter") ; {Enter}
MsgBox % Hotkey_HKToSendEx("sc19 & Enter")  ;	{sc19 Down}{Enter Down}{sc19 Up}{Enter Up}

Получить из строки хоткея, строку такого же вида, как и при отображении в контроле.

MsgBox % Hotkey_HKToStr(HK)

Получить хэндл из имени, или имя из хэндла.

MsgBox % Hotkey_ID(ID)

Если в ходе работы скрипта требуется самому установить хоткей. Без проверки повторов.

Hotkey_Set(Name, Hotkey)

Получить строку опций активного контрола, пусто если Hook не установлен в данный момент.

MsgBox % Hotkey_Arr("Hook")

Получить строку опций контрола.

MsgBox % Hotkey_Options(Name)

Если в ходе работы скрипта требуется установить новые опции для контрола.

Hotkey_ChangeOption(Name, Option)

Удалить контрол и данные о нём. Если указать второй параметр равным нулю, то контрол не будет удалён.

Hotkey_Delete(Name, Destroy = 1)

Отключить или включить все хоткеи библиотеки.
0 - отключить, например при скрытии окна, на случай если обнаружен конфликт со своими хоткеями.
1 - включить, например при показе окна, при запуске скрипта это не требуется.

Hotkey_InitHotkeys(bool)

При запуске можно оставить хоткеи отключенными.

Hotkey_Arr("ResetAllways", True)  ; Запускать перед созданием контролов.

Если требуется перебрать все контролы.

for name, hwnd in Hotkey_Arr("AllHotkeys")
	MsgBox % name "`n" hwnd 

Показать привязанную строку, пример есть про "Переназначение клавиш".

MsgBox % Hotkey_Arr("BindString")[Name]

Получить строку хоткея из имени.

MsgBox % Hotkey_Value(Name)

Получить строку как при отображении из имени.

MsgBox % Hotkey_ValueText(Name)

Если требуется выводить имена символьных клавиш только как при английской раскладке.

Hotkey_Arr("OnlyEngSym", True)  ; Запускать перед созданием контролов.

Если нужно изменить текст (по умолчанию - "Нет") который выводится при отсутствии нажатых клавиш, указываем новый текст во втором параметре.

Hotkey_Arr("Empty", "Мой текст")  ; Запускать перед созданием контролов.

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

Hotkey_Arr("User")

Снять фокус с контрола. Если Name пусто или не указано, то фокус будет снят с любого зарегистрированного контрола.

Hotkey_KillFocus(Name = "")

Установить фокус.

Hotkey_SetFocus(Name)

Если при клике по заголовку окна, месте окна без контролов или контролу не принимающему фокус нужно снимать фокус с контролов Edit.
Будет действовать для всех полей Edit в том окне, где есть хоть один добавленный контрол.

Hotkey_Arr("KillFocus", true)  ; Запускать перед созданием контролов.

Если нужно переместить или изменить размер контрола, Option тоже самое как для GuiControl Move ("x10 y20 w200 h100").

Hotkey_Move(Name, Option)

Если нужно блокировать контрол, если второй параметр false - разблокировать.

Hotkey_Disable(Name)

Если нужно скрыть контрол, если второй параметр false - показать.

Hotkey_Hide(Name)

Получить в своей функции OnFocusFunc сообщение об активации контрола, в первом параметре принимается имя.

Hotkey_Arr("OnFocus", Func("OnFocusFunc"))

OnFocusFunc(name) { 
	MsgBox % name
}

----------------------------------------------
Примеры:

+ Назначение хоткеев из назначенных клавиш.

Вводим хоткеи, закрываем окно, когда окно закрыто, установленными хоткеями должны вызыватся MsgBoxы. Можно снова кликнуть по иконке показав окно, и изменить хоткеи.


#NoEnv
#SingleInstance Force
OnExit("ExitApp")
Menu, Tray, Click, 1
Menu, Tray, NoStandard
Menu, Tray, Add, Hide/Show, GuiClose
Menu, Tray, Add, ExitApp, ExitApp
Menu, Tray, Default, Hide/Show
Hotkey_IniPath(A_ScriptDir "\Hotkey.ini"), Hotkey_IniSection("Hotkeys")
#IF !GuiShow
#IF
GuiShow := 0
Hotkey_Add("w300", "MyHotkey1", "KMJG1", "*")
Hotkey_Add("wp y+10", "MyHotkey2", "KMJG1", "*")
Hotkey_Add("wp y+10", "MyHotkey3", "KMJG1", "*")

GuiClose:
	HotkeySet(GuiShow := !GuiShow)
	Gui, Show, % GuiShow ? "" : "Hide"
	Return

HotkeySet(Reset=0) {
	Hotkey, IF, !GuiShow
	for name in Hotkey_Arr("AllHotkeys")
	{
		IF Reset
			Hotkey, % Hotkey_Value(name), Off, UseErrorLevel
		Else
			Hotkey, % Hotkey_Write(name), L_%name%, UseErrorLevel On
	}
	Hotkey, IF
}

ExitApp() {
	HotkeySet()
    ExitApp
}

L_MyHotkey1:
	MsgBox, , , % A_ThisLabel "`n" A_ThisHotkey, 0.6
	Return

L_MyHotkey2:
	MsgBox, , , % A_ThisLabel "`n" A_ThisHotkey, 0.6
	Return

L_MyHotkey3:
	MsgBox, , , % A_ThisLabel "`n" A_ThisHotkey, 0.6
	Return
+ Переназначение клавиш (назначаем хоткей, и назначаем клавиши которые он отправляет с помощью Send).

Более продвинутый пример, так как не требуется подтверждение сохранения \ назначения, хоткеи работают сразу после снятия фокуса с полей ввода.


#SingleInstance Force
#NoEnv
#UseHook
#IF !Hotkey_Arr("Hook")
#IF
 
Hotkey_IniPath("Hotkey.ini")
Hotkey_IniSection("Hotkeys")

Gui, Color, 0xFFDD8A, 0xFFFFAA
Gui, Font, s12
Loop 5
{ 
	Gui, Add, Text, cRed xm y+20, Press %A_Index%:
	Hotkey_Add("cRed w400 yp x+10 Section", "Press" A_Index, "G1KMLRJD", "*", "FuncPress", "Send" A_Index)
	Gui, Add, Text, xm, Send %A_Index%:
	Hotkey_Add("w400 yp xs", "Send" A_Index, "KMLRJ", "*", "FuncSend") 
	Gui, Add, GroupBox, wp+100 h14 y+10 xm
	FuncPress("Press" A_Index), FuncSend("Send" A_Index)
} 
Gui, Add, Edit, wp y+20 r10
Gui, Show 
return 

FuncPress(name) {
	Static PrKey := {}  
	Hotkey, IF, !Hotkey_Arr("Hook")
	Hotkey, % PrKey[name], Off, UseErrorLevel
	PrKey[name] := Hotkey_Write(name)  
	fn := Func("ActionPress").Bind(Hotkey_Arr("BindString")[Name]) 
	Hotkey, % PrKey[name], % fn, On, UseErrorLevel 
	Hotkey, IF
}

FuncSend(name) { 
	Hotkey_Arr("User")["StrSend_" name] := Hotkey_HKToSend(Hotkey_Write(name)) 
}

ActionPress(name) {  
	SendInput % Hotkey_Arr("User")["StrSend_" name]
}

GuiClose() {
    ExitApp
}
+ Обработка повторов в группах (несколько окон).

В ключе OnGroup указываем имя своей функции

Hotkey_Arr("OnGroup", FuncName) 

которая в случае совпадения внутри группы принимает массив с ключами:
names - массив имён в которых есть совпадения.
this - имя в который хотели ввести хоткей.
value - введённый хоткей.
group - номер группы.


#NoEnv
#SingleInstance Force

Hotkey_Arr("OnGroup", "OnGroupProc")
Hotkey_IniPath(A_ScriptDir "\Hotkey.ini")
Hotkey_IniSection("Hotkeys")

Loop 4
    GuiCreate(A_Index)
Hotkey_Group("CheckAll")
Return

OnGroupProc(arr) {
 	for k, v in arr.names
		names .= "`n" v
	WinGetPos, x, y, w, h, % "ahk_id" Hotkey_ID(arr.this)
	S_CoordModeToolTip := A_CoordModeToolTip
	CoordMode, ToolTip, Screen
	ToolTip, % "'" Hotkey_HKToStr(arr.value) "' уже назначено в группе номер: " arr.group names, x + w + 2, y + h + 2, 20
	CoordMode, ToolTip, %S_CoordModeToolTip%
	SetTimer HideTooltip20, -500
	Return

	HideTooltip20:
		ToolTip,,,, 20
		Return
}

GuiCreate(I) {
	Gui, New, -DPIScale +AlwaysOnTop +LabelGui
	Hotkey_Add("w300", I "Hotkey1", "KMLRJG1W", "*", "Save")
	Hotkey_Add("wp y+10", I "Hotkey2", "KMLRJDG1", "*", "Save")
	Hotkey_Add("wp y+10", I "Hotkey3", "KMLRJG1", "*", "Save")
	Gui, Show, % "y100 x" 100+(I-1)*450, Hotkey Gui %I%
}

Save(Name) {
    Hotkey_Write(Name)
}

GuiClose() {
    ExitApp
}
+ Listview

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


#NoEnv
#SingleInstance Force

Hotkey_IniPath(A_ScriptDir "\Hotkey.ini")
Hotkey_IniSection("Hotkeys") 

Gui, -DPIScale  
Gui, Font, s14

LVS_EX_INFOTIP = LV0x400   ;  уведомляющее сообщение LVN_GETINFOTIP
LVS_EX_HEADERDRAGDROP = LV0x10   ;  	Включает перетаскивание столбцов в элементе управления представления списка.

Gui, Add, Listview
, w600 h480 cBlue gListview AltSubmit NoSortHdr Grid -Multi -%LVS_EX_HEADERDRAGDROP% +%LVS_EX_INFOTIP% 
, Действие|Хоткей 
 
Loop 12
{
	Name := "Action" A_Index 
	Hotkey_Add("Hotkey:w300 gHotkeyText", Name, "KMJG1", "*", "Save", A_Index)
	LV_Add("", Name, Hotkey_ValueText(Name))
}  
LV_ModifyCol(1, "250")
LV_ModifyCol(2, "340 Center") 
Gui, Show
Return

Listview() {
	Critical 
	i := LV_GetNext()
	If !i || !Hotkey_ID("Action" i)
		Return Hotkey_Arr("Hook") && Hotkey_Main()
	If Hotkey_Arr("Hook") && (A_GuiEvent == "f" || A_GuiEvent = "S")
		Hotkey_Main(), LV_Modify(i, "-Focus"), LV_Modify(i, "-Select")  
	Else If (A_GuiEvent = "DoubleClick")
		LV_Modify(i, "col" 2, Hotkey_Main("Clean"))
	Else If (A_GuiEvent == "Normal" || A_GuiEvent == "F") 
		Hotkey_Main(Hotkey_ID("Action" i))   
}
	

GLabel(Name) {
	LV_Modify(Hotkey_Arr("BindString")[Name], "col" 2, Hotkey_ValueText(Name))
} 

HotkeyText(hwnd) {  
	funcobj := Func("GLabel").Bind(Hotkey_ID(hwnd))
	Try SetTimer, % funcobj, -1
}

Save(Name) {
	Hotkey_Write(Name)
}

GuiEscape:
GuiClose:
Escape::  ExitApp

----------------------------------------------

Синтаксис указания хоткеев.

----------------------------------------------

Изменить цвет фона и текста.

----------------------------------------------

+ Если Вы пользовались предыдущей версией.

Изначально была ошибка в том, что я стал использовать модификаторы в отличном, от стандартного контрола, порядке - Ctrl + Alt + Shift + Win.
Получается переходя с обычного контрола на библиотеку, хоткеи из ини файла могут не определится в группе как повторы.
Если у вас хоткеи объединены в группы, и Вы хотите перейти на новую версию, то можете при первом запуске новой версии у пользователя,
переписать все хоткеи в его ини файле с Ctrl + Alt + Shift + Win на Ctrl + Shift + Alt + Win, и записать в ини что проверка уже была,
чтобы не переписывать при каждом запуске. Функция для форматирования хоткея в новый вид.

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru Telegram: https://t.me/sergiol982
Win10x64 AhkSpy, Hotkey, ClockGui