DISCLAIMER THIS GUIDE IS INTENDED FOR READERS RUNNING WINDOWS OS.
Background
By all accounts, I'm relatively new to programming. My first real experience coding was taking a programming course one
and a half years ago through my college's cognitive science department that used python. Long story short is that I got
hooked, and have since learned to write in Matlab, AutoHotKey, Powershell, among other languages.
A pet project that I've been working on involves monitoring the CapsLock on my computer so that the behavior of the copy
and paste functions change while its on. For example: if the caps lock is active, and I copy a string to the clipboard,
then the string will also be added to a list in the python program.
While learning to do this, a number of hurdles got in the way, so I've decided to write this post assembling what I've
learned. I don't assume this guide to be definitive by any means, but I wanted to get the information assembled together
in case it helps anyone.
What Does This Guide Cover?
This guide covers two options for monitoring user-input from the keyboard and mouse using python. Which option is best
for you will depend on your particular needs and situation.
Part 1: Using the msvcrt module's getch function
The first module I will be covering is msvcrt. This module is included as part of the standard library, and
documentation can be found at the following links.
The function I want to highlight in the module is the getch() function. When called, the function will wait for you to
enter a character and will return the character entered as a string. (See the first link above for variants such as
getwch() which does the same thing but returns the unicode value)
Here is a short script to show how the function works (Note IDLE doesn't seem to like this script. Saving it and
clicking the file, or running the file from the command prompt should work):
from msvcrt import getch
def getch_demo():
""" Demonstration of the getch function """
print 'Q to quit'
while True:
result = getch() # get character entered as string
print "You pressed {}".format(result) + '\r',
if result == 'Q' or result == 'q':
break
if __name__=='__main__':
getch_demo()
There are a few things in the functionality of getch that are worth noting.
while it's waiting for a key entry, a module such as subprocess or threading might be needed. * (2) The console window must be the active window for it to register keypresses (You can verify this by clicking
outside the console window and entering a character). * (3) It doesn't monitor meta/modifier keys. It won't monitor keys such as the shift, Ctrl, Window, Fn, etc. Also Arrow
keys return capital letters such as "I",'S","M". * (4) The case of the letter is maintained. So pressing Shift+S will return "S" instead of "s".
On the side-project I'm currently working on numbers (2) and (3) were deal-breakers for me: as I'm trying to monitor the
state of the caps-lock key, and I needed to be able to monitor key presses without the console window being the active
window. To do so lets look now at using the win32api.
Part 2: Using the pywin32 library
The second module I will be looking at is using the pywin32 library. There are quite a few modules that are included in
the library, but I'm going to be focusing on how to use two of the functions from the win32api module to get the state
of keys: GetKeyState and GetAsyncKeyState.
(WHAT THE LIBRARY IS)q
** Basic For Calling the Functions**
Using the functions isn't itself all that difficult and can be done in the usual way: Importing the functions from the
win32api module, and calling them as you would any other function.
from win32api import GetKeyState
from win32api import GetAsyncKeyState
# To check realtime state of the key
GetKeyState(virtual_key_code)
# To check whether key has been pressed since last call
GetAsyncKeyState(virtual_key_code)
What value you give for virtual_key_code will depend on the key (or mouse-button) your trying to check, and will be an
integer between 1 and 254 inclusive. Figuring out which value to pass I found to be the most intimidating part of the
whole procedure. A full list is available at the MDSN documentation. However for those of you want an easy answer or
don't read hex, won't have to worry about the finer points of this conversion process. I've put together two
dictionaries that will convert descriptions of the keys (e.g. 'F key' or 'CTRL key') to their virtual key codes, and
vice-versa. Pastebin link
You (A) can save the code at the preceding link to as a file named something like VirtualKeyLookups.py and import the
dictionaries, or (B) drop the full dictionaries in the file you're working on. (Feel free to do whatever you like with
those dictionaries, I know some of the descriptions should be modified, but I've left them close to the original for
convenience.)
** 2.1 Using GetKeyState **
The first function we'll look at is GetKeyState. GetKeyState gets the current position of the key, and is called by
passing an integer between 1 and 254 inclusive for the key to check. The function will return 0 or 1 if the key is up,
and will return -127 or -128 if the key is down. Each time the key is pressed which of the each of the two values it
will return will cycle. Here's a bit of code to play around with it, substitute the name you gave the dictionaries you
saved earlier accordingly. Pastebin Link
More likely however you don't want to retain the value returned by GetKeyState, and you just want to know if the key is
up or down. So let's define two new functions to check if the key is up or down.
def keyIsUp(key):
keystate = GetKeyState( key )
if (keystate == 0) or (keystate == 1):
return True
else:
return False
def keyIsDown(key):
keystate = GetKeyState( key )
if (keystate != 0) and (keystate != 1):
return True
else:
return False
At this point I should probably say something about the nature of the codes passed for each key. If you think about the
keyboards you've seen recently, you might notice that there is a wide variation in layouts, keys present, etc. To get
around these issues, Microsoft uses something called Virtual Keys, which are standardized across keyboards. There are
254 virtual keys each with their own keycodes. Some of these keys have constants associated with them which you could
use if you chose to (using constants from the win32con module). The official MDSN documentation lists the constants
along with the integer value (in hex) and the description for each on this site.
However, you lucky reader, don't have to worry about the finer points of this conversion process. I've put together
two dictionaries that will convert descriptions of the keys (e.g. 'F key' or 'CTRL key') to their virtual key codes, and
vice-versa. Pastebin link
The function will return 0 or 1 if the key is up, and will return -127 or -128 if the key is down. Each time the key is
pressed which of the values it will return will cycle.
win32api.GetKeyState(virtual_key_code)
win32api.GetAsyncKeyState(virtual_key_code)
virtual_key_code will be an integer argument between 1-254. Which keycode coresponds to what key can appear opaque if
you can't read hex: the keycode for the 5 key on the top row of the keyboard would be 0x3F which for our purposes is
the same as 63.
However, you lucky reader, don't have to worry about the finer points of this conversion process. I've put together
two dictionaries that will convert descriptions of the keys (e.g. 'F key' or 'CTRL key') to their virtual key codes, and
vice-versa. Pastebin link