2017-05-01 25 views
0

win32apiを使用せずにキーボードの各キーを照会したいと思います。私はwin32api.GetAsyncKeyState(key)を使って作業していますが、モジュールがインストールされていない場合にもサポートを追加したいと思います。ctypesを使用してキープレスを照会

これまでのところ完全に動作するコードが1つ見つかりましたが、独自のスレッドを必要とするため重量が重くなり、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() 

答えて

0

は非常に単純な答えであることが判明し、私は最終的にそれを偶然見つけGetKeyState機能の場合

ctypes.windll.user32.GetKeyState(key) 

状態が押されていない時に0または1であること、および押されたときに、そうTrue/False結果を得るために、> 1のチェックがトリックを行うようだ60000のようなものに増加しますか。

GetAsyncKeyStateでも、負の数になることがありますが、時にはそうではありません。そのため、代わりの方法を使用するのが最善だと思いました。

関連する問題