Python 使用ctypes查询按键

Python 使用ctypes查询按键,python,keyboard-events,Python,Keyboard Events,我想在不使用win32api的情况下查询键盘的每个键。我使用win32api.GetAsyncKeyState(key)使其工作,但我还想添加对未安装模块的支持 到目前为止,我已经找到了一段完全可以工作的代码,尽管它看起来有点重,因为它需要自己的线程,并且需要超过1600个单独的函数,因为我想捕捉每个键,而不管修改器是什么(每个键有14种可能的组合) 这是我找到的代码,有人能建议一个替代方案,或者如何绕过修饰符问题吗 import ctypes import ctypes.wintypes im

我想在不使用
win32api
的情况下查询键盘的每个键。我使用
win32api.GetAsyncKeyState(key)
使其工作,但我还想添加对未安装模块的支持

到目前为止,我已经找到了一段完全可以工作的代码,尽管它看起来有点重,因为它需要自己的线程,并且需要超过1600个单独的函数,因为我想捕捉每个键,而不管修改器是什么(每个键有14种可能的组合)

这是我找到的代码,有人能建议一个替代方案,或者如何绕过修饰符问题吗

import ctypes
import ctypes.wintypes
import win32con


class GlobalHotKeys(object):
    """
    Register a key using the register() method, or using the @register decorator
    Use listen() to start the message pump

    Example:

    from globalhotkeys import GlobalHotKeys

    @GlobalHotKeys.register(GlobalHotKeys.VK_F1)
    def hello_world():
        print 'Hello World'

    GlobalHotKeys.listen()
    """

    key_mapping = []
    user32 = ctypes.windll.user32

    MOD_ALT = win32con.MOD_ALT
    MOD_CTRL = win32con.MOD_CONTROL
    MOD_CONTROL = win32con.MOD_CONTROL
    MOD_SHIFT = win32con.MOD_SHIFT
    MOD_WIN = win32con.MOD_WIN

    @classmethod
    def register(cls, vk, modifier=0, func=None):
        """
        vk is a windows virtual key code
         - can use ord('X') for A-Z, and 0-1 (note uppercase letter only)
         - or win32con.VK_* constants
         - for full list of VKs see: http://msdn.microsoft.com/en-us/library/dd375731.aspx

        modifier is a win32con.MOD_* constant

        func is the function to run.  If False then break out of the message loop
        """

        # Called as a decorator?
        if func is None:
            def register_decorator(f):
                cls.register(vk, modifier, f)
                return f
            return register_decorator
        else:
            cls.key_mapping.append((vk, modifier, func))


    @classmethod
    def listen(cls):
        """
        Start the message pump
        """

        for index, (vk, modifiers, func) in enumerate(cls.key_mapping):
            if not cls.user32.RegisterHotKey(None, index, modifiers, vk):
                raise Exception('Unable to register hot key: ' + str(vk) + ' error code is: ' + str(ctypes.windll.kernel32.GetLastError()))

        try:
            msg = ctypes.wintypes.MSG()
            i = 0

            while cls.user32.GetMessageA(ctypes.byref(msg), None, 0, 0) != 0:
                if msg.message == win32con.WM_HOTKEY:
                    (vk, modifiers, func) = cls.key_mapping[msg.wParam]
                    if not func:
                        break
                    func()

                cls.user32.TranslateMessage(ctypes.byref(msg))
                cls.user32.DispatchMessageA(ctypes.byref(msg))


        finally:
            for index, (vk, modifiers, func) in enumerate(cls.key_mapping):
                cls.user32.UnregisterHotKey(None, index)


    @classmethod
    def _include_defined_vks(cls):
        for item in win32con.__dict__:
            item = str(item)
            if item[:3] == 'VK_':
                setattr(cls, item, win32con.__dict__[item])


    @classmethod
    def _include_alpha_numeric_vks(cls):
        for key_code in (list (range(ord('A'), ord('Z') + 1)) + list(range(ord('0'), ord('9') + 1)) ):
            setattr(cls, 'VK_' + chr(key_code), key_code)

GlobalHotKeys._include_defined_vks()
GlobalHotKeys._include_alpha_numeric_vks()
这是一个如何使用它读取
a
的示例:

@GlobalHotKeys.register(ord('A'))
def a():
    print 'a'
@GlobalHotKeys.register(ord('A'), GlobalHotKeys.MOD_SHIFT)
def a_shift():
    print 'shift + a'
@GlobalHotKeys.register(ord('A'), GlobalHotKeys.MOD_CONTROL | GlobalHotKeys.MOD_SHIFT)
def a_ctrl_shift():
    print 'ctrl + shift + a'
...

GlobalHotKeys.listen()

结果证明这是一个非常简单的答案,当我试图阅读
GetKeyState
函数的microsoft信息时,我最终偶然发现了它

ctypes.windll.user32.GetKeyState(key)
未按下时,状态将为0或1,按下时将增加到60000左右,因此要获得
True/False
结果,检查
>1
似乎就可以了

GetAsyncKeyState
也可以,但有时会导致负数,有时则不会,所以我认为最好使用替代方法