test

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.

  • Option 1: Using the msvcrt module, which is included as part of the standard library
  • Option 2: Using the win32api module, which is most easily installed using the msi installer

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.

  • (1) It will simply wait for input when called. This is nice in some situations, but if we want to do something else

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

/r/PostPreview Thread