Generally speaking, a hook is a method of intercepting program events without a dedicated API. You can read more about it here: https://en.wikipedia.org/wiki/Hooking
This library wraps the JNativeHook library, allowing you to intercept global keyboard events and mouse events. That is, your B4J application can now recieve these events even if they occur outside your application or your application is not in focus or has no GUI. In order to use this library, download the JNativeHook-<version>.zip file from this address: https://github.com/kwhat/jnativehook/releases . The B4J library was written for version 2.0.2. Unzip the archive and place the JNativeHook.jar file in your B4J external libraries folder. Then download the jNativeHookB4J.zip file attached to this post and extract the jNativeHookB4J.jar and jNativeHookB4J.xml files to your B4J external libraries folder.
The following code shows an example of its usage:
Note how in the above example, all the NH_ events appear in the Main module. This doesn't mean, however, that they will execute in the Main thread. They will execute in the JNativeHook delegate thread. This is a general advantage however it means that if you want to access UI elements from within your event subs, you will have to use Thread.RunOnGuiThread() to do so. Also note that unregistering the NativeHook will end the NativeHook event loop. If this was the only active event loop in your program (no UI event loop, no server event loop, etc...), ending that event loop will end your program. That is why an _Unregistered event is provided.
Make sure to unregister the NativeHook when your program is done using it. If too many NativeHooks are left registered but unused, this will interfere with your ability to create new instances of NativeHook and for other programs that respond to these system events to do so. If this happens, reboot your computer and it should clear all those dangling NativeHooks from memory. However, if you properly unregister your NativeHooks, you shouldn't have any problems.
My preliminary tests with this library indicate that it performs very well and consumes very little computing resources. On a few years old i7 system, a program that I wrote with this library stayed at around 0.03% CPU load and very rarely spiked to 0.5% even with heavy mouse and keyboard usage and all native listeners running. The B4J library is pretty heavily commented and the comments sort of lead you through its usage. The JNativeHook.jar file that you download from github has packed into it all the native files necessary to work on Windows, Linux and Darwin-based Mac systems. I've only tested it on Windows, however.
EDIT (4JUL2015): jNativeHookB4J.zip was compiled against jdk 8u40. I've attached another .zip called jNativeHookB4JAncient.zip that was compiled against jdk 6u26 which should work for users and customers still using Javas 6 or 7 (I've only tested Ancient on jdk 7u71, though). jNativeHookB4jAncient works in exactly the same way except the NativeHook object is called NativeHookAncient. If you're using Java 5 or below, well, you're on your own...
EDIT (5JUL2015): Updated both libraries to version 1.1 to enable event consumption. See post #18 for details.
This library wraps the JNativeHook library, allowing you to intercept global keyboard events and mouse events. That is, your B4J application can now recieve these events even if they occur outside your application or your application is not in focus or has no GUI. In order to use this library, download the JNativeHook-<version>.zip file from this address: https://github.com/kwhat/jnativehook/releases . The B4J library was written for version 2.0.2. Unzip the archive and place the JNativeHook.jar file in your B4J external libraries folder. Then download the jNativeHookB4J.zip file attached to this post and extract the jNativeHookB4J.jar and jNativeHookB4J.xml files to your B4J external libraries folder.
The following code shows an example of its usage:
B4X:
Sub Process_Globals
Dim NH as NativeHook
Dim t as Timer
End Sub
Sub AppStart(Args() as String)
NH.Initialize("NH", Me) 'Initializes and registers the NativeHook
NH.startNativeKeyListener 'starts a NativeKeyListener
NH.enableKillCode 'Allows you to manually unregister by pressing Windows_Escape
NH.EnableEventConsumption 'Allows you to consume input events
t.Initialize("t", 60*1000)
t.Enabled = True 'Timer will unregister the NativeHook in 1 minute
StartMessageLoop
End Sub
'Event fired whenever a key is pressed, regardless of what application is in focus
Sub NH_NativeKeyPressed(nke as NativeKeyEvent) As Boolean
If NH.isCharacter(nke.keyCode) Then
Log(nke.keyText & " Pressed")
If nke.keyText=="F" Then Return True 'Consumes the event if the user pressed the "F" key
End If
Return False
End Sub
'Event fired when the NativeHook is unregistered
Sub NH_Unregistered
Log("NativeHook unregistered")
StopMessageLoop 'No more event loops means this program ends here
End Sub
Sub t_Tick
t.Enabled = False
NH.unregisterNativeHook
End Sub
Note how in the above example, all the NH_ events appear in the Main module. This doesn't mean, however, that they will execute in the Main thread. They will execute in the JNativeHook delegate thread. This is a general advantage however it means that if you want to access UI elements from within your event subs, you will have to use Thread.RunOnGuiThread() to do so. Also note that unregistering the NativeHook will end the NativeHook event loop. If this was the only active event loop in your program (no UI event loop, no server event loop, etc...), ending that event loop will end your program. That is why an _Unregistered event is provided.
Make sure to unregister the NativeHook when your program is done using it. If too many NativeHooks are left registered but unused, this will interfere with your ability to create new instances of NativeHook and for other programs that respond to these system events to do so. If this happens, reboot your computer and it should clear all those dangling NativeHooks from memory. However, if you properly unregister your NativeHooks, you shouldn't have any problems.
My preliminary tests with this library indicate that it performs very well and consumes very little computing resources. On a few years old i7 system, a program that I wrote with this library stayed at around 0.03% CPU load and very rarely spiked to 0.5% even with heavy mouse and keyboard usage and all native listeners running. The B4J library is pretty heavily commented and the comments sort of lead you through its usage. The JNativeHook.jar file that you download from github has packed into it all the native files necessary to work on Windows, Linux and Darwin-based Mac systems. I've only tested it on Windows, however.
EDIT (4JUL2015): jNativeHookB4J.zip was compiled against jdk 8u40. I've attached another .zip called jNativeHookB4JAncient.zip that was compiled against jdk 6u26 which should work for users and customers still using Javas 6 or 7 (I've only tested Ancient on jdk 7u71, though). jNativeHookB4jAncient works in exactly the same way except the NativeHook object is called NativeHookAncient. If you're using Java 5 or below, well, you're on your own...
EDIT (5JUL2015): Updated both libraries to version 1.1 to enable event consumption. See post #18 for details.
Attachments
Last edited: