4

I'm using pyhook and pyhk to map keystrokes on a windows XP machine, and it works fine except for when the keystroke (say, ctrl+z) already exists in the application. In that case, the ctrl+z passes to the application and triggers the action that has been mapped to it.

If you are familiar with autohotkey, note that autohotkey gets around this by defining hotkeys that can optionally be passed to the underlying application. Here's a bit of codes that gets at the idea. Note that I'm trying to keep track of when the ctrl key is down.

  import pythoncom, pyHook
  control_down = False

  def OnKeyboardEvent_up(event):
      global control_down
      if event.Key=='Lcontrol' or event.Key=='Rcontrol':
         control_down=False
      return True

  def OnKeyboardEvent(event,action=None,key='Z',context=None):
      global control_down
      if event.Key=='Lcontrol' or event.Key=='Rcontrol':
         control_down=True
      if control_down and event.Key==key:
         print 'do something'
         return False
      if event.Key=='Pause':
         win32gui.PostQuitMessage(1)
         return False
      # return True to pass the event to other handlers
      return True

  if __name__ == '__main__':
     hm = pyHook.HookManager()
     hm.KeyDown = OnKeyboardEvent
     hm.KeyUp = OnKeyboardEvent_up
     hm.HookKeyboard() # set the hook
     pythoncom.PumpMessages() # wait forever

Any help appreciated.

Thanks!

reckoner
  • 2,861
  • 3
  • 33
  • 43
  • 1
    Sadly (cross-platform) hotkey support is __very bad__ right now in Python. _Advanced (cough)_ things like these are very hard. I'm considering to write my own package for this some time soon. – orlp Jul 25 '12 at 21:11

3 Answers3

3

If you're insterested in Windows only, you can use win API, e.g. via ctypes:

>>> from ctypes import windll
>>> windll.user32.RegisterHotKey(0, -1, 0x0002, 0x5a)

After running these lines of code Ctrl (code = 0x0002) + Z (code = 0x5a) combination doesn't work any more in Python REPL.

So you should better look at what windows are those hotkey registered. More information you can find in MSDN: http://msdn.microsoft.com/en-us/library/windows/desktop/ms646309(v=vs.85).aspx

Rostyslav Dzinko
  • 39,424
  • 5
  • 49
  • 62
0

I may totally wrong here, but from my understanding of the pyHook documentation, in order to prevent the key presses from being sent to another application you need to change the return True in def OnKeyboardEvent_up(event): and OnKeyboardEvent(event,action=None,key='Z',context=None): to return False (or anything else other than True.

andrewmh20
  • 180
  • 1
  • 13
  • @reckoner I actually just ran the code from the question and did not see ctrl+z get mapped to the application I was in while running the script, even with the `return True`. – andrewmh20 Jan 03 '13 at 03:44
0

In windows I noticed that if the code "Do something" takes too long than the key codes are passed to the application even if you return False in the OnKeyboardEvent handler. The solution for me was to pack the code in a thread launched by the key or key combination press. This is sufficiently fast to make the return False work as expected.

def OnKeyboardEvent(event):
      if event.key == myKey:
         myThred = threading.Thread(target=doSomething_Function).start()
         return False
Rabinzel
  • 7,757
  • 3
  • 10
  • 30
Dede95
  • 41
  • 3