Por exemplo, no Visual Studio Express 2013, muitos dos atalhos de formatação foram "dobrados" em Ctrl+ E. Para comentar uma seleção, basta segurar Ctrl, bater E, bater C,entãoliberar Ctrl.
Se eu fosseenviandotal entrada, eu escreveria
SendInput {Ctrl Down}ec{Ctrl Up}
Mas como faço para transformar essa sequência em uma tecla de atalho? tentei
{Ctrl Down}EC{Ctrl Up}::
MsgBox, "Hello, world!"
Return
mas é claro que isso causa um erro de sintaxe:
Responder1
Finalmente descobri.
dr.
Substitua ^e
pela primeira tecla desejada. Substitua 3
pelo índice ASCII do segundo pressionamento de tecla desejado. Isso impõe que Ctrlseja mantido pressionado por ambas as teclas, caso contrário, cancela.
~$Ctrl UP::
ChordIsBroken := True
Return
^e::
ChordIsBroken := False
Input, OutputVar, L1 M
If (!ChordIsBroken && Asc(OutputVar) = 3)
{
MsgBox "Hello, World!"
}
Else
{
SendInput %OutputVar%
}
Return
Para adaptar isso Shiftem vez de Ctrl, você teria que substituir o Ctrl
s, remover o M
e fazer uma comparação mais simples, como OutputVar = C
em vez do Asc(OutputVar) = 3
. Não tenho certeza de como estender isso Alt
, mas Win
talvez você precise tentar L2
algo do tipo.
Explicação
Input
parecia um lugar óbvio para começar. Input
pede ao AHK para aguardar a entrada do usuário,por exemplo
^e::
Input, OutputVar, L1 ; "L1" means wait for 1 keystroke then continue.
If (OutputVar = "c")
{
MsgBox, "Hello, World!"
}
Return
A caixa de mensagem acima é acionada CtrlEentão C. Mas estamos procurando CtrlC, então vamos consertar isso:
^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
Agora temos uma caixa de mensagem ao pressionar CtrlEthen CtrlC. Mas há um problema com isso: a caixa de mensagem é acionada mesmo quando euliberar Ctrlentre as duas teclas. Então, como detectamos essencialmente uma {Ctrl Up}
entrada intermediária? Você não pode simplesmente verificar a entrada—
^e::
if (!GetKeyState("Ctrl"))
{
Return
}
Input, OutputVar, L1 M
; ...
—nem você pode simplesmente verificar após inserir—
^e::
Input, OutputVar, L1 M
if (!GetKeyState("Ctrl"))
{
Return
}
; ...
- nem você consegue fazer as duas coisas, porque não importa o que aconteça, você perderá o {Ctrl Up}
bloqueio para entrada.
Então eu olhei paradocumentação sobreHotkey
para inspiração. O operador de combinação personalizado, &
parecia promissor. Mas infelizmente,
^e & ^c::
; ...
causou um erro de compilação; aparentemente &
é para combinarnão modificadoapenas teclas digitadas.
Finalmente, chegou a hora UP
, e foi aí que finalmente fiz a descoberta. Eu redefini Ctrlpara UP
definir umalternarisso impediria o acionamento da caixa de mensagem!
$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
Agora, quando pressiono CtrlE, depois solto Ctrle pressiono CtrlC, nada acontece, como esperado!
Havia uma última coisa a consertar. No “cancelamento” (um “acorde quebrado”), eu queria que todas as teclas digitadas voltassem ao normal. Mas no código acima, Input
seria necessário "comer" uma tecla antes de retornar, independentemente de um acorde quebrado ou uma tecla secundária irrelevante. Adicionar um Else
caso resolve isso muito bem:
Else
{
SendInput %OutputVar%
}
Então, aí está - "acordes" no AutoHotkey. (Embora eu não chamaria isso exatamente de "acorde". Mais como ummelodia, com uma linha de baixo ;-)
@hippibruder ressalta generosamente que posso evitar a definição $Ctrl::
usando ~
para tornar $Ctrl UP::
o não bloqueio. Isso permite alguma simplificação! (Veja a seção tl;dr na parte superior para ver o resultado final.)
Mais uma coisa. Se, por acaso, após o "cancelamento" (um "acorde quebrado"), você quiser pressionar a primeira tecla,ou seja CtrlEpor si só, basta adicionar isso no Else
bloco,
Else
{
SendInput ^e
SendInput %OutputVar%
}
e não se esqueça de mudar a tecla de atalho para
$^e::
para evitar um loop infinito.
Responder2
Não acho que haja suporte integrado para acordes principais no AHK. Uma maneira de detectá-los seria registrar uma tecla de atalho para a primeira tonalidade do acorde (^e) e então usar o Input-Command para detectar as próximas tonalidades.
; 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