Async Key Events are classes for REALbasic that allow you to read the keyboard state asynchronously using keyname constants rather than raw key codes, automatically handle different keyboard layouts, and generate raw key-down and key-up events.
Async Key Events (formerly AsyncKeyHelper) is a small set of classes that allow you to read the keyboard state asynchronously using keyname constants rather than raw key codes to automatically handle different keyboard layouts. The classes can also generate raw (and global) key-down and key-up events that map to physical keys as opposed to printable characters.
Generating raw key events requires that you constantly poll the keyboard (with a timer, thread, or manually from a loop). Therefore, these classes are best suited for Games or other real-time applications that are constantly processing frames.
Drag the "Async Key Events" folder into the Rb project items list to add all the required classes to your project.
You need to create an instance of the AKeyEventGenerator class in order to accomplish anything with these classes. The easiest way to do this is to place a AKeyEventGenerator instance on your main window* and add code to the KeyDown and KeyUp events as needed. Alternately, you can add a new class to the project, set its super to AKeyEventGenerator, and then add code to the KeyDown and KeyUp events. Create an instance of this subclass in code in order to generate events or use the utility methods (this approach is handy for windowless apps). In either case, using only one instance at a time is recommended, however you can destroy and recreate this instance if the keyboard layout changes after its initial creation.
Regardless of how the AKeyEventGenerator instance is created, you must call the Update method as frequently as possible to generate KeyDown and KeyUp events. In a typically game this would be done once per frame, or perhaps at a fixed rate either from the main game loop, or in a separate thread or timer. The slower the updates are applied, the less responsive the keyboard will feel, but it's not necessary to go overboard; 20-60 updates per second is plenty for most applications.
*In REALbasic 5.5, drag the AKeyEventGenerator class from the the project items window into your window editor. In REALbasic 2005, select "Project Controls" in the window editor pane and add an "Object" instance to the window, then set that object's super to AKeyEventGenerator.
AsyncKeyDown(keyconst As Integer) As Boolean
This works like the built-in Keyboard.AsyncKeyDown method but accepts an AKeyNames module constant which is translated for the current keyboard layout rather than using a key code that represents a physical key position. E.g. AKeyEventGenerator.AsyncKeyDown(AKeyNames.kA) will return the state of the "A" key regardless of the current keyboard layout.
GetVirtualKey(keyconst As Integer) As AKeyVirtualKey
Returns an AKeyVirtualKey object given one of the predefined key constants. Returns Nil if the virtual key does not map to a key present on the current keyboard layout, or unsupported keys (please see the "Limitations and Tips" section for more information on supported keyboard layouts).
Updates the state of all key mappings and fires events when appropriate.
KeyDown(Key As AKeyVirtualKey)
Activated when a key has been pressed. (NOTE: This event only fires when Update is called)
KeyUp(Key As AKeyVirtualKey)
Activated when a previously pressed key has been released. (NOTE: This event only fires when Update is called)
This class should not be created directly, but is returned by AKeyEventGenerator under various conditions, such as during KeyDown and KeyUp events, or with the GetVirtualKey method.
Code As Integer (read only)
The keycode mapping for the key.
Name As String (read only)
A plain-text label for the key.
This module simply contains a list of key name constants that can be passed to AKeyEventGenerator methods. E.g. To test if the "A" key is down regardless of the current keyboard layout, call AKeyEventGenerator.AsyncKeyDown(AKeyNames.kA). Note that these are internal array look-up indexes and their actual values are of little interest as they have no correlation to hardware key codes.
Limitations and Tips:
Mappings are only generated for characters present in the AKeyNames module, and at this time that means US/Roman keys only. International keyboard layouts will still work, but non-roman characters or characters normally shifted on US keyboards will not be detected. Adding support for specific international keys is not difficult, but requires some forethought. Future updates will likely handle things more gracefully.
International keys aside, the key names and key-constant names may not match up 100% on all platforms, hardware, or keyboard layouts. For example, I opted for "Mac" names such as PAD_CLEAR rather than NUMLOCK, and F13 instead of PRINTSCREEN. At first thought you may think using different constants/names depending on the platform is a good idea, but that can break preferences across platforms. A better solution is to maintain multiple mappings for a single key code, this way you can use either constant/keyname in your app (perhaps switching between them, depending on platform or keyboard layout) but configuration files will work with either key name and remain fully cross platform. A future update may include such "aliased" virtual key mappings by default, and provide a better interface to manage these mappings.
Most keyboards only track 5-7 key presses simultaneously (or less - depends on the keyboard, and depends on the which keys are pressed). This is rarely a problem in a practical application but it's worth knowing.
This project is useful as-is but the included Key class can (should!) be extended to be more useful. You can add a "Command As String" property for example, and allow a user to bind certain keys to certain commands which are looked up and queued for execution when a key is pressed and/or released.
· REALbasic 5.5+
What's New in This Release:
· Major refactoring: Raw key events are now pushed to a class instance for better modularity.
· Added a workaround for an RB framework bug on Mac OS X when using certain keyboard layouts (like Canadian eh!)