Например, в Visual Studio Express 2013 многие сочетания клавиш форматирования были «свернуты» в Ctrl+ E. Чтобы прокомментировать выделение, нужно удерживать Ctrl, нажать E, нажать C,затемвыпускать Ctrl.
Если бы я былотправкатакой вклад, я бы написал
SendInput {Ctrl Down}ec{Ctrl Up}
Но как мне сделать эту последовательность горячей клавишей? Я пробовал
{Ctrl Down}EC{Ctrl Up}::
MsgBox, "Hello, world!"
Return
но, конечно, это приводит к синтаксической ошибке:
решение1
Наконец-то разобрался.
вкратце
Заменить ^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
Окно сообщения выше срабатывает на CtrlE. CНо мы ищем CtrlC, поэтому давайте исправим это:
^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
Теперь у нас есть окно сообщения при нажатии CtrlEтогда CtrlC. Но есть проблема с этим: окно сообщения срабатывает даже когда явыпускать Ctrlмежду двумя нажатиями клавиш. Так как же мы обнаруживаем по сути {Ctrl Up}
средний ввод? Вы не можете просто проверить на входе —
^e::
if (!GetKeyState("Ctrl"))
{
Return
}
Input, OutputVar, L1 M
; ...
—также вы не можете просто проверить после ввода—
^e::
Input, OutputVar, L1 M
if (!GetKeyState("Ctrl"))
{
Return
}
; ...
— и вы даже не сможете обойтись без обоих вариантов, потому что в любом случае вы пропустите {Ctrl Up}
блокировку while для ввода данных.
Затем я посмотрел вдокументация по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
Теперь, когда я нажимаю CtrlE, затем отпускаю Ctrlи нажимаю CtrlC, ничего не происходит, как и ожидалось!
Осталось исправить еще одну вещь. При «отмене» («сломанный аккорд») я хотел, чтобы все нажатия клавиш возвращались к норме. Но в коде выше пришлось Input
бы «съесть» нажатие клавиши перед возвратом, независимо от сломленного аккорда или нерелевантного вторичного нажатия клавиши. Добавление случая Else
прекрасно решает эту проблему:
Else
{
SendInput %OutputVar%
}
Итак, вот вам «аккорды» в AutoHotkey. (Хотя я бы не назвал это «аккордом». Скореемелодия, с басовой партией ;-)
@hippibruder великодушно указывает, что я могу избежать определения, $Ctrl::
используя ~
для создания $Ctrl UP::
неблокируемого. Это позволяет немного упростить! (См. раздел tl;dr вверху для получения окончательного результата.)
Еще одно. Если, возможно, при "отмене" ("сломанный аккорд") вы захотите выдать первое нажатие клавиши,то есть CtrlEпросто добавьте его в Else
блок,
Else
{
SendInput ^e
SendInput %OutputVar%
}
и не забудьте изменить горячую клавишу на
$^e::
чтобы избежать бесконечного цикла.
решение2
Я не думаю, что в AHK есть встроенная поддержка аккордов клавиш. Один из способов их обнаружения — зарегистрировать горячую клавишу для первой клавиши в аккорде (^e), а затем использовать Input-Command для обнаружения следующих клавиш.
; Tested with AHK_L U64 v1.1.14.03 (and Visual Studio 2010)
; This doesn't block the input. To block it remove '~' from the hotkey and 'V' from Input-Cmd
~^e::
; Input-Cmd will capture the next keyinput as its printable representation.
; (i.e. 'Shift-a' produces 'A'. 'a' produces 'a'. 'Ctrl-k' produces nothing printable. This can be changed with 'M' option. Maybe better approch; See help)
; Only the next, because of 'L1'. (Quick-Fail; Not necessary)
; To detect 'c' and 'u' with control pressed I used them as EndKeys.
; If a EndKey is pressed the Input-Cmd will end and save the EndKey in 'ErrorLevel'.
Input, _notInUse, V L1 T3, cu
; Return if Input-Cmd was not terminated by an EndKey
; or 'Control' is no longer pressed. (It would be better if Input-Cmd would be also terminated by a {Ctrl Up}. I don't know if that is possible)
if ( InStr(ErrorLevel, "Endkey:") != 1
|| !GetKeyState("Control") )
{
return
}
; Extract the EndKey-Name from 'ErrorLevel' (ErrorLevel == "Endkey:c")
key := SubStr(ErrorLevel, 8)
if ( InStr(key, "c") == 1 )
{
TrayTip,, ^ec
}
else if ( InStr(key, "u") == 1 )
{
TrayTip,, ^eu
}
else
{
MsgBox, wut? key="%key%"
}
return