Ctrl을 누른 상태에서 일련의 입력에 대한 단축키(예: {Ctrl Down}ec{Ctrl Up})를 어떻게 생성합니까?

Ctrl을 누른 상태에서 일련의 입력에 대한 단축키(예: {Ctrl Down}ec{Ctrl Up})를 어떻게 생성합니까?

예를 들어 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

마침내 알아 냈습니다.

tl;dr

^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이것을 대신 에 적용하려면 s를 바꾸고 를 제거한 다음 대신에 와 같은 간단한 비교를 수행 Ctrl해야 합니다 . 이것을 and 로 확장하는 방법을 모르지만 비슷한 것을 시도해야 할 수도 있습니다 .CtrlMOutputVar = CAsc(OutputVar) = 3AltWinL2

설명

Input시작하기에 분명한 장소처럼 보였습니다. InputAHK에게 사용자 입력을 기다리라고 요청합니다.예를 들어

^e::
    Input, OutputVar, L1        ; "L1" means wait for 1 keystroke then continue.
    If (OutputVar = "c")
    {
        MsgBox, "Hello, World!"
    }
    Return

위의 메시지 상자는 CtrlEthen 에서 트리거됩니다 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이제 then 을 누르면 메시지 상자가 나타납니다 CtrlC. 하지만 여기에는 문제가 있습니다. 메시지 상자가 실행되는 경우에도풀어 주다 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을 재정 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는 non-blocking을 사용 $Ctrl::하여 정의를 피할 수 있다는 점을 아낌없이 지적합니다 . 이것은 약간의 단순화를 허용합니다! (최종 결과는 상단의 설명 섹션을 참조하세요.)~$Ctrl UP::


하나 더. 혹시 "취소"("깨진 코드") 시 첫 번째 키 입력을 실행하려는 경우, CtrlE그 자체로 블록에 추가하기만 하면 됩니다 Else.

    Else
    {
        SendInput ^e
        SendInput %OutputVar%
    }

단축키를 다음으로 변경하는 것을 잊지 마세요.

$^e::

무한 루프를 피하기 위해.

답변2

AHK에는 기본 코드 지원 기능이 없다고 생각합니다. 이를 감지하는 한 가지 방법은 코드(^e)의 첫 번째 키에 대한 단축키를 등록한 후 입력 명령을 사용하여 다음 키를 감지하는 것입니다.

; 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

관련 정보