Three functions useful for acting upon a key pressed in a Windows text only console application. Typical usage would be in the design of menu selections and escaping from loops.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 | def keypress():
"""
Waits for the user to press a key. Returns the ascii code
for the key pressed or zero for a function key pressed.
"""
import msvcrt
while 1:
if msvcrt.kbhit(): # Key pressed?
a = ord(msvcrt.getch()) # get first byte of keyscan code
if a == 0 or a == 224: # is it a function key?
msvcrt.getch() # discard second byte of key scan code
return 0 # return 0
else:
return a # else return ascii code
def funkeypress():
"""
Waits for the user to press any key including function keys. Returns
the ascii code for the key or the scancode for the function key.
"""
import msvcrt
while 1:
if msvcrt.kbhit(): # Key pressed?
a = ord(msvcrt.getch()) # get first byte of keyscan code
if a == 0 or a == 224: # is it a function key?
b = ord(msvcrt.getch()) # get next byte of key scan code
x = a + (b*256) # cook it.
return x # return cooked scancode
else:
return a # else return ascii code
def anykeyevent():
"""
Detects a key or function key pressed and returns its ascii or scancode.
"""
import msvcrt
if msvcrt.kbhit():
a = ord(msvcrt.getch())
if a == 0 or a == 224:
b = ord(msvcrt.getch())
x = a + (b*256)
return x
else:
return a
# -----------------------------------------------------------------------------
# demo applications.
def about(): return\
"""
Keys reported: ENTER, comma, period, greater-than, less-than.
Upper and lower case keys: A, C, H, Q.
Function Keys: F1, SHIFT-F1, CTRL-F1, ALT-F1, Left arrow,
right arrow, page up, page down.
Any other keys are assigned to print "Default"
Pressing ESC or Q will initiate exit query.
Pressing A will print this text.
"""
def keycommands(x):
if x == 13: # ENTER
print 'ENTER pressed'
return True
if x in map(ord,'aA'): # A
print about()
return True
if x in map(ord,'cC'): # C
print 'Continue'
return True
if x in map(ord,'hH'): # H
print 'HELP'
return True
if x in map(ord,'qQ') or x == 27: # Q or ESC
print 'Press any key to exit.'
keypress()
print 'Bye'
return False
if x == ord(','): # ,
print 'Comma'
return True
if x == ord('.'): # .
print 'Period'
return True
if x == ord('>'): # >
print 'Greater Than'
return True
if x == ord('<'): # <
print 'Less Than'
return True
if x == 15104: # F1
print 'F1'
return True
if x == 21504: # SHIFT-F1
print 'SHIFT-F1'
return True
if x == 24064: # CTRL-F1
print 'CNTRL-F1'
return True
if x == 26624: # ALT-F1
print 'ALT-F1'
return True
if x == 18912: # PAGE UP
print 'PAGE UP'
return True
if x == 20960: # PAGE DOWN
print 'PAGE DOWN'
return True
if x == 19424: # LEFT ARROW KEY
print 'LEFT ARROW KEY'
return True
if x == 19936: # RIGHT ARROW KEY
print 'RIGHT ARROW KEY'
return True
print 'Default' # Any remaining keys
return True
def validating(x):
if x in map(ord,'hH'): # query if help is needed
print 'Would you like to see the help menu? <y/n>',
if keypress() in map(ord,'yY'):
return ord('h') # help needed
else: return ord('c') # help not needed
if x in map(ord,'qQ'): # query if quitting is requested
print 'Would you like to quit? <y/n>',
if keypress() in map(ord,'yY'):
return ord('q') # quit
else: return ord('c') # don't quit
return x # otherwise, x is any key other than H,Q.
#################################
# The keypress interpreter demo #
#################################
def commandloop():
print 'Keypress interpreter utility.'
print about()
print 'Waiting...'
interpreting=True
while interpreting:
interpreting=keycommands(validating(funkeypress()))
####################################
# The IBM scancode display utility #
####################################
def scancode():
print 'IBM scancode utility.\nPress CTRL-C to quit.'
while 1:
x=funkeypress()
print 'Dec: %d Hex: %x' % (x,x)
########################
# The Exit key example #
########################
def exitkey():
x = True
while x != 20448: # END key?
print 'o',
x = anykeyevent() # key?
if x == 20448 : break # if END key touched, then break.
elif x == None: continue # if no key touched, continue printing.
else: # if other key touched, prompt user.
print '\nPress END key to exit. Other key to continue printing.'
x = funkeypress()
#------------------------------------------------------------------------------
# The main loop.
if __name__ == '__main__':
while 1:
print """Please select one from the menu:
[1] Keypress interpreter demo.
[2] IBM scancode utility.
[3] Exit key example\n"""
x=keypress()
if x == ord('1'): commandloop()
if x == ord('2'): scancode()
if x == ord('3'): exitkey()
print 'Press q to quit.\n'
if keypress() in map(ord,'qQ'):
break
else:
continue
|
I've included demo applications the user may select from the main loop that demonstrate keyboard detection functionality:
commandloop(), a keypress interpreter demo, implements a 'case' statement to invoke an action to perform dependant upon what key is pressed.
scancode(), an IBM keyboard scancode utility for displaying the assigned keycode for the key pressed.
exitkey(), an example of detecting a key pressed. Prints an 'o' until key is pressed. Exit if END is pressed. Otherwise prints a message and waits for user input.
Because the keypress(),funkeypress(), and anykeyevent() functions are limited to Windows text only console applications, you'll either need to run the included demo application by double-clicking on the filename of this script from Windows Explorer, drag the filename to the START/RUN file launcher, or import the script into Python.exe. A script that uses either of these functions in a GUI based application or editing a file in the IDLE environment and pressing CNTL+F5 for example, will not run properly.
Busy waiting. Why are you looping in the first two functions, waiting for kbhit()? Calling getch() should do the trick already.
Using mscvrt.kbhit() allows me to hit CNTL-C to abort a function. But you're right that it's not necessary to use it in conjunction with getch().
Robert
Thanks for the solution! It was very helpfull to me. In my own script I just fix one thing:
this makes a processor idle for a 0.25 second in each cycle for me it's important, because, for example, on my Core i3 330M CPU I've got a 10-15% workload until the while-loop in progress after adding sleep(0.25) the CPU works normally without visible workload
I guess that 0.25 second is not critical if we are talking about keyboard input, anyway this value can be decreased...
...or, maybe anybody knows better solution?
Sorry, missprinting. time.sleep(0.25) should be inside the while-loop: