1 (изменено: serzh82saratov, 2017-03-11 22:39:35)

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

Смысл в устранении таких недостатков:
- Буквенные клавиши сохраняются по имени, и потом могут не работать при другой языковой раскладке (есть обходной путь)
- Определяются не все клавиши клавиатуры
- Не определяются кнопки мыши и джойстиков
- Не определяется клавиша модификатор "Win"
- Не определяются левые и правые модификаторы


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



http://ic.pics.livejournal.com/the_bestseller/49384395/12867/12867_original.png


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

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

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


#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.
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 контрола.
; Третье - опции (необязательно):
; Указываем строку из возможных букв "KMLRJDS", в любой последовательности:
; если не указано то - "K".

; K - Определять клавиши клавиатуры
; M - Кнопки мыши без левой и правой.
; L - Левая кнопка мыши, определяется только при удерживаемой правой кнопке мыши.
; R - Правая кнопка мыши.
; J - Кнопки джойстика, определяются только без модификаторов.
; D - Определять левые и правые модификаторы.
; S - Определять только одну нажатую клавишу, то есть без комбинации с модификаторами. С этим параметром опция "D" не имеет смысла.
; 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}

Можно прочитать сразу из ини файла, надо указать в 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)

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

Hotkey_Delete(ID[, Destroy])

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

+ Работа с несколькими окнами, контролы объединены в группу (нельзя назначить одинаковые ГК), все переменные локальны:

#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 w300 r1 hwndh1 gSave, % Hotkey_Read(I "Hotkey1")
    Gui, %I%:Add, Edit, Center wp y+10 r1 hwndh2 gSave, % Hotkey_Read(I "Hotkey2") 
	Hotkey_Register([I "Hotkey1",h1,"KDG1"], [I "Hotkey2",h2,"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")
	Hotkey_Register([I "Hotkey1",h1,"KMLRJG1"], [I "Hotkey2",h2,"KMLRJDG1"])
    Gui, %I%:Show, % "y100 x" 100+(I-1)*350, Hotkey Gui %I%
}

Save(Hwnd) {
    Hotkey_IniWrite(Hwnd)
}

GuiClose() {
    ExitApp
}

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

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

По вопросам возмездной помощи пишите в личку
E-Mail: serzh82saratov@mail.ru
OS: Win7x64, AutoHotkey_L v1.1.25.02 (Unicode 32-bit).