Monitoring Global Input with pyHook
The pyHook library wraps the low-level mouse and keyboard hooks in the Windows Hooking API for use in Python applications. This short tutorial demonstrates how to set keyboard and mouse hooks, what information is available about events, and how to pass or block events.
- Windows 2000 or later (low-level hooks are not supported in earlier versions of Windows)
- Python 2.4 or later
- Mark Hammond's PyWin32 library (formerly known as win32all extensions)
- pyHook 1.4 or later
Any application that wishes to receive notifications of global input events must have a Windows message pump. The easiest way to get one of these is to use the PumpMessages method in the Win32 Extensions package for Python.
import pythoncom pythoncom.PumpMessages()
When run, this program just sits idle and waits for Windows events. If you are using a GUI toolkit (e.g. wxPython), this loop is unnecessary since the toolkit provides its own.
To receive mouse events, you must create a HookManager object and provide it will callbacks for the events in which you are interested. For instance, you can elect to receive only left button down events, only right button up events, only movement events, or all mouse events to name a few. Each event type can be directed to one and only one callback function.
import pythoncom, pyHook def OnMouseEvent(event): # called when mouse events are received print 'MessageName:',event.MessageName print 'Message:',event.Message print 'Time:',event.Time print 'Window:',event.Window print 'WindowName:',event.WindowName print 'Position:',event.Position print 'Wheel:',event.Wheel print 'Injected:',event.Injected print '---' # return True to pass the event to other handlers return True # create a hook manager hm = pyHook.HookManager() # watch for all mouse events hm.MouseAll = OnMouseEvent # set the hook hm.HookMouse() # wait forever pythoncom.PumpMessages()
For a complete list of supported callbacks, see the properties of the HookManager class in the pyHook API documentation.
Keyboard hooks work in the same manner as mouse hooks, but return different information.
import pythoncom, pyHook def OnKeyboardEvent(event): print 'MessageName:',event.MessageName print 'Message:',event.Message print 'Time:',event.Time print 'Window:',event.Window print 'WindowName:',event.WindowName print 'Ascii:', event.Ascii, chr(event.Ascii) print 'Key:', event.Key print 'KeyID:', event.KeyID print 'ScanCode:', event.ScanCode print 'Extended:', event.Extended print 'Injected:', event.Injected print 'Alt', event.Alt print 'Transition', event.Transition print '---' # return True to pass the event to other handlers return True # create a hook manager hm = pyHook.HookManager() # watch for all mouse events hm.KeyDown = OnKeyboardEvent # set the hook hm.HookKeyboard() # wait forever pythoncom.PumpMessages()
Callbacks for key and mouse events can decide whether or not to allow the event messages to pass to the windows for which they were intended. If a callback function returns True, the message is allowed to pass to callbacks registered by other applications and then onto its destination. If the function returns False, the message is blocked.
import pythoncom, pyHook def OnKeyboardEvent(event): # block only the letter A, lower and uppercase return (event.Ascii not in (ord('a'), ord('A'))) # create a hook manager hm = pyHook.HookManager() # watch for all mouse events hm.KeyDown = OnKeyboardEvent # set the hook hm.HookKeyboard() # wait forever pythoncom.PumpMessages()
Not all key and mouse events can be blocked. For instance, pyHook allows the Ctrl-Alt-Delete combo as is suggested by the Windows hooking documentation. (This behavior could be changed by hacking the pyHook C extension so it doesn't play as nicely.)
If a callback function does not return in a timely manner, the event is automatically forwarded along the hook callback chain, and, if no other callback blocks it, onto the destination window. Therefore, as little processing as possible should be done in a callback. Instead, the callback should add events to a queue for later processing by an application and quickly decide whether or not to block the message.
This tutorial introduces the basics of the pyHook library. Please refer to the full pyHook API documentation for more information.
The original author of this tutorial is Peter Parente, and the original location of it is here: http://mindtrove.info/articles/monitoring-global-input-with-pyhook/
It has been moved to the pyHook project space to consolidate all the documentation in one place.