KnowledgeBase Archive

An Archive of Early Microsoft KnowledgeBase Articles

View on GitHub

Q64785: ON KEY Key Trap with INKEY$ Loop Requires Additional Key Press

Article: Q64785
Product(s): See article
Version(s): 4.00 4.00b 4.50
Operating System(s): MS-DOS
Keyword(s): ENDUSER | SR# S900731-96 B_BasicCom | mspl13_basic
Last Modified: 13-AUG-1990

A commonly used key-trapping strategy relies on using an INKEY$ loop
to wait for a key press that is then handled by an ON KEY GOSUB
handler. Using this strategy requires two key presses: one that
triggers the ON KEY trap and another to exit the INKEY$ loop upon
returning from the key handler. When making use of a key handler that
performs a process transparent to the user, the key trap may appear to
require two keystrokes for processing to continue. This behavior may
be problematic for those who want processing to resume after one
keystroke. This article contains a code example demonstrating this
behavior and three other code examples illustrating alternate
key-trapping strategies that require only one key press for processing
to continue.

This information applies to Microsoft QuickBASIC versions 4.00, 4.00b,
and 4.50, to Microsoft BASIC Compiler versions 6.00 and 6.00b for
MS-DOS and MS OS/2, and to Microsoft BASIC Professional Development
System (PDS) versions 7.00 and 7.10 for MS-DOS and MS OS/2.

When an INKEY$ loop is used in conjunction with the ON KEY statement
to wait for a key press, control is passed to the ON KEY handler when
a trappable key press occurs. Because the ON KEY GOSUB statement
clears the keyboard buffer, the INKEY$ loop will still be waiting for
a key press when control is returned from the ON KEY GOSUB handler.
Therefore, a second key press is required to exit the INKEY$ loop.

This behavior can be overcome either by using the SLEEP statement in
place of the INKEY$ loop, by setting a flag within the ON KEY handler
that will cause the INKEY$ loop to abort after a key trap, or by
RETURNing from the key handler to a line number or label outside of
the INKEY$ loop.

The following code example demonstrates the requirement for a second
key press:

   CLS
   ON KEY(1) GOSUB handler:
   KEY(1) ON
   PRINT "Press the F1 key"
   WHILE INKEY$ = ""
   WEND
   END
   handler:
           PRINT "In key handler"
           RETURN

The following strategies can be used to allow processing to continue
after one key press:

Sample 1: Using The SLEEP Statement
-----------------------------------

   CLS
   ON KEY(1) GOSUB handler:
   KEY(1) ON
   PRINT "Press the F1 key"
   SLEEP                    'Note: The SLEEP statement was not supported
   END                      '      until QuickBASIC version 4.00b. This
                            '      example will fail in earlier versions.
   handler:
           PRINT "In key handler"
           RETURN

Sample 2: Using Flag to Exit Out of INKEY$ Loop
-----------------------------------------------

   CONST TRUE = -1
   CONST FALSE = NOT TRUE

   CLS
   TrappedFlag% = FALSE
   ON KEY(1) GOSUB handler:
   KEY(1) ON
   PRINT "Press the F1 key"
   WHILE INKEY$ = "" AND NOT TrappedFlag%
   WEND
   END

   handler:
           TrappedFlag% = TRUE
           PRINT "In key handler"
           RETURN

Sample 3: RETURN to a Fixed Line Label or Line Number
-----------------------------------------------------

   CLS
   ON KEY(1) GOSUB handler:
   KEY(1) ON
   PRINT "Press the F1 key"
   WHILE INKEY$ = ""
   WEND

   OutOfLoop:
   END

   handler:
           PRINT "In key handler"
           RETURN OutOfLoop:

WARNING: Do not use the RETURN <line> statement if the ON KEY() GOSUB
statement at the main-level code traps a key pressed within a SUB or
FUNCTION procedure, since RETURN <line> would then leave unrecoverable
return addresses on the stack, which eventually leads to an "Out of
Stack Space" error after many key-trapping GOSUB iterations. RETURN
<line> should only be used in the handler for keys trapped at the main
program level.

Sample 3 above works without producing the "Out of Stack Space" error
because no keys are pressed or trapped in SUB or FUNCTION procedures.

THE INFORMATION PROVIDED IN THE MICROSOFT KNOWLEDGE BASE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. MICROSOFT DISCLAIMS ALL WARRANTIES, EITHER EXPRESS OR IMPLIED, INCLUDING THE WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL MICROSOFT CORPORATION OR ITS SUPPLIERS BE LIABLE FOR ANY DAMAGES WHATSOEVER INCLUDING DIRECT, INDIRECT, INCIDENTAL, CONSEQUENTIAL, LOSS OF BUSINESS PROFITS OR SPECIAL DAMAGES, EVEN IF MICROSOFT CORPORATION OR ITS SUPPLIERS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. SOME STATES DO NOT ALLOW THE EXCLUSION OR LIMITATION OF LIABILITY FOR CONSEQUENTIAL OR INCIDENTAL DAMAGES SO THE FOREGOING LIMITATION MAY NOT APPLY.

Copyright Microsoft Corporation 1986-2002.