Max1234-ITA
Max1234-ITA

Reputation: 176

Python 2.7 - How to check if SHIFT-Key or CTRL+Key is pressed?

I wrote a small routine in python 2.7, which waits for some time (say, 10 minutes) but immediately exits if a key is pressed by the the user.

I'm on Windows (7, 64-bit), so I tried using the msvcrt library:

import sys
import msvcrt
from time import sleep

   def sleep_sec(secstosleep, allowskip = True):
       waitinterval_ms = 0.050
       nwaits = int(secstosleep * 1000 / waitinterval)

       sys.stdout.write("\n    Sleeping for %s seconds. You can press CTRL-F12 to skip.\n\n" % secstosleep)
       for sl in range(0, nwaits + 1):
           sleep(waitinterval_ms)
           if allowskip:
               # Check if User has pressed CTRL-F12 to stop waiting
               if = msvcrt.kbhit():
                   kp = msvcrt.getch()
                   if kp == '\xe0':
                        print "\a"  # Beep once
                        sys.stdout.write("\nSleep interrupted by User\n")
                        break

In effect it works quite well, except for the fact that it will break if the user hits either F12, F11 or Cursor Up key: I found out that if I press F12, getch() will return the '\xe0', but it seems the same code is also returned by the other mentioned keys; no way to trap CTRL, SHIFT, ALT, etc.

I would like to force the user pressing CTRL-F12, instead, to avoid quitting the wait by inadvertently hitting one of those keys.

Am I doing something wrong? Is there a way to intercept CTRL, ALT or SHIFT being pressed along with another key?

Thanks in advance, Max - Italy

Upvotes: 2

Views: 13454

Answers (3)

Nouman
Nouman

Reputation: 7303

I will suggest you to use keyboard module. It has a lot of features and is pretty simple to use. You can also use it to detect keypresses. Examples:
If you want to detect key a:

import keyboard as kb
while True:
    if kb.is_pressed("a"):break

You can also use it to detect combinations. For example , if you want to check if a and b are pressed at the same time:

import keyboard as kb
while True:
    if kb.is_pressed("a+b"):break

So , you can use to to detect if ctrl and f12 are pressed:

import keyboard as kb
while True:
    if kb.is_pressed("ctrl+f12"):break

A sample according to your posted code:

import sys
import keyboard as kb
import time
def sleep_sec(secstosleep,allowskip=True):
    t = time.time() #getting time in sec
    sys.stdout.write("\n    Sleeping for %s seconds. You can press CTRL-F12 to skip.\n\n"% secstosleep)
    if allowskip:
        while time.time() - t <= secstosleep: #while current time(in sec) - t is less than secstosleep
            if kb.is_pressed("ctrl+f11"): #if ctrl and f12 are pressed
                print "\a"
                sys.stdout.write("\nSleep interrupted by User\n")
                quit(0)
sleep_sec(10*60) # 10*60 == 10 min

Upvotes: 7

Max1234-ITA
Max1234-ITA

Reputation: 176

As suggested by Daniel, I've modified my code like this:

import sys
import msvcrt
from time import sleep

def sleep_sec(secstosleep, allowskip = True):
   waitinterval_ms = 0.050
   nwaits = int(secstosleep * 1000 / waitinterval)

   sys.stdout.write("\n    Sleeping for %s seconds. You can press CTRL-F12 to skip.\n\n" % secstosleep)
   for sl in range(0, nwaits + 1):
       sleep(waitinterval_ms)
       if allowskip:
           # Check if User has pressed CTRL-F12 to stop waiting
           if = msvcrt.kbhit():
               kp = msvcrt.getch()
               if kp == '\xe0':
                    kp += msvcrt.getch()

               if kp == '\xe0\x8a':    # \x8a is the keycode for CTRL-F12
                    print "\a"  # Beep once
                    sys.stdout.write("\nSleep interrupted by User\n")
                    break

I've also noticed that different keycodes are returned for F12, CTRL-F12 and SHIFT-F12, so keystrokes can be easily recognized.

Thanks again, Daniel!

Max.

Upvotes: 0

Daniel Trugman
Daniel Trugman

Reputation: 8491

From the msvcrt manual for msvcrt.getch():

[..] If the pressed key was a special function key, this will return '\000' or '\xe0'; the next call will return the keycode.

Just call getch() again to get the actual keycode

Upvotes: 2

Related Questions