例如,在 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
andWin
但你可能必須嘗試L2
或類似的東西。
解釋
Input
似乎是一個明顯的起點。Input
要求 AHK 等待用戶輸入,例如
^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 慷慨地指出,我可以$Ctrl::
透過使用來避免~
定義$Ctrl UP::
非阻塞。這可以進行一些簡化! (有關最終結果,請參閱頂部的 tl;dr 部分。)
還有一件事。如果,也許,在「取消」(「斷弦」)時,您想發出第一次擊鍵,IE 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