Наконец-то разобрался.
ТЛ; др
Замените ^e
первым желаемым нажатием клавиши. Замените 3
индексом ASCII второго желаемого нажатия клавиши. Это гарантирует, что Ctrl удерживается нажатием обеих клавиш, иначе отменяется.
~$Ctrl UP::
ChordIsBroken := True
Return
^e::
ChordIsBroken := False
Input, OutputVar, L1 M
If (!ChordIsBroken && Asc(OutputVar) = 3)
{
MsgBox "Hello, World!"
}
Else
{
SendInput %OutputVar%
}
Return
Чтобы адаптировать это к Shift вместо Ctrl, вам нужно заменить Ctrl
s, удалить M
и сделать более простое сравнение, например OutputVar = C
вместо Asc(OutputVar) = 3
. Не уверен, как распространить это на Alt
и Win
но вам, возможно, придется попробовать L2
или что-то в этом роде.
объяснение
Input
казался очевидным местом для начала. Input
просит AHK ждать ввода пользователя, например
^e::
Input, OutputVar, L1 ; "L1" means wait for 1 keystroke then continue.
If (OutputVar = "c")
{
MsgBox, "Hello, World!"
}
Return
Окно сообщения выше вызывает по Ctrl E затем C. Но мы ищем Ctrl C, так что давайте исправим это:
^e::
Input, OutputVar, L1 M ; "M" allows storage of modified keystrokes (^c).
If (Asc(OutputVar) = 3) ; ASCII character 3 is ^c.
{
MsgBox "Hello, World!"
}
Return
Теперь у нас есть окно сообщения о нажатии Ctrl E, а затем Ctrl C. Но есть проблема с этим: окно сообщения срабатывает, даже когда я нажимаю Ctrl между двумя нажатиями клавиш. Итак, как мы можем определить, по существу, {Ctrl Up}
средний ввод? Вы не можете просто проверить на входе
^e::
if (!GetKeyState("Ctrl"))
{
Return
}
Input, OutputVar, L1 M
; ...
Не можете просто проверить после ввода
^e::
Input, OutputVar, L1 M
if (!GetKeyState("Ctrl"))
{
Return
}
; ...
- ни один из них не сработает, потому что, несмотря ни на что, вы пропустите {Ctrl Up}
при блокировке ввода.
Затем я заглянул в документацию по Hotkey
для вдохновения. Оператор пользовательской комбинации &
, казалось многообещающим. Но, к сожалению,
^e & ^c::
; ...
вызвала ошибку компиляции; по-видимому, &
предназначен только для комбинации неизмененных нажатий клавиш.
Наконец-то дело дошло до UP
, и вот, наконец, я совершил прорыв. Я переопределил Ctrl 's UP
чтобы установить переключатель, который бы препятствовал срабатыванию окна сообщения!
$Ctrl::Send {Ctrl Down} ; The $ prevents an infinite loop. Although this
$Ctrl UP:: ; line seems redundant, it is in fact necessary.
ChordIsBroken := True ; Without it, Ctrl becomes effectively disabled.
Send {Ctrl Up}
Return
^e::
ChordIsBroken := False
Input, OutputVar, L1 M
If (!ChordIsBroken && Asc(OutputVar) = 3)
{
MsgBox "Hello, World!"
}
Return
Теперь, когда я нажимаю Ctrl E, затем отпускаю Ctrl и нажимаю Ctrl C, ничего не происходит, как ожидалось!
Была одна последняя вещь, которую нужно исправить. При "отмене" ("сломанный аккорд") я хотел, чтобы все нажатия клавиш вернулись в нормальное состояние. Но в приведенном выше коде Input
должен был бы "съесть" нажатие клавиши перед возвратом, независимо от разрыва аккорда или неуместного вторичного нажатия клавиши. Добавление случая Else
хорошо решает это:
Else
{
SendInput %OutputVar%
}
Итак, вот оно - "аккорды" в AutoHotkey. (Хотя я бы точно не назвал это "аккордом". Больше похоже на мелодию с басовой линией ;-)
@hippibruder щедро указывает на то, что я могу избежать определения $Ctrl::
с помощью ~
чтобы сделать $Ctrl UP::
неблокирующим. Это позволяет немного упростить! (См. Раздел tl; dr в верхней части для окончательного результата.)
Еще кое-что. Если, случайно, после "отмены" ("разбитый аккорд"), вы хотите выполнить первое нажатие клавиши, то есть Ctrl E , просто добавьте это в блок Else
,
Else
{
SendInput ^e
SendInput %OutputVar%
}
и не забудьте изменить горячую клавишу на
$^e::
чтобы избежать бесконечного цикла.