XML: Key Traps
A Key Trap is gauge code that ‘listens’ for a specific keyboard entry to be made. Its purpose is to allow custom XML script to be executed when the user types that specific key. By nature, it’s conditional: if the keystroke is made, then disregard whatever that key is currently assigned to do, if anything, and then process the key trap script.
In XML, the trap is defined using an <On Key> block placed within a <Keys> section:
1 <Keys> 2 <On Key="Alphanumeric"> 3 <Visible>(L:KeyTrapEnabled, bool) 1 ==</Visible> 4 (M:Key) chr (>C:fs9gps:NameSearchEnterChar) 5 </On> 6 </Keys>
Here, the key trap definition is any alphanumeric character (line 2) and the key trap script (line 3 and line 4) passes the character that was typed to a gps variable provided, however, that L:KeyTrapEnabled = 1.
<Visible>: <Visible> expressions are frequently added to key traps so the user can control when the trap is functional, which is especially important when broad key definitions “ascii” or “alphanumeric” are used. In the example above, whenever the user has not set L:KeyTrapEnabled to 1, the key trap is not functional. That way, the typical (i.e., default) key assignment of “G” will still toggle the landing gear rather than being trapped and the character “G” sent to the gps variable.
<On Key> blocks are nested within <Keys> sections and therefore should be placed at the bottom of the gauge script in order to catch all keystrokes and events triggered during each gauge update cycle.
DEFINING THE TRAP KEY
Format of the trap key definition is flexible.
- It can be broadly specified using “ascii” or “alphanumeric” expressions, or
- individually specified using the decimal or hex ascii code value of a key, or
- specified using the individual character itself (includes Backspace, Tab, Enter, Esc, Space, A thru Z, and F1 thru F12. See tables).
<On Key=”ascii”> traps any of the following characters: ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890 and space, minus, plus, comma, period <On Key=”alphanumeric”> traps any of the following characters: ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890 and space <On Key=”87”> traps the letter “W”. 87 is the decimal value of the ascii code for character “W” <On Key=”0x57”> traps the letter “W”. 0x57 is the hex value of the ascii code for character “W” <On Key=”W”> traps the letter “W”
Hex and decimal values are always interchangeable in the trap definition - it can accept either number format.
Ctrl and Shift Combination: Ctrl and/or Shift can be combined with most keys and trapped in an <On Key> block.
The table below shows binary representation of the ascii code for letter W. The ascii decimal value of W is 87, hex equivalent is 0x57, and binary is 1 0 1 0 1 1 1.
To add Shift, place 1 in Bit 8. For Ctrl, add 1 in bit 9 . Ctrl+Shift is 1 in both bit 8 and bit 9. The key trap definition can accept the decimal or hex equivalent of the result, but not the binary.
Alt can also be combined with a key to form a trap, but it appears to conflict with the FS Menu system, so I would say it's use is not recommended.
Several formats are acceptable for definition of the key combination.
<On Key=”855”> traps the key combination Ctrl + Shift + W <On Key=”0x357”> traps the key combination Ctrl + Shift + W, and <On Key=”Ctrl+Shift+W”> also traps the key combination Ctrl + Shift + W and may be the easiest format to remember (includes Backspace, Tab, Enter, Esc, Space, A thru Z, and F1 thru F12. See tables).
When the <On Key> definition includes Shift and/or Ctrl, (M:Key) will return only the root character code.
<Keys> <On Key="599"> <Visible>(L:KeyTrapEnabled, bool) 1 ==</Visible> (M:Key) (>L:CtrlW_Value, enum) </On> </Keys>
In the Ctrl+W trap example above, (L:CtrlW_Value, enum), and hence, (M:Key), returns 87, which is the decimal value of the ascii code for W, not 599 which is the decimal value for Ctrl + W used in the trap definition.
The tables at the bottom of the wiki summarize keystroke trap capability. Blue font with no shading reflects keys and combinations that are trappable. Pink shading indicates that the key, or key combination, is not trappable, and grey represents uncertainty as my keyboards do not have these keys.
Ascii and Alphanumeric: "yes" indicates keys that are trappable using <On Key=”Ascii”> or <On Key=”Alphanumeric”> definitions.
Trap using Name: indicates keys that can be trapped using the character name in the definition, for example <On Key=”Backspace”> or <On Key=”A”>. Ctrl and Shift can be used in combination with these, for example <On Key=”Ctrl+Shift+Enter”>. Includes Backspace, Tab, Enter, Esc, Space, A thru Z, and F1 thru F12, or whatever is the maximum F key number. The tables at the bottom of this wiki show a more complete, though likely not exhaustive, list.
Trap using Ascii Decimal, Ascii Hex: indicates keystrokes that are trappable using decimal or hex values in the definition. For example, the Home key can be trapped using <On Key=”36”> or <On Key=”0x24”> definition.
Trap using Ctrl, Shift and Ctrl+Shift: Ctrl and Shift can be used in combination with most keys. For example, a Ctrl+Capslock trap is defined as <On Key=”532”> or <On Key=”0x214”> (0x214 is the hex equivalent of decimal 532).
Differences in keyboards may alter the trap capability shown in the tables. If a keyboard has a NumPad with stand alone keys (1 isn't paired with END , 2 isn't paired with Down Arrow, etc.) then all the NumPad keys may be trappable.
NEUTRALIZING AN EXISTING KEY ASSIGNMENT
A key trap without a trap script neutralizes an existing key assignment because the trap momentarily disregards the existing assignment and instead, processes the trap script. As an example,
<Keys> <On Key=”Q"/> <On Key=”L"/> </Keys>
disables the default sound and lights keyboard assignment toggles.
Note: Multiple <On Key> and/or <On Event> traps are permissible within a <Keys> block.
KEY TRAP PROCESSING
Keystrokes trapped in the current update cycle are queued and then their trap routines are sequentially processed at the end of the cycle. All simulation variables (A:Vars) affected by the trap routines return updated values on the subsequent cycle.
Key Traps across the Gauge Set: FS processes <On Key> trap routines found in all gauges of the aircraft’s panel (the ‘gauge set’).
So, if Gauge00 contains the following:
<Keys> <On Key=”Ctrl+W"> <Visible>(L:KeyTrapEnabled, bool) 1 ==</Visible> (L:MyVarA,enum) 10 + (>L:MyVarA,enum) </On> </Keys>
and Gauge01 contains:
<Keys> <On Key=”Ctrl+W"> <Visible>(L:KeyTrapEnabled, bool) 1 ==</Visible> (L:MyVarA,enum) 20 + (>L:MyVarA,enum) </On> </Keys>
Then, on the update cycle following entry of Ctrl+W, (L:MyVarA, enum) will return 30.
VISIBLE WINDOW REQUIREMENT
Key traps have the same visibility requirements as Event traps. One condition is that gauges must be in a visible window for their trap routines to be processed. If a gauge is part of a window whose visibility is set to visibility=0, then no <On Key> routines in that gauge will be run until visibility of the window is set to 1, or if the window is visible on the screen.
Another important condition is that key trap routines in XML gauges are disabled when the user is in External view. This is a problem for those who like to manage systems (i.e. the autopilot) via keystrokes while flying in External view.
Note: A recently released FSX module (XMLTools v.1.0, June 2014, from Tom Aguilo) will handle FSX event traps in any view mode, thus overcoming the visible and external window limitations of stock FSX. XMLTools can be freely downloaded from the FSDeveloper Resources site. Check that site or FSDeveloper Gauges Forum for XMLTools update notices.
M:Key is a parameter that returns the decimal ascii code value of a keystroke.
In the following key trap,
<Keys> <On Key="Alphanumeric"> <Visible>(L:KeyTrapEnabled, bool) 1 ==</Visible> (M:Key) (>L:MKeyValue, enum) </On> </Keys>
if the letter “X” is typed, (L:MKeyValue, enum) is 88. Whenever Ctrl and/or Shift are used in combination with a key, M:Key returns the ascii decimal value for the key.
In certain situations, the user may want to concatenate and store multi-character ascii keystroke entries, for example, gps data entry when the user prefers to type the input rather than use the mouse to rotate knob images. Without use of an external module such as XMLVars, FS cannot easily store string values in XML environment. FS is mostly limited to storing the decimal ascii code equivalent of individual letters into individual L:Vars. This has traditionally been accomplished through the use of a shift register inside a key trap.
The example below accommodates typing of up to 5 keystrokes, storing the ascii code value of each typed character into a separate L:Var, subsequently retrieving the L:Vars, converting the ascii code back to characters, concatenating the characters, then ultimately storing the string into FlightPlanNewWaypointIdent.
1 <Keys> 2 <On Key="Alphanumeric"> 3 <Visible>(L:KeyEntry, enum) 39 ==</Visible> 4 (L:Num394,enum) (>L:Num395,enum) 5 (L:Num393,enum) (>L:Num394,enum) 6 (L:Num392,enum) (>L:Num393,enum) 7 (L:Num391,enum) (>L:Num392,enum) 8 (M:Key) (>L:Num391,enum) 9 (L:Num395,enum) chr 10 (L:Num394,enum) chr scat 11 (L:Num393,enum) chr scat 12 (L:Num392,enum) chr scat 13 (L:Num391,enum) chr scat 14 (>@c:FlightPlanNewWaypointIdent, string) 15 </On> 16 </Keys>
Lines 4-7: The “shift register”. Before storing the decimal ascii value of the current keystroke into L:Num391 (Line 8), the value of the previous keystroke entry, which was initially stored in L:Num391, is stored into L:Num392 (Line 7). Preceding that (Line 6), the value in L:Num392 is shifted up to (stored into) L:Num393, and so forth. After 5 keystrokes, the ascii value of first keystroke entered will end up being stored in L:Num395.
Line 8: The ascii decimal value of the current keystroke, (M:Key), is stored into L:Num391.
Lines 9–13: The L:Var ascii values are recalled in a last-in, first-out order, converted back to symbols using the ‘chr’ operator, and concatenated using the ‘scat’ operator to form a string.
Line 14: The concatenated string is entered into FlightPlanNewWaypointIdent.
External dll modules such as Tom Aguilo’s XMLVars (included in his XMLTools module) or Doug Dawson’s String_Storage allow the user to store and retrieve string values without the use of a Shift Register and are highly recommended. For a more complete discussion of string storage options in Flight Simulator, refer to the Storing Strings wiki.
rpmc (July 2014)