InputHook() [v1.1.31+]

Creates an object which can be used to collect or intercept keyboard input.

InputHook := InputHook(Options, EndKeys, MatchList)

매개변수

Options

다른 기호로 구성되는 문자열 (순서에 상관없이, 사이에 선택적으로 스페이스 허용):

B: Sets BackspaceIsUndo to false, which causes Backspace to be ignored.

C: Sets CaseSensitive to true, making MatchList case sensitive.

I: Sets MinSendLevel to 1 or a given value, causing any input with send level below this value to be ignored. For example, I2 would ignore any input with a level of 0 (the default) or 1, but would capture input at level 2.

L: 길이 제한 (예, L5). 최대로 허용되는 입력 길이. When the text reaches this length, the Input is terminated and EndReason is set to the word Max (unless the text matches one of the MatchList phrases, in which case EndReason is set to the word Match). 길이를 지정하지 않으면, 1023 길이로 제한됩니다.

Specifying L0 disables collection of text and the length limit, but does not affect which keys are counted as producing text (see VisibleText). This can be useful in combination with OnChar, OnKeyDown, KeyOpt or EndKeys.

M: Ctrl+A부터 Ctrl+Z까지의 변형 키눌림은 실제 ASCII 문자가그에 상응한다면 인지되고 변환됩니다. 다음 예제를 연구해 보십시오. Ctrl+C를 인지합니다:

CtrlC := Chr(3) ; Ctrl-C에 대한 문자를 CtrlC 변수에 저장합니다.
ih := InputHook("L1 M")
ih.Start()
ih.Wait()
if (ih.Input = CtrlC)
    MsgBox, Control-C를 눌렀습니다.

주의: Ctrl+A부터 Ctrl+Z까지의 문자는 Chr(1)부터 Chr(26)에 상응합니다. 또한, M 옵션 때문에 Ctrl+와 같이 어떤 키보드 단축키는 Input이 진행 중인 동안 잘못된 행위를 할 수 있습니다.

T: Sets Timeout (e.g. T3 or T2.5).

V: Sets VisibleText and VisibleNonText to true. 보통, 사용자의 입력을 막습니다 (시스템으로부터 숨습니다). 이 옵션을 사용하면 사용자의 키눌림을 활성 창에 전달할 수 있습니다.

*: Wildcard. Sets FindAnywhere to true, allowing matches to be found anywhere within what the user types.

E: 키 코드가 아니라 문자 코드로 한-문자 종료 키를 처리합니다. 이렇게 하면 활성 창의 키보드 레이아웃이 스크립트의 키보드 레이아웃과 다를 경우 결과가 더 일관성이 있습니다. 또한 실제로 주어진 종료 문자를 생성하지 않는 키 조합이 입력을 종료하지 못하도록 막습니다; 예를 들어, @가 종료 키이면, (E 옵션이 사용될 경우) US 레이아웃에서 Shift+2는 촉발되지만 Ctrl+Shift+2는 촉발되지 않습니다. C 옵션도 사용된다면, 종료 키는 대소문자를 구분합니다.

EndKeys

A list of zero or more keys, any one of which terminates the Input when pressed (the end key itself is not written to the Input buffer). When an Input is terminated this way, EndReason is set to the word EndKey and the EndKey property is set to the name of the key.

EndKeys 리스트는 Send 명령어와 비슷한 형식을 사용합니다. 예를 들어, {Enter}.{Esc}를 지정하면 Enter, ., 또는 Esc가 입력을 종료시킵니다. 활괄호 자체를 종료 키로 사용하려면, {{} 그리고/또는 {}}을 지정하십시오.

Ctrl, Alt, 또는 Shift를 종료 키로 사용하려면, 그 키의 중립 버전이 아니라, 좌/우 버전을 사용하십시오. 예를 들어, {Control}가 아니라 {LControl}{RControl}로 지정하십시오.

Although modified keys such as Alt+C (!c) are not supported, non-alphanumeric characters such as ?!:@&{} by default require the Shift key to be pressed or not pressed depending on how the character is normally typed. If the E option is present, single character key names are interpreted as characters instead, and in those cases the modifier keys must be in the correct state to produce that character. When the E and M options are both used, Ctrl+A through Ctrl+Z are supported by including the corresponding ASCII control characters in EndKeys.

An explicit key code such as {vkFF} or {sc001} may also be specified. 이것은 키에 이름도 없고 건네질 때 보이는 문자도 생산하지 않는 아주 희귀한 경우에 유용합니다. 그의 가상 키 코드는 다음과 같이 종료할 수 있습니다. 아래 키 리스트 페이지에 있는 단계를 따르십시오.

MatchList

키 문구를 쉼표로-가른 리스트. 이 문구에 부합하면 Input은 종료됩니다 (그 경우 EndReason은 단어 Match가 설정됩니다). 사용자가 타자한 모든 것은 정확하게 이 문구 중 하나에 부합해야 일치가 일어납니다 (단, * 옵션이 있는 경우는 예외입니다). 게다가, 구분 쉼표 둘레에 있는 스페이스나 탭은 의미가 있습니다. 즉, 부합 문자열의 일부가 됩니다. 예를 들어, MatchListABC , XYZ이라면, 사용자가 ABC 뒤에 또는 XYZ 앞에 스페이스를 타자해야 부합이 일어납니다.

연속적인 두 개의 쉼표는 글자 그대로의 쉼표 하나가 결과입니다. 예를 들어, 다음은 문자열의 끝에 문자 그대로의 쉼표 하나를 생산합니다: string1,,,string2. 비슷하게, 다음 목록에는 항목 하나가 들어 있고 그 안에 글자 그대로의 쉼표가 하나 들어 있습니다: single,,item.

MatchList 안의 항목들은 개별적인 매개변수로 취급되지 않기 때문에, 리스트는 변수 안에 완전히 포함될 수 있습니다. 실제로, 그의 길이가 16383 문자를 넘어서면 변수 안에 일부만 포함됩니다. 그 길이가 스크립트 줄의 최대 길이이기 때문입니다. 예를 들어, MatchList%List1%,%List2%,%List3%으로 구성될 수 있습니다 -- 여기에서 각 변수는 부합 문구의 방대한 부-리스트를 담고 있습니다.

Input Stack

Any number of InputHook objects can be created and in progress at any time, but the order in which they are started affects how input is collected.

When each Input is started (by the Start method or Input command), it is pushed onto the top of a stack, and is removed from this stack only when the Input is terminated. Keyboard events are passed to each Input in order of most recently started to least. If an Input suppresses a given keyboard event, it is passed no further down the stack.

Sent keystrokes are ignored if the send level of the keystroke is below the InputHook's MinSendLevel. In such cases, the keystroke may still be processed by an Input lower on the stack.

Multiple InputHooks can be used in combination with MinSendLevel to separately collect both sent keystrokes and real ones.

Calling the Input command terminates any previous Input started by the Input command, but leaves any InputHooks active. If the Input is not visible, any InputHooks which it interrupts will generally not collect any input until the Input command returns.

InputHook Object

The InputHook function returns an InputHook object, which has the following methods and properties.

메쏘드

KeyOpt

Sets options for a key or list of keys.

InputHook.KeyOpt(Keys, KeyOptions)
Keys

A list of keys. Braces are used to enclose key names, virtual key codes or scan codes, similar to the Send command. For example, {Enter}.{{} would apply to Enter, . and {. Specifying a key by name, by {vkNN} or by {scNNN} may produce three different results; see below for details.

Specify the string {All} (case-insensitive) on its own to apply KeyOptions to all VK and all SC. KeyOpt may then be called a second time to remove options from specific keys.

KeyOptions

One or more of the following single-character options (spaces and tabs are ignored).

- (minus): Removes any of the options following the -, up to the next +.

+ (plus): Cancels any previous -, otherwise has no effect.

E: End key. If enabled, pressing the key terminates Input, sets EndReason to the word EndKey and the EndKey property to the key's normalized name. Unlike the EndKeys parameter, the state of the Shift key is ignored. For example, @ and 2 are both equivalent to {vk32} on the US keyboard layout.

I: Ignore text. Any text normally produced by this key is ignored, and the key is treated as a non-text key (see VisibleNonText). Has no effect if the key normally does not produce text.

N: Notify. Causes the OnKeyDown and OnKeyUp callbacks to be called each time the key is pressed.

S: Suppresses (blocks) the key after processing it. This overrides VisibleText or VisibleNonText until -S is used. +S implies -V.

V: Visible. Prevents the key from being suppressed (blocked). This overrides VisibleText or VisibleNonText until -V is used. +V implies -S.

Options can be set by both virtual key code and scan code, and are accumulative.

When a key is specified by name, the options are set either by VK or by SC. Where two physical keys share the same VK but differ by SC (such as Up and NumpadUp), they are handled by SC. By contrast, if a VK number is used, it will apply to any physical key which produces that VK (and this may vary over time as it depends on the active keyboard layout).

Removing an option by VK number does not affect any options that were set by SC, or vice versa. However, when an option is removed by key name and that name is handled by VK, the option is also removed for the corresponding SC (according to the script's keyboard layout). This allows keys to be excluded by name after applying an option to all keys.

If +V is set by VK and +S is set by SC (or vice versa), +V takes precedence.

Start

Starts collecting input.

InputHook.Start()

Has no effect if the Input is already in progress.

The newly started Input is placed on the top of the InputHook stack, which allows it to override any previously started Input.

This method installs the keyboard hook (if it was not already).

Stop

Terminates the Input and sets EndReason to the word Stopped.

InputHook.Stop()

Has no effect if the Input is not in progress.

Wait

Waits until the Input is terminated (InProgress is false).

InputHook.Wait(MaxTime)
MaxTime

The maximum number of seconds to wait. If Input is still in progress after MaxTime seconds, the method returns and does not terminate Input.

Returns EndReason.

General Properties

EndKey

Returns the name of the end key which was pressed to terminate the Input.

KeyName := InputHook.EndKey

Note that EndKey returns the "normalized" name of the key regardless of how it was written in EndKeys. 예를 들어, {Esc} 그리고 {vk1B}는 모두 Escape를 생산합니다. GetKeyName()를 사용하면 정규화된 이름을 열람할 수 있습니다.

If the E option was used, EndKey returns the actual character which was typed (if applicable). 그렇지 않으면, 키 이름은 스크립트의 활성 키보드 레이아웃에 따라 결정됩니다.

EndKey returns an empty string if EndReason is not "EndKey".

EndMods

Returns a string of the modifiers which were logically down when Input was terminated.

Mods := InputHook.EndMods

If all modifiers were logically down (pressed), the full string is:

<^>^<!>!<+>+<#>#

These modifiers have the same meaning as with hotkeys. Each modifier is always qualified with < (left) or > (right). The corresponding key names are: LCtrl, RCtrl, LAlt, RAlt, LShift, RShift, LWin, RWin.

InStr() can be used to check whether a given modifier (such as >! or ^) is present. The following line can be used to convert Mods to a string of neutral modifiers, such as ^!+#:

Mods := RegExReplace(Mods, "[<>](.)(?:>\1)?", "$1")

Due to split-second timing, this property may be more reliable than GetKeyState() even if it is used immediately after Input terminates, or in the OnEnd callback.

EndReason

Returns an EndReason string indicating how Input was terminated.

Reason := InputHook.EndReason

Returns an empty string if the Input is still in progress.

InProgress

Returns true if the Input is in progress and false otherwise.

Boolean := InputHook.InProgress

Input

Returns any text collected since the last time Input was started.

String := InputHook.Input

This property can be used while the Input is in progress, or after it has ended.

Match

Returns the MatchList item which caused the Input to terminate.

String := InputHook.Match

Returns the matched item with its original case, which may differ from what the user typed if the C option was omitted. Returns an empty string if EndReason is not "Match".

OnEnd

Retrieves or sets the function object which is called when Input is terminated.

MyFunc := InputHook.OnEnd
InputHook.OnEnd := MyFunc

Type: function object or empty string. Default: empty string.

The function is passed one parameter: a reference to the InputHook object.

The function is called as a new thread, so starts off fresh with the default values for settings such as SendMode and DetectHiddenWindows.

OnChar

Retrieves or sets the function object which is called after a character is added to the input buffer.

MyFunc := InputHook.OnChar
InputHook.OnChar := MyFunc

Type: function object or empty string. Default: empty string.

The function is passed the following parameters: InputHook, Char. Char is a string containing the character or characters.

The presence of multiple characters indicates that a dead key was used prior to the last keypress, but the two keys could not be transliterated to a single character. For example, on some keyboard layouts `e produces è while `z produces `z.

The function is never called when an end key is pressed.

OnKeyDown

Retrieves or sets the function object which is called when a notification-enabled key is pressed.

MyFunc := InputHook.OnKeyDown
InputHook.OnKeyDown := MyFunc

Type: function object or empty string. Default: empty string.

Key-down notifications must first be enabled by KeyOpt or NotifyNonText.

The function is passed the following parameters: InputHook, VK, SC. VK and SC are integers. To retrieve the key name (if any), use GetKeyName(Format("vk{:x}sc{:x}", VK, SC)).

The function is called as a new thread, so starts off fresh with the default values for settings such as SendMode and DetectHiddenWindows.

The function is never called when an end key is pressed.

OnKeyUp [v1.1.32+]

Retrieves or sets the function object which is called when a notification-enabled key is released.

MyFunc := InputHook.OnKeyUp
InputHook.OnKeyUp := MyFunc

Type: function object or empty string. Default: empty string.

Key-up notifications must first be enabled by KeyOpt or NotifyNonText. Whether a key is considered text or non-text is determined when the key is pressed. If an InputHook detects a key-up without having detected key-down, it is considered non-text.

The function is passed the following parameters: InputHook, VK, SC. VK and SC are integers. To retrieve the key name (if any), use GetKeyName(Format("vk{:x}sc{:x}", VK, SC)).

The function is called as a new thread, so starts off fresh with the default values for settings such as SendMode and DetectHiddenWindows.

Option Properties

BackspaceIsUndo

Controls whether Backspace removes the most recently pressed character from the end of the Input buffer.

Boolean := InputHook.BackspaceIsUndo
InputHook.BackspaceIsUndo := Boolean

Type: Integer (boolean). Default: true. Option B sets the value to false.

When Backspace acts as undo, it is treated as a text entry key. Specifically, whether the key is suppressed depends on VisibleText rather than VisibleNonText.

Backspace is always ignored if pressed in combination with a modifier key such as Ctrl (the logical modifier state is checked rather than the physical state).

Note: If the input text is visible (such as in an editor) and the arrow keys or other means are used to navigate within it, Backspace will still remove the last character rather than the one behind the caret (insertion point).

CaseSensitive

Controls whether MatchList is case sensitive.

Boolean := InputHook.CaseSensitive
InputHook.CaseSensitive := Boolean

Type: Integer (boolean). Default: false. Option C sets the value to true.

FindAnywhere

Controls whether each match can be a substring of the input text.

Boolean := InputHook.FindAnywhere
InputHook.FindAnywhere := Boolean

Type: Integer (boolean). Default: false. Option * sets the value to true.

If true, a match can be found anywhere within what the user types (the match can be a substring of the input text). If false, the entirety of what the user types must match one of the MatchList phrases. In both cases, one of the MatchList phrases must be typed in full.

MinSendLevel

Retrieves or sets the minimum send level of input to collect.

Level := InputHook.MinSendLevel
InputHook.MinSendLevel := Level

Type: Integer. Default: 0. Option I sets the value to 1 (or a given value).

Level는 0부터 101 사이의 정수여야 합니다. Events which have a send level lower than this value are ignored. For example, a value of 101 causes all input generated by SendEvent to be ignored, while a value of 1 only ignores input at the default send level (zero).

SendInput 그리고 SendPlay 방법은 이 설정에 상관 없이 언제나 무시됩니다. Input generated by any source other than AutoHotkey is never ignored as a result of this setting.

NotifyNonText

Controls whether the OnKeyDown and OnKeyUp callbacks are called whenever a non-text key is pressed.

Boolean := InputHook.NotifyNonText
InputHook.NotifyNonText := Boolean

Type: Integer (boolean). Default: false.

Setting this to true enables notifications for all keypresses which do not produce text, such as when pressing Left or Alt+F. Setting this property does not affect a key's options, since the production of text depends on the active window's keyboard layout at the time the key is pressed.

NotifyNonText is applied to key-up events by considering whether a previous key-down with a matching VK code was classified as text or non-text. For example, if NotifyNonText is true, pressing Ctrl+A will produce OnKeyDown and OnKeyUp calls for both Ctrl and A, while pressing A on its own will not call OnKeyDown or OnKeyUp unless KeyOpt has been used to enable notifications for that key.

See VisibleText for details about which keys are counted as producing text.

Timeout

Retrieves or sets the timeout value in seconds.

Seconds := InputHook.Timeout
InputHook.Timeout := Seconds

Type: Float. Default: 0.0 (none). Option T also sets the timeout value.

The timeout period ordinarily starts when Start is called, but will restart if this property is assigned a value while Input is in progress. If Input is still in progress when the timeout period elapses, it is terminated and EndReason is set to the word Timeout.

VisibleNonText

Controls whether keys or key combinations which do not produce text are visible (not blocked).

Boolean := InputHook.VisibleNonText
InputHook.VisibleNonText := Boolean

Type: Integer (boolean). Default: true. Option V sets the value to true.

If true, keys and key combinations which do not produce text may trigger hotkeys or be passed on to the active window. If false, they are blocked.

See VisibleText for details about which keys are counted as producing text.

VisibleText

Controls whether keys or key combinations which produce text are visible (not blocked).

Boolean := InputHook.VisibleText
InputHook.VisibleText := Boolean

Type: Integer (boolean). Default: false. Option V sets the value to true.

If true, keys and key combinations which produce text may trigger hotkeys or be passed on to the active window. If false, they are blocked.

Any keystrokes which cause text to be appended to the Input buffer are counted as producing text, even if they do not normally do so in other applications. For instance, Ctrl+A produces text if the M option is used, and Esc produces the control character Chr(27).

Dead keys are counted as producing text, although they do not typically produce an immediate effect. Pressing a dead key might also cause the following key to produce text (if only the dead key's character).

Backspace is counted as producing text only when it acts as undo.

The standard modifier keys and CapsLock, NumLock and ScrollLock are always visible (not blocked).

EndReason

The EndReason property returns one of the following strings:

String 설명
Stopped The Stop method was called or Start has not yet been called for the first time.
Max Input이 허용된 최대 길이에 도달하였습니다. 그리고 MatchList 안의 항목에 부합하지 못했습니다.
Timeout Input 시간 제한 초과.
Match Input이 MatchList 안의 항목 중 하나에 부합합니다. The Match property contains the matched item.
EndKey

EndKeys 중 하나가 눌렸습니다. Input을 종료합니다. The EndKey property contains the terminating key name or character without braces.

If the Input is in progress, EndReason is blank.

논평

The Start method must be called before input will be collected.

InputHook is designed to allow different parts of the script to monitor input, with minimal conflicts. It can operate continuously, such as to watch for arbitrary words or other patterns. It can also operate temporarily, such as to collect user input or temporarily override specific (or non-specific) keys without interfering with hotkeys.

Keyboard hotkeys are still in effect while an Input is in progress, but cannot activate if any of the required modifier keys are suppressed, or if the hotkey uses the reg method and its suffix key is suppressed. For example, the hotkey ^+a:: might be overridden by InputHook, whereas the hotkey $^+a:: would take priority unless the InputHook suppressed Ctrl or Shift.

Keys are either suppressed (blocked) or not depending on the following factors (in order):

The keyboard hook is required while an Input is in progress, but will be uninstalled automatically if it is no longer needed when the Input is terminated. The presence of the keyboard hook causes the script to become temporarily persistent, meaning that ExitApp may be needed to terminate it.

AutoHotkey does not support Input Method Editors (IME). The keyboard hook intercepts keyboard events and translates them to text by using ToUnicodeEx or ToAsciiEx (except in the case of VK_PACKET events, which encapsulate a single character).

여러 언어나 키보드 레이아웃을 사용한다면, Input은 스크립트가 아니라 활성 창의 키보드 레이아웃을 사용합니다 (Input이 보이는지 여부에 상관이 없습니다).

Although not as flexible, hotstrings are generally easier to use.

InputHook vs. Input

InputHook and the Input command are two different interfaces for the same underlying functionality. The following are mostly equivalent:

Input, OutputVar, %Options%, %EndKeys%, %MatchList%
ih := InputHook(Options, EndKeys, MatchList)
ih.Start()
ErrorLevel := ih.Wait()
if (ErrorLevel = "EndKey")
    ErrorLevel .= ":" ih.EndKey
OutputVar := ih.Input

The Input command terminates any previous Input which it started, whereas InputHook allows more than one Input at a time.

Options is interpreted the same, but the default settings differ:

The Input command blocks the thread while it is in progress, whereas InputHook allows the thread to continue, or even exit (which allows any thread that it interrupted to resume). Instead of waiting, the script can register an OnEnd function to be called when the Input is terminated.

The Input command returns the user's input only after the Input is terminated, whereas InputHook's Input property allows it to be retrieved at any time. The script can register an OnChar function to be called whenever a character is added, instead of continuously checking the Input property.

InputHook gives much more control over individual keys via the KeyOpt method. This includes adding or removing end keys, suppressing or not suppressing specific keys, or ignoring the text produced by specific keys.

Unlike the Input command, InputHook can be used to detect keys which do not produce text, without terminating the Input. This is done by registering an OnKeyDown function and using KeyOpt or NotifyNonText to specify which keys are of interest.

If a MatchList item caused the Input to terminate, the Match property can be consulted to determine exactly which match (this is more useful when the * option is present).

Although the script can consult GetKeyState() after the Input command returns, sometimes it does not accurately reflect which keys were pressed when the Input was terminated. InputHook's EndMods property reflects the logical state of the modifier keys at the time Input was terminated.

There are some differences relating to backward-compatibility:

Input, KeyWait, 핫스트링, InputBox, #InstallKeybdHook, 쓰레드, if var in/contains MatchList

예제

Waits for the user to press any single key.

MsgBox % KeyWaitAny()

; Same again, but don't block the key.
MsgBox % KeyWaitAny("V")

KeyWaitAny(Options:="")
{
    ih := InputHook(Options)
    if !InStr(Options, "V")
        ih.VisibleNonText := false
    ih.KeyOpt("{All}", "E")  ; End
    ih.Start()
    ErrorLevel := ih.Wait()  ; Store EndReason in ErrorLevel
    return ih.EndKey  ; Return the key name
}

Waits for any key in combination with Ctrl/Alt/Shift/Win.

MsgBox % KeyWaitCombo()

KeyWaitCombo(Options:="")
{
    ih := InputHook(Options)
    if !InStr(Options, "V")
        ih.VisibleNonText := false
    ih.KeyOpt("{All}", "E")  ; End
    ; Exclude the modifiers
    ih.KeyOpt("{LCtrl}{RCtrl}{LAlt}{RAlt}{LShift}{RShift}{LWin}{RWin}", "-E")
    ih.Start()
    ErrorLevel := ih.Wait()  ; Store EndReason in ErrorLevel
    return ih.EndMods . ih.EndKey  ; Return a string like <^<+Esc
}

Simple auto-complete: any day of the week. Pun aside, this is a fully functional example. Simply run the script and start typing today, press Tab to complete or press Esc to exit.

global WordList := "Monday`nTuesday`nWednesday`nThursday`nFriday`nSaturday`nSunday"

global Suffix := "", SacHook

SacHook := InputHook("V", "{Esc}")
SacHook.OnChar := Func("SacChar")
SacHook.OnKeyDown := Func("SacKeyDown")
SacHook.OnEnd := Func("SacEnd")
SacHook.KeyOpt("{Backspace}", "N")
SacHook.Start()

SacChar(ih, char)  ; Called when a character is added to SacHook.Input.
{
    Suffix := ""
    if RegExMatch(ih.Input, "`nm)\w+$", prefix)
        RegExMatch(WordList, "`nmi)^" prefix "\K.*", Suffix)
    
    ToolTip % Suffix, % A_CaretX + 15, % A_CaretY    
    
    ; Intercept Tab only while we're showing a tooltip.
    ih.KeyOpt("{Tab}", Suffix = "" ? "-NS" : "+NS")
}

SacKeyDown(ih, vk, sc)
{
    if (vk = 8) ; Backspace
        SacChar(ih, "")
    else if (vk = 9) ; Tab
        Send % "{Text}" Suffix
}

SacEnd()
{
    ExitApp
}