KEYBOARD/MOUSE

Name

KEYBOARD/MOUSE -- 

Function

nCode               ASC(<cExp>)
cChar               CHR(<nCode>)
cKeyLabel           FKLABEL(<nFunctionKey>)
nFunctionKeys       FKMAX()
nButStatus          FT_MBUTPRS( <nButton> [, @nButPrs [, @nX [, @nY] ] ] )
nBStat              FT_MBUTREL( nButton [, @nButRel [, @nX [, @nY] ] ])
                    FT_MCONOFF( <nTop>, <nLeft>, <nBottom>, <nRight> )
lCursorState        FT_MCURSOR( [ <lState> ] )
lIsDoubleClk        FT_MDBLCLK( [ <nClick> [, <nButton> [, <nInterval> [, <nRow> [, <nCol>; [, <nTime> ] ] ] ] ] ] )
NIL                 FT_MDEFCRS( <nCrsType>, <nScrMask>, <nCrsMask> )
nButtonStatus       FT_MGETPOS( @<nX>, @<nY> )
<nPage>             FT_MGETPAGE()
nButtonStatus       FT_MGETPOS( @<nX>, @<nY> )
NIL                 FT_MGETSENS( <@nHoriz>, <@nVert>, <@nDouble> )
nRowPos             FT_MGETX()
nColPos             FT_MGETY()
NIL                 FT_MHIDECRS()
lMouseStatus        FT_MINIT()
lInRegion           FT_MINREGION( <nT>, <nL>, <nB>, <nR> )
NIL                 FT_MMICKEYS( @<nX>, @<nY> )
nMouseStatus        FT_MRESET()
NIL                 FT_MSETPOS( <nX>, <nY> )
NIL                 FT_MSETPAGE( <@nPage> )
NIL                 FT_MSETPOS( <nX>, <nY> )
NIL                 FT_MSETSENS( <nHoriz>, <nVert>, <nDouble> )
NIL                 FT_MSHOWCRS()
<nMajor>            FT_MVERSION( <@nMinor>, <@nType>, <@nIRQ>  )
NIL                 FT_MXLIMIT( <nX1>, <nX2> )
NIL                 FT_MYLIMIT( <nY1>, <nY2> )
cCode               FT_SCANCODE()
nInkeyCode          INKEY([<nSeconds>] [,<nEventMask>])
nInkeyCode          LASTKEY()
nCurrentMouseColumn MCOL()
nSpeed              MDBLCLK([<nNewSpeed>])
NIL                 MHIDE()
lIsPressed          MLEFTDOWN()
lIsPresent          MPRESENT()
NIL                 MRESTSTATE( <cSaveState> )
lIsPressed          MRIGHTDOWN()
nCurrentMouseRow    MROW()
cSaveState          MSAVESTATE()
NIL                 MSETBOUNDS( [<nTop>], [<nLeft>], [<nBottom>], [<nRight>] )
aRegions            MSETCLIP([<nCoord list>], [<nMode>])
lIsVisible          MSETCURSOR( [<lVisible>] )
NIL                 MSETPOS( <nRow>, <nCol> )
nOldCursorShape     MSHOW([<nCol>, <nRow>, <nStyle>]) --> nOldCursorShape MSHOW([<nCursorShape>]) --> nOldCursorShape MSHOW([<nCursorShape>] | [<nCol>, <nRow>, <nMode>])
aState | 0          MSTATE()
nInkeyCode          NEXTKEY()
bCurrentAction      SETKEY(<nInkeyCode>, [<bAction>])

Description

Function FKLABEL()

 FKLABEL(<nFunctionKey>) --> cKeyLabel

FKLABEL() is a compatibility function used to replicate the FKLABEL() function in dBASE III PLUS. As a general principle, the use of this function is not recommended and not needed in xClipper. The function keys are labeled Fn, where n ranges from one to 40 and corresponds directly to the FKLABEL() argument.

Function FKMAX()

 FKMAX() --> nFunctionKeys

FKMAX() is a compatibility function used to replicate the FKMAX() function in dBASE III PLUS. As a general principle, the use of this function is not recommended and not needed in xClipper. It simply returns a constant value of 40.

Function FT_MBUTPRS()

 FT_MBUTPRS( <nButton> [, @nButPrs [, @nX [, @nY] ] ] ) --> nButStatus

Retrieves the mouse button status and the position of the cursor when a button was last pressed.

Function FT_MBUTREL()

 FT_MBUTREL( nButton [, @nButRel [, @nX [, @nY] ] ]) --> nBStat

This function returns the release status of the mouse buttons and the coordinates of the last release.

Function FT_MCONOFF()

 FT_MCONOFF( <nTop>, <nLeft>, <nBottom>, <nRight> )

This function tells the mouse driver to hide the cursor if it is in the given region. The driver hides the cursor by decrementing the cursor flag. A call to FT_MSHOWCRS is required to turn the cursor back on. Calling FT_MSHOWCRS also disables this function.

See FT_MSHOWCRS for a discussion of the cursor display flag.

Function FT_MCURSOR()

 FT_MCURSOR( [ <lState> ] ) --> lCursorState

This function works like most Clipper state functions. If no value is sent to FT_MCURSOR() it will return the state of the mouse cursor.

Function FT_MDBLCLK()

 FT_MDBLCLK( [ <nClick> [, <nButton> [, <nInterval> [, <nRow> [, <nCol>;
 [, <nTime> ] ] ] ] ] ] ) --> lIsDoubleClk

This is a mouse meta function that checks for the presence of a double click.

Function FT_MDEFCRS()

 FT_MDEFCRS( <nCrsType>, <nScrMask>, <nCrsMask> ) --> NIL

In text mode the mouse cursor can either be a software generated or the actual hardware cursor. This routine allows one choose between them. The software cursor is the default and its effect on the character it covers is determined by the screen mask and the cursor mask. Both of these masks are 16 bit values (which in Clipper are passed as standard numerical values). The 16 bit masks are arranged in a manner identical to the way information is stored for each character cell on the screen. The low order 8 bits represent the actual character displayed while the high order bits represent the display atributes such as blinking, intensity and forground and background colors. The mask is represented in the diagram below:

Bit: |15 |14 12|11 |10 8|7 0| Function:|blink |background|intensity|foreground|character|

Blinking and high intensity are on when the bit is 1. The background and foreground indicate which colors are used for each. The software mouse cursor uses these two values by taking the mask from the screen cell it is on and performing a logical AND on each bit with the screen mask value. The result is then logically XOR'ed with the cursor mask value. Thus to keep the character the same but invert the foreground and background colors the following values would be used:

Bit: |15 |14 12|11 |10 8|7 0| Function:|blink |background|intensity|foreground|character| screen: | 0 | 111 | 0 | 111 |11111111 | =30719 cursor: | 0 | 111 | 0 | 111 |00000000 | =30464

The hardware cursor is the text cursor provided by the video board. One specifies the range of scan lines which are on using <nScrMask> and <nCrsMask>. The range of values is dependant upon the type of monitor. The first scan line is 0.

Function FT_MGETCOORD()

 FT_MGETPOS( @<nX>, @<nY> ) --> nButtonStatus

Loads cursor position into x and y coordinates passed by reference and returns the button status.

Function FT_MGETPAGE()

 FT_MGETPAGE() --> <nPage>

This function gets the display page for the mouse cursor. The valid values of nPage is dependent upon the display mode. See FT_SETVPG() for changing the current video page

Function FT_MGETPOS()

 FT_MGETPOS( @<nX>, @<nY> ) --> nButtonStatus

Loads cursor position into x and y coordinates passed by reference and returns the button status. The coordinate system in text mode has eight virtual coordinates per character cell. Thus x=16 means that you are in the Row 2. The values returned by this routine when in text mode and with mouse driver versions 6 and above are multiples of 8. We have experience with drivers prior to that version

Function FT_MGETSENS()

 FT_MGETSENS( <@nHoriz>, <@nVert>, <@nDouble> ) --> NIL

This function returns the current values of the mouse movement sensitivity parameters. The first two arguments control the amount of movement necessary to move the cursor a given amount. The third argument determines the threshold above which the mouse moves at twice the normal speed. For further discussion of these values see FT_MSETSENS()

Function FT_MGETX()

 FT_MGETX() --> nRowPos

Retrieves mouse's row position in virtual screen coordinates. The values returned are multiples of 8 when in text mode and with at least Microsoft drivers 6 and above.

Function FT_MGETY()

 FT_MGETY() --> nColPos

Retrieves mouse's column position in virtual screen coordinates. The values returned are multiples of 8 when in text mode and with at least Microsoft drivers 6 and above.

Function FT_MHIDECRS()

 FT_MHIDECRS() --> NIL

Hides the mouse cursor. Make sure to turn the mouse cursor off when redrawing screens. The mouse cursor dutifully saves the screen under it, so if you draw over the mouse cursor it will create a "hole" in your screen when you move the mouse cursor.

Note: A call to FT_MHIDECRS() decrements a mouse driver variable which indicates whether the cursor is shown. The cursor is visible only when the variable = 0. Thus multiple calls to FT_MHIDECRS() require an equal number of calls to FT_MSHOWCRS() before the cursor will again be visible. Once the variable is 0 calls to FT_MSHOWCRS() does not increment the varaible above 0.

Function FT_MINIT()

 FT_MINIT() --> lMouseStatus

Initializes the mouse drive, associated variables and returns mouse status. It checks to see if the mouse has been previously initialized and if so it does not reinitialize. The row and column limits of mouse movement is set to the maximum for the current video mode. Use FT_MSHOWCRS() to display the mouse cursor.

Function FT_MINREGION()

 FT_MINREGION( <nT>, <nL>, <nB>, <nR> ) --> lInRegion

This function will check to see if the mouse cursor is within the confines of the specified region.

Function FT_MMICKEYS()

 FT_MMICKEYS( @<nX>, @<nY> ) --> NIL

<nX> and <nY> must be passed by reference to receive the mouse position in Mickeys.

Function FT_MRESET()

 FT_MRESET() --> nMouseStatus

Resets the mouse driver and returns mouse status. Use FT_MSHOWCRS() to display the mouse cursor. The mouse is set to allow it to cover the complete screen (as defined by MAXCOL() and MAXROW()). This is necessary because at least some versions of the mouse drivers do not operate according to the documentation when confronted with a 43 or 50 line screen.

Normally, FT_MINIT() should be used to initialize the mouse since it will not reinitialize if already done.

Function FT_MSETCOORD()

 FT_MSETPOS( <nX>, <nY> ) --> NIL

Positions mouse cursor on screen using text (normal row and column) coordinates.

Function FT_MSETPAGE()

 FT_MSETPAGE( <@nPage> ) --> NIL

This function sets the display page for the mouse cursor. The valid values of nPage is dependent upon the display mode. See FT_SETVPG() for changing the current video page

Function FT_MSETPOS()

 FT_MSETPOS( <nX>, <nY> ) --> NIL

Positions mouse cursor on screen. The virtual coordinate system in text mode has eight virtual coordinates per character cell. Thus x=16 means that you are in the Row 2.

Function FT_MSETSENS()

 FT_MSETSENS( <nHoriz>, <nVert>, <nDouble> ) --> NIL

This function allows one to control the mouse movement sensitivity. The first two arguments control the amount of movement necessary to move the cursor a given amount. The values are the percentage of full sensitivity and the default values after installing the mouse driver is 50 which represents approximately 3.2 inches of horizontal and 2 inches of vertical mouse movement to cover the entire screen. A value of 100 requires about 0.9 inches of horizontal mouse movement to cover the screen from one side to the other.

The third argument changes the threshold above which the mouse moves at twice the normal speed. The value is a percentage of full sensitivity with the default (50) providing doubling at 64 mickeys per second.

NOTE: These values are NOT restored after resetting the mouse driver/ hardware. A well behaved application should reset them to the original value upon exiting.

NOTE: The above description is counter to all of the documentation I have available. However, it does not work the way it is documented with Microsoft drivers versions 6.16, 6.24, 7.04 and 8.20. The above movement values are documented to be the number of mickeys per 8 pixels and the double speed value as the number mickeys per second required to double the speed. Each of these values should range from 1 to 32K but the driver forces a maximum of 100. Also the documentation states that resetting the mouse will reset these values. This is not the case.

Function FT_MSHOWCRS()

 FT_MSHOWCRS() --> NIL

Displays the mouse cursor. Make sure to turn the mouse cursor off when redrawing screens. The mouse cursor dutifully saves the screen under it, so if you draw over the mouse cursor it will create a "hole" in your screen when you move the mouse cursor.

Note: A call to FT_MHIDECRS() decrements a mouse driver variable which indicates whether the cursor is shown. The cursor is visible only when the variable = 0. Thus multiple calls to FT_MHIDECRS() require an equal number of calls to FT_MSHOWCRS() before the cursor will again be visible. Once the variable is 0 calls to FT_MSHOWCRS() does not increment the variable above 0.

Function FT_MVERSION()

 FT_MVERSION( <@nMinor>, <@nType>, <@nIRQ>  ) --> <nMajor>

This function returns the current values of the mouse driver version number and type. The major version would be 6 and the minor version would be 10 if the driver were version 6.10. The mouse type and IRQ numbers are also returned.

NOTE: It appears that the values reported when one starts the mouse driver actually have the minor version in hexadecimal! Thus on bootup my screen showed 6.24 but this routine returned 30 for the minor version number!

Function FT_MXLIMIT()

 FT_MXLIMIT( <nX1>, <nX2> ) --> NIL

Set maximum vertical bounds of mouse using virtual screen coordinates.

Function FT_MYLIMIT()

 FT_MYLIMIT( <nY1>, <nY2> ) --> NIL

Set maximum horizontal bounds of mouse using virtual screen coordinates.

Function FT_SCANCODE()

 FT_SCANCODE() --> cCode

FT_SCANCODE() enables you to distinguish the different scancodes of similar keys (such as Grey minus versus regular minus), thus increasing the number of keys your input routine can recognize.

It works like INKEY(), in that it waits for a key to be pressed. The scan code consists of two bytes, which are returned as a two-character string.

For example, calling FT_SCANCODE() and pressing the Grey-minus key will return a two character string:

CHR(45) + CHR(74)

LASTKEY() is not updated by FT_SCANCODE(), so don't try to test LASTKEY() to see what was pressed during an FT_SCANCODE() call. Simply assign the return value to a variable and test that (see the test driver below).

* This was adapted from a short C routine posted by John Kaster on NANFORUM. It was written in Clipper to help demonstrate the FT_INT86 function of the Nanforum Toolkit.

This program requires FT_INT86().

Function INKEY()

 INKEY([<nSeconds>] [,<nEventMask>]) --> nInkeyCode

INKEY() is a keyboard function that extracts the next key pending in the keyboard buffer or the next mouse event and returns a value representing the appropriate event. The value is also saved internally and can be accessed using LASTKEY(). If the <nSeconds> argument is specified and there are no pending keys in the buffer, program execution pauses until a key appears in the keyboard buffer, or an appropriate mouse event occurs, or <nSeconds> has elapsed. The time INKEY() waits is based on the operating system clock and is not related to the microprocessor speed. If <nSeconds> is zero, program execution pauses until a key is pressed or an unmasked mouse event occurs. Note that INKEY() is not a wait state and, therefore, SET KEYs are not active.

INKEY() is similar to the NEXTKEY() function. Unlike INKEY(), however, NEXTKEY() reads, but does not extract the key or mouse event. This is useful when you need to test for a key or mouse event without processing it.

INKEY() is the basic primitive of the xClipper system for fetching keys and mouse events. It is used for polling the keyboard, polling the mouse, or pausing program execution. As an example, you can use INKEY() to terminate commands with a record scope such as LIST, LABEL FORM, and REPORT FORM by including it in a WHILE condition.

<nSeconds>

specifies the number of seconds INKEY() waits for a keypress or mouse event. You can specify the value in increments as small as one-tenth of a second. Specifying zero halts the program until a key is pressed or an unmasked event occurs. If <nSeconds> is omitted, INKEY() does not wait for a keypress or mouse event.

<nEventMask>

specifies which events should be returned. If

<nEventMask>

is omitted, the value represented by the SET EVENTMASK command will be used. If there is no SET EVENTMASK command issued, the default value that will be used is 128 (keyboard events only). This parameter can be any combination of the following values. The constant values listed below are defined in Inkey.ch. Inkey Constants ------------------------------------------------------------------------ Constant Value Descripiton ------------------------------------------------------------------------ INKEY_MOVE 1 Mouse Events INKEY_LDOWN 2 Mouse Left Click Down INKEY_LUP 4 Mouse Left Click Up INKEY_RDOWN 8 Mouse Right Click Down INKEY_RUP 16 Mouse Right Click Up INKEY_KEYBOARD 128 Keyboard Events INKEY_ALL 159 All Mouse and Keyboard Events ------------------------------------------------------------------------

Returns :

INKEY() returns an integer value from -39 to 386 for keyboard events and integer values from 1001 to 1007 for mouse events. This value identifies either the key extracted from the keyboard buffer or the mouse event that last occurred. If the keyboard buffer is empty, and no mouse events are taking place, INKEY() returns 0. INKEY() returns values for all ASCII characters, function, Alt+Function, Ctrl+Function, Alt+Letter, and Ctrl+Letter key combinations.

See also : CHR() LASTKEY() NEXTKEY()

Function LASTKEY()

 LASTKEY() --> nInkeyCode

LASTKEY() is a function that reports the INKEY() value of the last key fetched from the keyboard buffer by the INKEY() function, or the next mouse event, or a wait state such as ACCEPT, INPUT, READ, WAIT, ACHOICE(), DBEDIT(), or MEMOEDIT(). The time LASTKEY() waits is based on the operating system clock and is not related to the microprocessor speed. LASTKEY() retains its current value until another key is fetched from the keyboard buffer.

LASTKEY() has a number of uses which include:

Determining the key that terminates a READ

Determining the key that exits the current Get object within a user-defined function, invoked by a VALID clause

Identifying an exception key in the user function of ACHOICE(), DBEDIT(), or MEMOEDIT()

LASTKEY() is also used with UPDATED() to determine if any Get object's buffer was changed during a READ.

LASTKEY() is related to NEXTKEY() and READKEY(). NEXTKEY() reads the current key pending in the keyboard buffer without removing it. Use NEXTKEY() instead of INKEY() when polling for a key.

For a complete list of INKEY() codes and Inkey.ch constants for each key, refer to the Error Messages and Appendices Guide.

Function MCOL()

 MCOL() --> nCurrentMouseColumn

Function MDBLCLK()

 MDBLCLK([<nNewSpeed>]) --> nSpeed

Function MHIDE()

 MHIDE() --> NIL

MHIDE() hides the mouse pointer. This function should be used together with MSHOW() when updating the screen. It is important to hide the mouse pointer before changing the screen display and then show it again after the change.

Note: The MSETCURSOR() function should be used in place of MSHOW() and MHIDE(). It is kept here for compatibility.

Function MLEFTDOWN()

 MLEFTDOWN() --> lIsPressed

Function MPRESENT()

 MPRESENT() --> lIsPresent

Function MRESTSTATE()

 MRESTSTATE( <cSaveState> ) --> NIL

Function MRIGHTDOWN()

 MRIGHTDOWN() --> lIsPressed

Function MROW()

 MROW() --> nCurrentMouseRow

Function MSAVESTATE()

 MSAVESTATE() --> cSaveState

Function MSETBOUNDS()

 MSETBOUNDS( [<nTop>], [<nLeft>], [<nBottom>], [<nRight>] ) --> NIL

Function MSETCLIP()

 MSETCLIP([<nCoord list>], [<nMode>]) --> aRegions

MSETCLIP() controls mouse pointer movements. It allows you to restrict movement to a region. When an inclusion is defined and the user tries to move the mouse pointer out of the rectangle, it remains stuck at the edge of the area, but is still visible. This mode should be used to restrict the range of user choices for moving or clicking the mouse.

Function MSETCURSOR()

 MSETCURSOR( [<lVisible>] ) --> lIsVisible

Function MSETPOS()

 MSETPOS( <nRow>, <nCol> ) --> NIL

Function MSHOW()

 MSHOW([<nCol>, <nRow>, <nStyle>]) --> nOldCursorShape
 MSHOW([<nCursorShape>]) --> nOldCursorShape
 MSHOW([<nCursorShape>] | [<nCol>, <nRow>, <nMode>]) --> nOldCursorShape

MSHOW() displays the mouse pointer. It is generally used without parameters to simply redisplay the mouse pointer at the position where MHIDE() hid it (assuming the user has not moved the mouse).

It is possible to use two sets of parameters with this function.

Specify the coordinates where the pointer should appear. In this case, three parameters must be passed: the mode and its coordinates. In text mode, coordinates are passed as row and column. In graphic mode, you can pass either text or graphic coordinates. Conversion is done automatically based on the font size of the current characters.

You can also specify the mouse cursor shape to be displayed when the mouse is visible. This feature is available in graphic mode only.

It is important to hide the mouse pointer before any new screen display, and then show it again. See MHIDE() for further information on how to do this.

Note: The MSETCURSOR() function should be used in place of MSHOW() and MHIDE(). It is kept here for compatibility.

Function MSTATE()

 MSTATE() --> aState | 0

MSTATE() returns information on the mouse state, i.e., the current screen position of the pointer, the state of the left and right mouse buttons, the visibility status of the mouse pointer, and the version of the mouse driver.

Returns :

 MSTATE() Return Array
 ------------------------------------------------------------------------
 Position                 Description
 ------------------------------------------------------------------------
 LLM_STATE_X              State of X position.
 LLM_STATE_Y              State of Y position.
 LLM_STATE_ROW            State of column position.
 LLM_STATE_COL            State of line position.
 LLM_STATE_LEFT           State of left mouse button.  LLM_BUTTON_DOWN
 means down and LLM_BUTTON_UP means up.
 LLM_STATE_RIGHT          State of right mouse button.  LLM_BUTTON_DOWN
 means down and LLM_BUTTON_UP means up.
 LLM_STATE_VISIBLE        State of mouse pointer.  True (.T) means
 visible and false (.F) means invisible.  (See
 MSHOW() and MHIDE() for more information.)
 LLM_STATE_DRIVER         Indicates version of mouse driver.
 LLM_STATE_SHAPE          Mouse cursor shape.  (See note below.)
 LLM_STATE_CLICKS_LEFT    Number of left clicks since last MSTATE() call.
 LLM_STATE_CLICKS_RIGHT   Number of right clicks since last MSTATE()
 call.
 ------------------------------------------------------------------------
 
Note: The following are the possible values predefined for this return array position: LLM_CURSOR_ARROW, LLM_CURSOR_SIZE_NS, LLM_CURSOR_SIZE_WE, LLM_CURSOR_SIZE_NW_SE, LLM_CURSOR_SIZE_NE_SW, LLM_CURSOR_HAND, LLM_CURSOR_FINGER, LLM_CURSOR_CROSS, LLM_CURSOR_WAIT. For a description of these values see the MSHOW() table of Cursor Shape Constants. If the mouse is missing, 0 is returned. The number of clicks (i.e., aState[LLM_STATE_CLICKS_LEFT] and aState[LLM_STATE_CLICKS_RIGHT]) is reset each time MSTATE() is called. Use MSTATE() to reset the mouse settings when needed.

See also : MHIDE() MSETCURSOR() MSHOW()

Function NEXTKEY()

 NEXTKEY() --> nInkeyCode

NEXTKEY() is a function that reads the keystroke pending in the keyboard buffer or the next mouse event without removing it. The value returned is the INKEY() code of the key pressed--the same value as returned by INKEY() and LASTKEY(). NEXTKEY() returns values for all ASCII characters as well as function, Alt+function, Ctrl+function, Alt+letter, and Ctrl+letter key combinations.

NEXTKEY() is like the INKEY() function but differs in one fundamental respect. INKEY() removes the pending key from the keyboard buffer and updates LASTKEY() with the value of the key. by contrast NEXTKEY() reads, but does not remove the key from the keyboard buffer, and does not update LASTKEY().

Since NEXTKEY() does not remove the key from the keyboard buffer, it can be used to poll the keyboard, and then pass control to a routine that uses a wait state or INKEY() to actually fetch the key from the buffer.

For a complete list of INKEY() codes and Inkey.ch constants.

Function SETKEY()

 SETKEY(<nInkeyCode>, [<bAction>]) --> bCurrentAction

SETKEY() is a keyboard function that sets or queries the automatic action associated with a particular key during a wait state. A wait state is any mode that extracts keys from the keyboard except for INKEY(), but including ACHOICE(), DBEDIT(), MEMOEDIT(), ACCEPT, INPUT, READ and WAIT. Up to 32 keys may be assigned at any one time. At startup, the system automatically assigns the F1 key to execute a procedure or user-defined function named Help.

When an assigned key is pressed during a wait state, the EVAL() function evaluates the associated <bAction> and the parameters, PROCNAME(), PROCLINE(), and READVAR(). It is, however, not necessary to list arguments when specifying <bAction> if you do not plan to use them within the action block.

SETKEY() is like the SET KEY command which associates a procedure invocation with a key.