Catching key events globally

94 views
Skip to first unread message

Ram Rachum

unread,
Jul 26, 2015, 11:17:01 AM7/26/15
to wxPython-users
Hi everyone,

There's something I'm trying to do with wxPython and I can't figure out how.

I want to catch key events globally. This means key-up, key-down and char events. (I'm trying to build something like AHK in Python.)

Now, I know wxPython allows global hotkeys, but that's not satisfactory, because I want to get all the events, including key up, key down and char. How can I do that? 

(I tried using pyHook, which almost worked except char events aren't implemented.)


Thanks,
Ram.

Ram Rachum

unread,
Jul 26, 2015, 3:15:13 PM7/26/15
to wxPython-users, ram.r...@gmail.com
I should specify: I'm on Windows 7 and I'm okay with a Windows-only solution.

Tim Roberts

unread,
Jul 27, 2015, 2:25:52 PM7/27/15
to wxpytho...@googlegroups.com
A Windows hook is the right solution. You shouldn't need WM_CHAR
events. All keystrokes arrive as WM_KEYDOWN and WM_KEYUP. The default
handler for WM_KEYDOWN will generate a WM_CHAR if it is appropriate for
the key that was pressed. You can get everything you need from the key
down and up sequences.

--
Tim Roberts, ti...@probo.com
Providenza & Boekelheide, Inc.

Ram Rachum

unread,
Jul 27, 2015, 3:13:42 PM7/27/15
to wxPython-users
Hi Tim,

I'm not sure how to follow your solution.

"A Windows hook is the right solution." So you mean I shouldn't use wxPython? Or is there a way to do a global Windows hook for char events in wxPython? If not how can I do this? 

"You can get everything you need from the key down and up sequences." Are you sure? Because I understand that the OS has its own logic for char events. For example, if I press alt-x then it generates a key down event but not a key char event, because a character isn't emitted. Another thing is that non-US keyboards have different characters and their contained in the key char event but not the key down event.


Thanks for your help,
Ram Rachum.



--
You received this message because you are subscribed to a topic in the Google Groups "wxPython-users" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/wxpython-users/q2wnlaWvLxc/unsubscribe.
To unsubscribe from this group and all its topics, send an email to wxpython-user...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Tim Roberts

unread,
Jul 27, 2015, 6:55:22 PM7/27/15
to wxpytho...@googlegroups.com
Ram Rachum wrote:

"A Windows hook is the right solution." So you mean I shouldn't use wxPython? Or is there a way to do a global Windows hook for char events in wxPython? If not how can I do this?

I mean that pyHook will allow you to create a global Windows hook in Python.  It should do what you need to do.



"You can get everything you need from the key down and up sequences." Are you sure? Because I understand that the OS has its own logic for char events. For example, if I press alt-x then it generates a key down event but not a key char event, because a character isn't emitted. Another thing is that non-US keyboards have different characters and their contained in the key char event but not the key down event.

It depends on what you need to do with the information.  The Windows keyboard hooks -- even at the API level -- only deliver key down and key up.  You can look that up in MSDN under the WH_KEYBOARD hook type.

Every key event starts with a key down.  From the key down info, the input subsystem can create a char event, if the current keyboard state warrants it.  A keyboard hook can't get that info, but you can certainly get the same key info that the system got.

Ram Rachum

unread,
Jul 28, 2015, 6:05:51 AM7/28/15
to wxPython-users
On Tue, Jul 28, 2015 at 1:55 AM, Tim Roberts <ti...@probo.com> wrote:
Ram Rachum wrote:

"A Windows hook is the right solution." So you mean I shouldn't use wxPython? Or is there a way to do a global Windows hook for char events in wxPython? If not how can I do this?

I mean that pyHook will allow you to create a global Windows hook in Python.  It should do what you need to do.

PyHook doesn't support char events. From the docs:

    def SubscribeKeyChar(self, func):
        '''
        Registers the given function as the callback for this keyboard event type.
        Use the KeyChar property as a shortcut.

        B{Note}: this is currently non-functional, no WM_*CHAR messages are
        processed by the keyboard hook.

        @param func: Callback function
        @type func: callable
        '''

 



"You can get everything you need from the key down and up sequences." Are you sure? Because I understand that the OS has its own logic for char events. For example, if I press alt-x then it generates a key down event but not a key char event, because a character isn't emitted. Another thing is that non-US keyboards have different characters and their contained in the key char event but not the key down event.

It depends on what you need to do with the information.  The Windows keyboard hooks -- even at the API level -- only deliver key down and key up.  You can look that up in MSDN under the WH_KEYBOARD hook type.

One thing I want to do is get all the typed text.
 

Every key event starts with a key down.  From the key down info, the input subsystem can create a char event, if the current keyboard state warrants it.  A keyboard hook can't get that info, but you can certainly get the same key info that the system got.

I can get all the keydown events and try to recreate the char events, but then I need to reimplement logic like checking whether the alt-key was pressed, or checking the user language and translating the keypress to a character in their language, and possibly lots of other logic I'm not thinking about. A much better solution would be to get those char events directly, after the system has already applied all that logic. The question is how do I get that info. 

 

-- 
Tim Roberts, ti...@probo.com
Providenza & Boekelheide, Inc.

Tim Roberts

unread,
Jul 29, 2015, 2:59:22 PM7/29/15
to wxpytho...@googlegroups.com
Ram Rachum wrote:
On Tue, Jul 28, 2015 at 1:55 AM, Tim Roberts <ti...@probo.com> wrote:
Ram Rachum wrote:

"A Windows hook is the right solution." So you mean I shouldn't use wxPython? Or is there a way to do a global Windows hook for char events in wxPython? If not how can I do this?

I mean that pyHook will allow you to create a global Windows hook in Python.  It should do what you need to do.

PyHook doesn't support char events. From the docs:

Right, because Windows itself does support char events in system hooks.



It depends on what you need to do with the information.  The Windows keyboard hooks -- even at the API level -- only deliver key down and key up.  You can look that up in MSDN under the WH_KEYBOARD hook type.

One thing I want to do is get all the typed text.

Key down and key up will do that, with a little additional work.



Every key event starts with a key down.  From the key down info, the input subsystem can create a char event, if the current keyboard state warrants it.  A keyboard hook can't get that info, but you can certainly get the same key info that the system got.

I can get all the keydown events and try to recreate the char events, but then I need to reimplement logic like checking whether the alt-key was pressed, or checking the user language and translating the keypress to a character in their language, and possibly lots of other logic I'm not thinking about. A much better solution would be to get those char events directly, after the system has already applied all that logic. The question is how do I get that info.

That's a much easier solution for YOU, but it's not a much better solution for the system.  Much of that logic happens in the process of the application that is to receive the message.  The input system deals in key up and key down.

Have you done any reading at all about the window hook concept at the API level?  PyHook isn't inventing any capabilities that aren't in the system.  There are other hook types available.  For example, you can install a hook that gets called every time an application pulls a message from its message queue.  That would certainly get you WM_CHAR messages, but that requires that your hook code be in a DLL, because the DLL has to be injected into every process in the system.  That's a heavyweight operation, and it cannot be done in Python.
Reply all
Reply to author
Forward
0 new messages