InputHook does not recognize Numpad keys Topic is solved

Get help with using AutoHotkey (v2 or newer) and its commands and hotkeys
bapl
Posts: 119
Joined: 17 Apr 2021, 00:24

InputHook does not recognize Numpad keys

13 Nov 2022, 12:58

Hello.
I need to create the ability to catch hotkeys in order to add them to the settings.
I found 'InputHook': https://lexikos.github.io/v2/docs/commands/InputHook.htm

However, when pressing Numpad1-Numpad9, I get numbers from 1 to 9. So how do I get Numpad1, Numpad2?
lexikos
Posts: 9664
Joined: 30 Sep 2013, 04:07
Contact:

Re: InputHook does not recognize Numpad keys

13 Nov 2022, 20:12

Code?

KeyWaitAny() from the documentation returns "Numpad1" when I press Numpad1. If you ask for text input, obviously you will get text input, not key names.
bapl
Posts: 119
Joined: 17 Apr 2021, 00:24

Re: InputHook does not recognize Numpad keys

14 Nov 2022, 01:48

@lexikos

Code: Select all

ihSingleKey := InputHook("L1 m"), ihSingleKey.Start(), ihSingleKey.Wait(), SingleKey := ihSingleKey.Input
name := GetKeyName(SingleKey)
vk   := GetKeyVK(SingleKey)
sc   := GetKeySC(SingleKey)
MsgBox(Format("Name:`t{}`nVK:`t{:X}`nSC:`t{:X}", name, vk, sc))
ExitApp()
lexikos
Posts: 9664
Joined: 30 Sep 2013, 04:07
Contact:

Re: InputHook does not recognize Numpad keys

14 Nov 2022, 01:57

As I guessed, you asked for text input, so you got text input. Keys can be identified via EndKey or OnKeyDown, as per the documentation.
bapl
Posts: 119
Joined: 17 Apr 2021, 00:24

Re: InputHook does not recognize Numpad keys

14 Nov 2022, 04:50

@lexikos
Am I doing the right thing if I write the identification code in this way (I write for the GUI):

Code: Select all

global OldKey := 'F2'
HotkeyRegister(A_GuiEvent, GuiCtrlObj, Info, *) {
     x := 0
     global OldKey
     Status.Opt("BackGroundc666666")
     Status.Value := "Press key.."
     Key := A_PriorKey
     while x = 0
          {
               if A_PriorKey != Key
                    x := 1
               Sleep 10
          }
     Status.Opt("BackGroundc666666")
     Status.Value := "Hotkey: " A_PriorKey
     if OldKey
Hotkey OldKey, MyFunc, 'off'
OldKey := A_PriorKey
Hotkey A_PriorKey, MyFunc
return
}
And why does the script refuse to work if I do not set global Oldkey at the beginning of the line? In the first version, this was allowed, in the second, I get a bunch of warnings that OldKey is empty:

Code: Select all

Error: This variable has not been assigned a value.

Specifically: global OldKey

	156: Status.Opt("BackGroundc666666")
	157: Status.Value := "Горячая клавиша: " A_PriorKey
▶	158: If OldKey
	159: Hotkey(OldKey, MyFunc, 'off')
	160: OldKey := A_PriorKey
lexikos
Posts: 9664
Joined: 30 Sep 2013, 04:07
Contact:

Re: InputHook does not recognize Numpad keys

14 Nov 2022, 05:11

How do you judge the code to be right or wrong? Does it work? I wouldn't write it that way, polling a variable which relies on KeyHistory. Further to that, you read the value of A_PriorKey multiple times after the loop, and at any of those times it could have a different value if a keyboard event comes through at the wrong moment.

There is an example in the documentation for waiting for the user to enter any single key. I already pointed it out in my first post in this topic.
And why does the script refuse to work if I do not set global Oldkey at the beginning of the line? In the first version, this was allowed, in the second, I get a bunch of warnings that OldKey is empty:

I think you are under some misconceptions. In the first version, the variable has a value when it is read for the first time. In the second version, it does not have a value. That is an error. You do not get any warnings; only an error, clearly stating the problem.
bapl
Posts: 119
Joined: 17 Apr 2021, 00:24

Re: InputHook does not recognize Numpad keys

14 Nov 2022, 09:12

@lexikos

Is this a good example?:

Code: Select all

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()
    ih.Wait()
    return ih.EndKey  ; Return the key name
}
It came out something like this:

Code: Select all

HotkeyRegister(A_GuiEvent, GuiCtrlObj, Info, *) {
     Options:=""
     global OldKey
     Status.Opt("BackGroundc666666")
     Status.Value := "Press key.."
     ih := InputHook(Options)
     if !InStr(Options, "V")
         ih.VisibleNonText := false
     ih.KeyOpt("{All}", "E")  ; End
     ih.Start()
     ih.Wait()
     Status.Opt("BackGroundc666666")
     Status.Value := "Hotkey: " ih.EndKey
     if OldKey
Hotkey OldKey, MyFunc, 'off'
OldKey := ih.EndKey
Hotkey ih.EndKey, MyFunc, 'on'
return
}
And another interesting question.

When I call the function like this:

Code: Select all

B := MyFunc(1)
MsgBox B


MyFunc(A) {
    A := A+2
    return A
}
I can get the value into variable B.

But when I use OnEvent like:

Code: Select all

Status := Setting.Add("Text", "xm w" Width2 " r2 Background494949 +Center 0x200  vEndKey", "Press: ")
Status.OnEvent("Click", HotkeyRegister.Bind("Normal"))
HotkeyRegister(GuiCtrlObj, *) {
    A := 1
    return A
}
Where will the return take place? It's just that when I execute this method and access the second OnEvent, I get an empty string.
Here is an example:

Code: Select all

A := 0
Setting:= Gui()
Width2 := 310
Setting.Opt("+LastFound -DPIScale")
WinSetTransparent(220)
Setting.BackColor := "c242424"
Setting.MarginX := "0", Setting.MarginY := "0"
Setting.SetFont("s11 cffffff Bold")
Setting.Add("Text", "section w" Width2 " r2 Background0f0f0f Center 0x200 +Center", "Gui")
Setting.SetFont("s8")
Status := Setting.Add("Text", "xm w" Width2 " r2 Background494949 +Center 0x200", "A+1")
Status.OnEvent("Click", HotkeyRegister.Bind('Normal'))
Status2 := Setting.Add("Text", "xm w" Width2 " r2 Background494949 +Center 0x200", "Msgbox")
Status2.OnEvent("Click", MsgEndKey.Bind('Normal'))
Setting.Add("Text", "xm w" Width2 " h0 +Center BackgroundTrans").GetPos(&PX, &PY, &PW, &PH)
H := PY + PH
Setting.Opt("-Caption")
WinSetRegion("0-0 w" Width2 " h" H " r6-6")
Setting.Show("w" Width2 " x" (A_ScreenWidth - Width2) " y150")
return

HotkeyRegister(GuiCtrlObj, *) {
    A := 1
    return A
}

MsgEndKey(GuiCtrlObj, *) {
Msgbox A
}
Sorry for so many questions. I just want to understand it all, because every time I have huge problems because of not understanding how it works.
lexikos
Posts: 9664
Joined: 30 Sep 2013, 04:07
Contact:

Re: InputHook does not recognize Numpad keys

16 Nov 2022, 02:07

I think you need to brush up on fundamental concepts like calling functions, returning values, and variable scope.

You can't just return a value and expect it to make its way back to some other part of your code, when that code isn't calling the function. The return value goes back to whatever called the function. Its meaning depends on however that code interprets the return value.
Callback Return Value
If multiple callbacks have been registered for an event, a callback may return a non-empty value to prevent any remaining callbacks from being called.
The return value may have additional meaning for specific events. For example, a Close callback may return a non-zero number (such as true) to prevent the GUI window from closing.
Source: OnEvent (GUI) - Syntax & Usage | AutoHotkey v2
The reason you get an empty string has nothing to do with the return. There is no connection between return A and the value that A will have in the other function.

A := 1 has not been declared global. It is local to HotkeyRegister. You don't have this problem with OldKey, because you declared global OldKey.
bapl
Posts: 119
Joined: 17 Apr 2021, 00:24

Re: InputHook does not recognize Numpad keys

16 Nov 2022, 02:40

@lexikos
Do I really have to declare a variable inside functions as global every time, or just write "global"?
I don't really understand many things without examples, because I don't speak English well, so I learn through examples, for the most part.
That's why it's so hard for me to understand some documentation when there are no obvious examples.

Sorry if this is too rough, but it would be nice if you could show any example where I get the return value via '.OnEvent("Click", HotkeyRegister.Bind("Normal"))' without using 'global'.
Sorry again for being so stupid. :(

I use google translator to communicate with you. I apologize in advance if I made a mistake somewhere in the wording of the sentence.

I would like, without 'extra' code, to accept a callback from where it came from and take information from there, so as not to write 'global' inside each function in the future
lexikos
Posts: 9664
Joined: 30 Sep 2013, 04:07
Contact:

Re: InputHook does not recognize Numpad keys  Topic is solved

16 Nov 2022, 03:17

Are you asking whether assume-global actually does what it purports to do? Obviously you can use it.

You shouldn't use it for a single variable. You are unnecessarily increasing the risk of errors to save only a small amount of typing.

You have created a GUI to enter a hotkey. Both event callback functions receive a reference to the GUI control. There is no need to create additional global variables, because you can put whatever you want into the GuiControl or Gui object by just assigning a property.

Code: Select all

Example() {
    g := Gui()
    g.N := 0
    g.AddButton(, "N++").OnEvent("Click", IncrementN)
    g.AddButton(, "Show N").OnEvent("Click", ShowN)
    g.Show()
}
IncrementN(Btn, *) {
    Btn.Gui.N++
}
ShowN(Btn, *) {
    MsgBox Btn.Gui.N
}
Example
There is no need to even do that, because v2 has nested functions and closures. Nested functions do not require declarations to assign to outer local variables.

Code: Select all

Example() {
    ; Each time Example() is called, it creates a new Gui and gets a new N.
    g := Gui()
    N := 0
    IncrementN(Btn, *) {
        N++
    }
    ShowN(Btn, *) {
        MsgBox N
    }
    g.AddButton(, "N++").OnEvent("Click", IncrementN)
    g.AddButton(, "Show N").OnEvent("Click", ShowN)
    g.Show()
}
Example
You are also binding a parameter to each function. You can bind whatever you want to the function, including an object into which you can store properties...

Code: Select all

Example() {
    g := Gui()
    State := {N: 0}
    g.AddButton(, "N++").OnEvent("Click", IncrementN.Bind(State))
    g.AddButton(, "Show N").OnEvent("Click", ShowN.Bind(State))
    g.Show()
}
IncrementN(State, Btn, *) {
    State.N++
}
ShowN(State, Btn, *) {
    MsgBox State.N
}
Example
...or even just a variable reference.

Code: Select all

Example() {
    ; Each time Example() is called, it creates a new Gui and gets a new N.
    g := Gui()
    N := 0
    g.AddButton(, "N++").OnEvent("Click", IncrementN.Bind(&N))
    g.AddButton(, "Show N").OnEvent("Click", ShowN.Bind(&N))
    g.Show()
}
IncrementN(&N, Btn, *) {
    N++
}
ShowN(&N, Btn, *) {
    MsgBox N
}
Example
bapl
Posts: 119
Joined: 17 Apr 2021, 00:24

Re: InputHook does not recognize Numpad keys

16 Nov 2022, 03:29

@lexikos
This is quite the best answer for me. After that, my questions immediately disappear. Thank you for such a detailed answer and your time!

Return to “Ask for Help (v2)”

Who is online

Users browsing this forum: Google [Bot], teadrinker and 29 guests