Catching keystrokes under Windows

O

Olli Piepponen

Hi,

I'm having a little problem catching keystrokes under Windows. I did a
little research and found that with mscvrt.getch() one can cath a single
key that is pressed. However this doesn't work when the program is run
on the backround and not as the primary task. What I would like to have
is a same sort of function that would also work when the program is being
run on the background. I'm trying to implement a program that would listen
for a certain key to be pressed and then start a timer that would *beep*
after 30 seconds or so. I've everything else sorted out except how to
catch the one key.

So is there an easy way like msvcrt.getch() is or does one have to start
playing with the win32api module? If the win32api-module is needed for this
task could you also explain how? Python is my first real programming
language so I don't understand too much about C\C++ stuff. Examples would
be highly appreciated.
 
P

Peter Hansen

Olli said:
I'm having a little problem catching keystrokes under Windows. I did a
little research and found that with mscvrt.getch() one can cath a single
key that is pressed. However this doesn't work when the program is run
on the backround and not as the primary task. What I would like to have
is a same sort of function that would also work when the program is being
run on the background. I'm trying to implement a program that would listen
for a certain key to be pressed and then start a timer that would *beep*
after 30 seconds or so. I've everything else sorted out except how to
catch the one key.

So is there an easy way like msvcrt.getch() is or does one have to start
playing with the win32api module? If the win32api-module is needed for this
task could you also explain how? Python is my first real programming
language so I don't understand too much about C\C++ stuff. Examples would
be highly appreciated.

You absolutely cannot use msvcrt for this, as it works only with console
programs (i.e. DOS window programs).

You do have to use the win32 stuff, but at that point it becomes mostly
a non-Python question: you will have to research how this is done in
Windows in general, then come back here with the results of that research
and ask how to duplicate it in Python. That part is easy, but the research
is your job.

Note that "background" and "primary task" have little meaning here...
there is no "primary task" under Windows, although there is the concept
of the active window (the top-most one generally). You're probably asking
for a way of "hooking" in to the OS itself, in the same way that something
like Explorer intercepts Alt-Tab no matter where it's typed...

-Peter
 
M

Michael Geary

Olli Piepponen:
I'm having a little problem catching keystrokes under Windows.
I did a little research and found that with mscvrt.getch() one
can cath a single key that is pressed. However this doesn't work
when the program is run on the backround and not as the
primary task. What I would like to have is a same sort of
function that would also work when the program is being run
on the background. I'm trying to implement a program that
would listen for a certain key to be pressed and then start a
timer that would *beep* after 30 seconds or so. I've
everything else sorted out except how to catch the one key.

So is there an easy way like msvcrt.getch() is or does one have
to start playing with the win32api module? If the
win32api-module is needed for this task could you also explain
how? Python is my first real programming language so I don't
understand too much about C\C++ stuff. Examples would be
highly appreciated.

To do this for all Windows applications, you need to use a systemwide
message hook, which is set with the Windows function SetWindowsHookEx using
the WH_KEYBOARD option. The hook code must be in a DLL (dynamic link
library) and should be written in a language like C or C++.

This is a fairly advanced bit of Windows programming, and you wouldn't want
to tackle it without some prior experience in both Windows and C/C++.
However, Pete Parente wrote a DLL that does this keystroke interception and
calls back to Python code to handle the keystrokes. I haven't looked at
Pete's code yet, but you can find it here:

http://sourceforge.net/projects/uncassist

pyHook is what you're looking for on that page. Below is Pete's original
message with some more information.

Hope that helps,

Mike
 
R

Richie Hindle

[Olli]
I'm having a little problem catching keystrokes under Windows.
[...] when the program is being run on the background.
[Mike]
To do this for all Windows applications, you need to use a systemwide
message hook, which is set with the Windows function SetWindowsHookEx
using the WH_KEYBOARD option.

There's an easier way using Windows Hotkeys, as long as you don't expect
the keystroke to be delivered to the focussed application (eg. if the
feature is something like "Press Ctrl+Shift+S to shut down the reactor").

---------------------------------------------------------------------

import sys
from ctypes import *
from ctypes.wintypes import *

# Define the Windows DLLs, constants and types that we need.
user32 = windll.user32

WM_HOTKEY = 0x0312
MOD_ALT = 0x0001
MOD_CONTROL = 0x0002
MOD_SHIFT = 0x0004

class MSG(Structure):
_fields_ = [('hwnd', c_int),
('message', c_uint),
('wParam', c_int),
('lParam', c_int),
('time', c_int),
('pt', POINT)]

# Register a hotkey for Ctrl+Shift+S.
hotkeyId = 1
if not user32.RegisterHotKey(None, hotkeyId, MOD_CONTROL | MOD_SHIFT, ord('S')):
sys.exit("Failed to register hotkey; maybe someone else registered it?")

# Spin a message loop waiting for WM_HOTKEY.
msg = MSG()
while user32.GetMessageA(byref(msg), None, 0, 0) != 0:
if msg.message == WM_HOTKEY and msg.wParam == hotkeyId:
print "Yay!"
windll.user32.PostQuitMessage(0)
user32.TranslateMessage(byref(msg))
user32.DispatchMessageA(byref(msg))
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,969
Messages
2,570,161
Members
46,710
Latest member
bernietqt

Latest Threads

Top