class Voice2Keyboard: def __init__(self): self.hook = Hook() self.hook.handler = self.on_event self.HOTKEY = {'Lwin', 'Z'} self.LANGUAGE = "tr-TR" self.recognizer = speech_recognition.Recognizer() self.lock = False self.list_devices() def list_devices(self): for index, name in enumerate( speech_recognition.Microphone.list_microphone_names()): log.info(f"device_index[{index}]='{name}'") log.info( "if microphone doesn't work, try to set DEVICE_INDEX to one the devices above" ) self.DEVICE_INDEX = None def on_event(self, event): if not isinstance( event, KeyboardEvent) or event.event_type != 'key down' or self.lock: return False if set(event.pressed_key) != self.HOTKEY: # log.info(event.__dict__) return False self.lock = True log.info("listening...") with speech_recognition.Microphone( device_index=self.DEVICE_INDEX) as source: audio = self.recognizer.listen(source) log.info("converting audio to text...") try: text = self.recognizer.recognize_google( audio_data=audio, # This uses Google Speech Engine's public API key. # If you exceed the quota, you need your own API key from https://console.developers.google.com/ key="AIzaSyBOti4mM-6x9WDnZIjIeyEU21OpBXqWBgw", language=self.LANGUAGE) log.info(f"typing '{text}'") keyboard.send_keys(text, with_spaces=True) except: log.exception("") finally: keyboard.send_keys("{VK_LWIN up}{Z up}") self.lock = False def listen(self): log.info(f"registering {self.HOTKEY} hotkey") self.hook.hook(keyboard=True, mouse=False) def exit(self): log.info(f"unregistering hotkey") self.hook.unhook_keyboard()
def mouse_key_hook(): global monitor_thread_id global hk monitor_thread_id = win32api.GetCurrentThreadId() hk = Hook() hk.handler = on_event hk.hook(keyboard=True, mouse=True)
def __init__(self): self.hook = Hook() self.hook.handler = self.on_event self.HOTKEY = {'Lwin', 'Z'} self.LANGUAGE = "tr-TR" self.recognizer = speech_recognition.Recognizer() self.lock = False self.list_devices()
def setUp(self): """Set some data and ensure the application is in the state we want""" self.hook = Hook() # Save pointers to original system calls before mocking self.CallNextHookEx = windll.user32.CallNextHookEx self.PeekMessageW = windll.user32.PeekMessageW self.TranslateMessage = windll.user32.TranslateMessage self.DispatchMessageW = windll.user32.DispatchMessageW self.atexit_register = atexit.register self.sys_exit = sys.exit self.fake_kbhook_id = 22 self.fake_mousehook_id = 33
def setUp(self): """Set some data and ensure the application is in the state we want""" self.logger = pywinauto.actionlogger.ActionLogger() self.hook = Hook() self.hook.handler = self._on_hook_event self.wait_time = 0.4 self.short_wait_time = self.wait_time / 4.0 self.timer = None self.keybd_events = [] self.mouse_events = [] self.app = None # prevent capturing keyboard keys when launching a test manually time.sleep(self.short_wait_time)
def listen(): # set up hook hook = Hook() hook.handler = on_event hook.hook(keyboard=True, mouse=True) hook.listen()
class Win32HooksTests(unittest.TestCase): """Unit tests for the Win32Hook class""" def setUp(self): """Set some data and ensure the application is in the state we want""" self.logger = pywinauto.actionlogger.ActionLogger() self.hook = Hook() self.hook.handler = self._on_hook_event self.wait_time = 0.4 self.short_wait_time = self.wait_time / 4.0 self.timer = None self.keybd_events = [] self.mouse_events = [] self.app = None # prevent capturing keyboard keys when launching a test manually time.sleep(self.short_wait_time) def tearDown(self): """Close all hooks after tests""" self.keybd_events = [] self.mouse_events = [] if self.timer: self.timer.cancel() self.hook.stop() if self.app: self.app.kill() def _get_safe_point_to_click(self): """Run notepad.exe to have a safe area for mouse clicks""" mfc_samples_folder = os.path.join(os.path.dirname(__file__), r"..\..\apps\MFC_samples") if is_x64_Python(): mfc_samples_folder = os.path.join(mfc_samples_folder, 'x64') sample_exe = os.path.join(mfc_samples_folder, "CmnCtrl1.exe") self.app = Application() self.app.start(sample_exe) self.app.CommonControlsSample.wait("ready") return self.app.CommonControlsSample.rectangle().mid_point() def _sleep_and_unhook(self): """A helper to remove all hooks after a pause""" time.sleep(self.short_wait_time) self.hook.stop() def trace(self, msg, *args): """Log the specified message""" self.logger.log(msg.format(*args)) def _on_hook_event(self, args): """Callback for keyboard events""" if isinstance(args, KeyboardEvent): self.trace( "Win32HooksTests::_on_hook_event got KeyboardEvent: key={0} type={1}", args.current_key, args.event_type) self.keybd_events.append(args) elif isinstance(args, MouseEvent): self.trace( "Win32HooksTests::_on_hook_event got MouseEvent: key={0} type={1}", args.current_key, args.event_type) self.mouse_events.append(args) def _type_keys_and_unhook(self, key_strokes): """A timer callback to type key strokes and unhook""" send_keys(key_strokes) # Give a time to process the keys by the hook self._sleep_and_unhook() def test_keyboard_hook_unicode_sequence(self): """Test capturing a sequence of unicode keystrokes by a keyboard hook""" keys = u'uk' self.timer = Timer(self.wait_time, self._type_keys_and_unhook, [keys]) self.timer.start() self.hook.hook(keyboard=True, mouse=False) # Continue here only when the hook will be removed by the timer _delete_keys_from_terminal(keys) self.assertEqual(len(self.keybd_events), 4) self.assertEqual(self.keybd_events[0].current_key, u'u') self.assertEqual(self.keybd_events[0].event_type, 'key down') self.assertEqual(len(self.keybd_events[0].pressed_key), 0) self.assertEqual(self.keybd_events[1].current_key, u'u') self.assertEqual(self.keybd_events[1].event_type, 'key up') self.assertEqual(len(self.keybd_events[1].pressed_key), 0) self.assertEqual(self.keybd_events[2].current_key, u'k') self.assertEqual(self.keybd_events[2].event_type, 'key down') self.assertEqual(len(self.keybd_events[2].pressed_key), 0) self.assertEqual(self.keybd_events[3].current_key, u'k') self.assertEqual(self.keybd_events[3].event_type, 'key up') self.assertEqual(len(self.keybd_events[3].pressed_key), 0) def test_keyboard_hook_parallel_pressed_keys(self): """Test capturing parallel pressed keys by a keyboard hook""" keys = u'+a' self.timer = Timer(self.wait_time, self._type_keys_and_unhook, [keys]) self.timer.start() self.hook.hook(keyboard=True, mouse=False) # Continue here only when the hook will be removed by the timer _delete_keys_from_terminal(keys) self.assertEqual(len(self.keybd_events), 4) self.assertEqual(self.keybd_events[0].current_key, u'Lshift') self.assertEqual(self.keybd_events[0].event_type, 'key down') self.assertEqual(len(self.keybd_events[0].pressed_key), 0) self.assertEqual(self.keybd_events[1].current_key, u'A') self.assertEqual(self.keybd_events[1].event_type, 'key down') self.assertEqual(len(self.keybd_events[1].pressed_key), 0) self.assertEqual(self.keybd_events[2].current_key, u'A') self.assertEqual(self.keybd_events[2].event_type, 'key up') self.assertEqual(len(self.keybd_events[2].pressed_key), 0) self.assertEqual(self.keybd_events[3].current_key, u'Lshift') self.assertEqual(self.keybd_events[3].event_type, 'key up') self.assertEqual(len(self.keybd_events[3].pressed_key), 0) def _mouse_click_and_unhook(self, coords): """A timer callback to perform a mouse click and unhook""" click(coords=coords) # Give a time to process the mouse clicks by the hook self._sleep_and_unhook() def test_mouse_hook(self): """Test capturing a sequence of mouse clicks by hook""" # Get a safe point to click pt = self._get_safe_point_to_click() coords = [(pt.x, pt.y)] # Set a timer to perform a click and hook the mouse self.timer = Timer(self.wait_time, self._mouse_click_and_unhook, coords) self.timer.start() self.hook.hook(keyboard=False, mouse=True) # Continue here only when the hook will be removed by the timer self.assertEqual(len(self.mouse_events), 2) self.assertEqual(self.mouse_events[0].current_key, u'LButton') self.assertEqual(self.mouse_events[0].event_type, 'key down') self.assertEqual(self.mouse_events[0].mouse_x, pt.x) self.assertEqual(self.mouse_events[0].mouse_y, pt.y) self.assertEqual(self.mouse_events[1].current_key, u'LButton') self.assertEqual(self.mouse_events[1].event_type, 'key up') self.assertEqual(self.mouse_events[1].mouse_x, pt.x) self.assertEqual(self.mouse_events[1].mouse_y, pt.y)
class Win32HooksWithMocksTests(unittest.TestCase): """Unit tests for the Win32Hook class with mocks for low level dependencies""" def setUp(self): """Set some data and ensure the application is in the state we want""" self.hook = Hook() # Save pointers to original system calls before mocking self.CallNextHookEx = windll.user32.CallNextHookEx self.PeekMessageW = windll.user32.PeekMessageW self.TranslateMessage = windll.user32.TranslateMessage self.DispatchMessageW = windll.user32.DispatchMessageW self.atexit_register = atexit.register self.sys_exit = sys.exit self.fake_kbhook_id = 22 self.fake_mousehook_id = 33 def tearDown(self): """Cleanups after finishing a test""" self.hook.stop() # Restore the pointers to original system calls after mocking windll.user32.CallNextHookEx = self.CallNextHookEx windll.user32.PeekMessageW = self.PeekMessageW windll.user32.TranslateMessage = self.TranslateMessage windll.user32.DispatchMessageW = self.DispatchMessageW atexit.register = self.atexit_register sys.exit = self.sys_exit def test_none_hook_handler(self): """Test running a hook without a handler The next hook in chain still should be called Simulate an odd situation when we got a hook ID (a hook is inserted) but a handler for the hook processing wasn't supplied by a user """ self.hook.keyboard_id = self.fake_kbhook_id self.hook.mouse_id = self.fake_mousehook_id self.hook.handler = None # replace the system API with a mock object windll.user32.CallNextHookEx = mock.Mock(return_value=0) # prepare arguments for _keyboard_ll_hdl call kbd = win32structures.KBDLLHOOKSTRUCT(0, 0, 0, 0, 0) res = self.hook._keyboard_ll_hdl(-1, 3, id(kbd)) windll.user32.CallNextHookEx.assert_called_with( self.fake_kbhook_id, -1, 3, id(kbd)) self.assertEqual(res, 0) # Setup a fresh mock object and arguments for _mouse_ll_hdl call windll.user32.CallNextHookEx = mock.Mock(return_value=0) mouse = win32structures.MSLLHOOKSTRUCT((11, 12), 0, 0, 0, 0) res = self.hook._mouse_ll_hdl(-1, 3, id(mouse)) self.assertEqual(res, 0) windll.user32.CallNextHookEx.assert_called_with( self.fake_mousehook_id, -1, 3, id(mouse)) def test_keyboard_hook_exception(self): """Test handling an exception in a keyboard hook""" self.hook.handler = _on_hook_event_with_exception windll.user32.CallNextHookEx = mock.Mock(return_value=0) kbd = win32structures.KBDLLHOOKSTRUCT(0, 0, 0, 0, 0) self.hook.keyboard_id = self.fake_kbhook_id # Verify CallNextHookEx is called even if there is an exception is raised self.assertRaises(ValueError, self.hook._keyboard_ll_hdl, -1, 3, id(kbd)) windll.user32.CallNextHookEx.assert_called() windll.user32.CallNextHookEx.assert_called_with( self.fake_kbhook_id, -1, 3, id(kbd)) self.assertRaises(ValueError, self.hook._keyboard_ll_hdl, 0, 3, id(kbd)) windll.user32.CallNextHookEx.assert_called() windll.user32.CallNextHookEx.assert_called_with( self.fake_kbhook_id, 0, 3, id(kbd)) def test_mouse_hook_exception(self): """Test handling an exception in a mouse hook""" self.hook.handler = _on_hook_event_with_exception windll.user32.CallNextHookEx = mock.Mock(return_value=0) mouse = win32structures.MSLLHOOKSTRUCT((11, 12), 0, 0, 0, 0) self.hook.mouse_id = self.fake_mousehook_id # Verify CallNextHookEx is called even if there is an exception is raised self.assertRaises(ValueError, self.hook._mouse_ll_hdl, -1, 3, id(mouse)) windll.user32.CallNextHookEx.assert_called() windll.user32.CallNextHookEx.assert_called_with( self.fake_mousehook_id, -1, 3, id(mouse)) self.assertRaises(ValueError, self.hook._mouse_ll_hdl, 0, 3, id(mouse)) windll.user32.CallNextHookEx.assert_called() windll.user32.CallNextHookEx.assert_called_with( self.fake_mousehook_id, 0, 3, id(mouse)) @mock.patch.object(Hook, '_process_win_msgs') @mock.patch.object(Hook, 'is_hooked') def test_listen_loop(self, mock_is_hooked, mock_process_msgs): """Test running the main events loop""" atexit.register = mock.Mock(return_value=0) mock_is_hooked.side_effect = [1, 0] # exit at a second loop mock_process_msgs.return_value = 0 # mock hook IDs self.hook.keyboard_id = self.fake_kbhook_id self.hook.mouse_id = self.fake_mousehook_id # run the events loop self.hook.listen() # verify atexit.register calls atexit.register.assert_called() self.assertEqual(len(atexit.register.mock_calls), 2) name, args, kwargs = atexit.register.mock_calls[0] self.assertEqual(args[1], self.fake_kbhook_id) name, args, kwargs = atexit.register.mock_calls[1] self.assertEqual(args[1], self.fake_mousehook_id) # verify is_hooked method calls mock_is_hooked.assert_called() self.assertEqual(len(mock_is_hooked.mock_calls), 2) # verify _process_win_msgs method has been called mock_process_msgs.assert_called() self.assertEqual(len(mock_process_msgs.mock_calls), 1) @mock.patch.object(Hook, 'stop') def test_process_win_msg(self, mock_stop): """Test Hook._process_win_msgs""" # Mock external API windll.user32.PeekMessageW = mock.Mock(side_effect=[1, 0]) windll.user32.TranslateMessage = mock.Mock() windll.user32.DispatchMessageW = mock.Mock() # Test processing the normal messages self.hook._process_win_msgs() windll.user32.PeekMessageW.assert_called() windll.user32.TranslateMessage.assert_called() windll.user32.DispatchMessageW.assert_called() # Test processing WM_QUIT def side_effect(*args): """Emulate reception of WM_QUIT""" args[0].contents.message = win32con.WM_QUIT return 1 windll.user32.PeekMessageW = mock.Mock(side_effect=side_effect) self.assertRaises(SystemExit, self.hook._process_win_msgs) mock_stop.assert_called_once() def test_is_hooked(self): """Verify Hook.is_hooked method""" self.assertEqual(self.hook.is_hooked(), False) self.hook.mouse_is_hook = True self.assertEqual(self.hook.is_hooked(), True) self.hook.mouse_is_hook = False self.assertEqual(self.hook.is_hooked(), False) self.hook.keyboard_is_hook = True self.assertEqual(self.hook.is_hooked(), True) self.hook.keyboard_is_hook = False self.assertEqual(self.hook.is_hooked(), False) self.hook.hook(mouse=False, keyboard=False) self.assertEqual(self.hook.is_hooked(), False)
"""Callback for keyboard and mouse events""" if isinstance(args, KeyboardEvent): if args.current_key == 'A' and args.event_type == 'key down' and 'Lcontrol' in args.pressed_key: print("Ctrl + A was pressed") if args.current_key == 'K' and args.event_type == 'key down': print("K was pressed") if args.current_key == 'M' and args.event_type == 'key down' and 'U' in args.pressed_key: hk.unhook_mouse() print("Unhook mouse") if args.current_key == 'K' and args.event_type == 'key down' and 'U' in args.pressed_key: hk.unhook_keyboard() print("Unhook keyboard") if isinstance(args, MouseEvent): if args.current_key == 'RButton' and args.event_type == 'key down': print("Right button pressed") if args.current_key == 'WheelButton' and args.event_type == 'key down': print("Wheel button pressed") hk = Hook() hk.handler = on_event main_thread_id = win32api.GetCurrentThreadId() t = Timer(5.0, on_timer) # Quit after 5 seconds t.start() hk.hook(keyboard=True, mouse=True)
def run(self): hk = Hook() hk.handler = self.handleEvents hk.hook(keyboard=True, mouse=True)
# def handleEvents(args): # global down # if isinstance(args, MouseEvent): # if args.current_key == 'LButton' and args.event_type == 'key up': # keyboard.press_and_release('ctrl+c') # if isinstance(args, KeyboardEvent): # if 'control' in args.current_key and args.event_type == 'key down': # down = True # if 'control' in args.current_key and args.event_type == 'key up': # down = False # if args.current_key == 'C' and down: # print(1) # def onClipboardChanged() # data = clipboard.mimeData() # if data.hasText(): # print(data.text()) # app = QApplication([]) # clipboard = app.clipboard() # clipboard.dataChanged.connect(onClipboardChanged) if __name__ == '__main__': print('no config.') hk = Hook() hk.handler = handleEvents hk.hook(keyboard=True, mouse=True)
def __main__() -> None: hook = Hook() hook.handler = on_event hook.hook(keyboard=True, mouse=True) hook.listen()
class Win32HooksTests(unittest.TestCase): """Unit tests for the Win32Hook class""" def setUp(self): """Set some data and ensure the application is in the state we want""" self.logger = pywinauto.actionlogger.ActionLogger() self.hook = Hook() self.hook.handler = self._on_hook_event self.wait_time = 0.4 self.short_wait_time = self.wait_time / 4.0 self.timer = None self.keybd_events = [] self.mouse_events = [] self.app = None # prevent capturing keyboard keys when launching a test manually time.sleep(self.short_wait_time) def tearDown(self): """Close all hooks after tests""" self.keybd_events = [] self.mouse_events = [] if self.timer: self.timer.cancel() self.hook.stop() if self.app: self.app.kill() def _get_safe_point_to_click(self): """Run notepad.exe to have a safe area for mouse clicks""" mfc_samples_folder = os.path.join( os.path.dirname(__file__), r"..\..\apps\MFC_samples") if is_x64_Python(): mfc_samples_folder = os.path.join(mfc_samples_folder, 'x64') sample_exe = os.path.join(mfc_samples_folder, "CmnCtrl1.exe") self.app = Application() self.app.start(sample_exe) self.app.CommonControlsSample.wait("ready") return self.app.CommonControlsSample.rectangle().mid_point() def _sleep_and_unhook(self): """A helper to remove all hooks after a pause""" time.sleep(self.short_wait_time) self.hook.stop() def trace(self, msg, *args): """Log the specified message""" self.logger.log(msg.format(*args)) def _on_hook_event(self, args): """Callback for keyboard events""" if isinstance(args, KeyboardEvent): self.trace( "Win32HooksTests::_on_hook_event got KeyboardEvent: key={0} type={1}", args.current_key, args.event_type) self.keybd_events.append(args) elif isinstance(args, MouseEvent): self.trace( "Win32HooksTests::_on_hook_event got MouseEvent: key={0} type={1}", args.current_key, args.event_type) self.mouse_events.append(args) def _type_keys_and_unhook(self, key_strokes): """A timer callback to type key strokes and unhook""" send_keys(key_strokes) # Give a time to process the keys by the hook self._sleep_and_unhook() def test_keyboard_hook_unicode_sequence(self): """Test capturing a sequence of unicode keystrokes by a keyboard hook""" keys = u'uk' self.timer = Timer(self.wait_time, self._type_keys_and_unhook, [keys]) self.timer.start() self.hook.hook(keyboard=True, mouse=False) # Continue here only when the hook will be removed by the timer _delete_keys_from_terminal(keys) self.assertEqual(len(self.keybd_events), 4) self.assertEqual(self.keybd_events[0].current_key, u'u') self.assertEqual(self.keybd_events[0].event_type, 'key down') self.assertEqual(len(self.keybd_events[0].pressed_key), 0) self.assertEqual(self.keybd_events[1].current_key, u'u') self.assertEqual(self.keybd_events[1].event_type, 'key up') self.assertEqual(len(self.keybd_events[1].pressed_key), 0) self.assertEqual(self.keybd_events[2].current_key, u'k') self.assertEqual(self.keybd_events[2].event_type, 'key down') self.assertEqual(len(self.keybd_events[2].pressed_key), 0) self.assertEqual(self.keybd_events[3].current_key, u'k') self.assertEqual(self.keybd_events[3].event_type, 'key up') self.assertEqual(len(self.keybd_events[3].pressed_key), 0) def test_keyboard_hook_parallel_pressed_keys(self): """Test capturing parallel pressed keys by a keyboard hook""" keys = u'+a' self.timer = Timer(self.wait_time, self._type_keys_and_unhook, [keys]) self.timer.start() self.hook.hook(keyboard=True, mouse=False) # Continue here only when the hook will be removed by the timer _delete_keys_from_terminal(keys) self.assertEqual(len(self.keybd_events), 4) self.assertEqual(self.keybd_events[0].current_key, u'Lshift') self.assertEqual(self.keybd_events[0].event_type, 'key down') self.assertEqual(len(self.keybd_events[0].pressed_key), 0) self.assertEqual(self.keybd_events[1].current_key, u'A') self.assertEqual(self.keybd_events[1].event_type, 'key down') self.assertEqual(len(self.keybd_events[1].pressed_key), 0) self.assertEqual(self.keybd_events[2].current_key, u'A') self.assertEqual(self.keybd_events[2].event_type, 'key up') self.assertEqual(len(self.keybd_events[2].pressed_key), 0) self.assertEqual(self.keybd_events[3].current_key, u'Lshift') self.assertEqual(self.keybd_events[3].event_type, 'key up') self.assertEqual(len(self.keybd_events[3].pressed_key), 0) def _mouse_click_and_unhook(self, coords): """A timer callback to perform a mouse click and unhook""" click(coords=coords) # Give a time to process the mouse clicks by the hook self._sleep_and_unhook() def test_mouse_hook(self): """Test capturing a sequence of mouse clicks by hook""" # Get a safe point to click pt = self._get_safe_point_to_click() coords = [(pt.x, pt.y)] # Set a timer to perform a click and hook the mouse self.timer = Timer(self.wait_time, self._mouse_click_and_unhook, coords) self.timer.start() self.hook.hook(keyboard=False, mouse=True) # Continue here only when the hook will be removed by the timer self.assertEqual(len(self.mouse_events), 2) self.assertEqual(self.mouse_events[0].current_key, u'LButton') self.assertEqual(self.mouse_events[0].event_type, 'key down') self.assertEqual(self.mouse_events[0].mouse_x, pt.x) self.assertEqual(self.mouse_events[0].mouse_y, pt.y) self.assertEqual(self.mouse_events[1].current_key, u'LButton') self.assertEqual(self.mouse_events[1].event_type, 'key up') self.assertEqual(self.mouse_events[1].mouse_x, pt.x) self.assertEqual(self.mouse_events[1].mouse_y, pt.y)
class Win32HooksWithMocksTests(unittest.TestCase): """Unit tests for the Win32Hook class with mocks for low level dependencies""" def setUp(self): """Set some data and ensure the application is in the state we want""" self.hook = Hook() # Save pointers to original system calls before mocking self.CallNextHookEx = windll.user32.CallNextHookEx self.PeekMessageW = windll.user32.PeekMessageW self.TranslateMessage = windll.user32.TranslateMessage self.DispatchMessageW = windll.user32.DispatchMessageW self.atexit_register = atexit.register self.sys_exit = sys.exit self.fake_kbhook_id = 22 self.fake_mousehook_id = 33 def tearDown(self): """Cleanups after finishing a test""" self.hook.stop() # Restore the pointers to original system calls after mocking windll.user32.CallNextHookEx = self.CallNextHookEx windll.user32.PeekMessageW = self.PeekMessageW windll.user32.TranslateMessage = self.TranslateMessage windll.user32.DispatchMessageW = self.DispatchMessageW atexit.register = self.atexit_register sys.exit = self.sys_exit def test_none_hook_handler(self): """Test running a hook without a handler The next hook in chain still should be called Simulate an odd situation when we got a hook ID (a hook is inserted) but a handler for the hook processing wasn't supplied by a user """ self.hook.keyboard_id = self.fake_kbhook_id self.hook.mouse_id = self.fake_mousehook_id self.hook.handler = None # replace the system API with a mock object windll.user32.CallNextHookEx = mock.Mock(return_value=0) # prepare arguments for _keyboard_ll_hdl call kbd = win32structures.KBDLLHOOKSTRUCT(0, 0, 0, 0, 0) res = self.hook._keyboard_ll_hdl(-1, 3, id(kbd)) windll.user32.CallNextHookEx.assert_called_with(self.fake_kbhook_id, -1, 3, id(kbd)) self.assertEqual(res, 0) # Setup a fresh mock object and arguments for _mouse_ll_hdl call windll.user32.CallNextHookEx = mock.Mock(return_value=0) mouse = win32structures.MSLLHOOKSTRUCT((11, 12), 0, 0, 0, 0) res = self.hook._mouse_ll_hdl(-1, 3, id(mouse)) self.assertEqual(res, 0) windll.user32.CallNextHookEx.assert_called_with(self.fake_mousehook_id, -1, 3, id(mouse)) def test_keyboard_hook_exception(self): """Test handling an exception in a keyboard hook""" self.hook.handler = _on_hook_event_with_exception windll.user32.CallNextHookEx = mock.Mock(return_value=0) kbd = win32structures.KBDLLHOOKSTRUCT(0, 0, 0, 0, 0) self.hook.keyboard_id = self.fake_kbhook_id # Verify CallNextHookEx is called even if there is an exception is raised self.assertRaises(ValueError, self.hook._keyboard_ll_hdl, -1, 3, id(kbd)) windll.user32.CallNextHookEx.assert_called() windll.user32.CallNextHookEx.assert_called_with(self.fake_kbhook_id, -1, 3, id(kbd)) self.assertRaises(ValueError, self.hook._keyboard_ll_hdl, 0, 3, id(kbd)) windll.user32.CallNextHookEx.assert_called() windll.user32.CallNextHookEx.assert_called_with(self.fake_kbhook_id, 0, 3, id(kbd)) def test_mouse_hook_exception(self): """Test handling an exception in a mouse hook""" self.hook.handler = _on_hook_event_with_exception windll.user32.CallNextHookEx = mock.Mock(return_value=0) mouse = win32structures.MSLLHOOKSTRUCT((11, 12), 0, 0, 0, 0) self.hook.mouse_id = self.fake_mousehook_id # Verify CallNextHookEx is called even if there is an exception is raised self.assertRaises(ValueError, self.hook._mouse_ll_hdl, -1, 3, id(mouse)) windll.user32.CallNextHookEx.assert_called() windll.user32.CallNextHookEx.assert_called_with(self.fake_mousehook_id, -1, 3, id(mouse)) self.assertRaises(ValueError, self.hook._mouse_ll_hdl, 0, 3, id(mouse)) windll.user32.CallNextHookEx.assert_called() windll.user32.CallNextHookEx.assert_called_with(self.fake_mousehook_id, 0, 3, id(mouse)) @mock.patch.object(Hook, '_process_win_msgs') @mock.patch.object(Hook, 'is_hooked') def test_listen_loop(self, mock_is_hooked, mock_process_msgs): """Test running the main events loop""" atexit.register = mock.Mock(return_value=0) mock_is_hooked.side_effect = [1, 0] # exit at a second loop mock_process_msgs.return_value = 0 # mock hook IDs self.hook.keyboard_id = self.fake_kbhook_id self.hook.mouse_id = self.fake_mousehook_id # run the events loop self.hook.listen() # verify atexit.register calls atexit.register.assert_called() self.assertEqual(len(atexit.register.mock_calls), 2) name, args, kwargs = atexit.register.mock_calls[0] self.assertEqual(args[1], self.fake_kbhook_id) name, args, kwargs = atexit.register.mock_calls[1] self.assertEqual(args[1], self.fake_mousehook_id) # verify is_hooked method calls mock_is_hooked.assert_called() self.assertEqual(len(mock_is_hooked.mock_calls), 2) # verify _process_win_msgs method has been called mock_process_msgs.assert_called() self.assertEqual(len(mock_process_msgs.mock_calls), 1) @mock.patch.object(Hook, 'stop') def test_process_win_msg(self, mock_stop): """Test Hook._process_win_msgs""" # Mock external API windll.user32.PeekMessageW = mock.Mock(side_effect=[1, 0]) windll.user32.TranslateMessage = mock.Mock() windll.user32.DispatchMessageW = mock.Mock() # Test processing the normal messages self.hook._process_win_msgs() windll.user32.PeekMessageW.assert_called() windll.user32.TranslateMessage.assert_called() windll.user32.DispatchMessageW.assert_called() # Test processing WM_QUIT def side_effect(*args): """Emulate reception of WM_QUIT""" args[0].contents.message = win32con.WM_QUIT return 1 windll.user32.PeekMessageW = mock.Mock(side_effect=side_effect) self.assertRaises(SystemExit, self.hook._process_win_msgs) mock_stop.assert_called_once() def test_is_hooked(self): """Verify Hook.is_hooked method""" self.assertEqual(self.hook.is_hooked(), False) self.hook.mouse_is_hook = True self.assertEqual(self.hook.is_hooked(), True) self.hook.mouse_is_hook = False self.assertEqual(self.hook.is_hooked(), False) self.hook.keyboard_is_hook = True self.assertEqual(self.hook.is_hooked(), True) self.hook.keyboard_is_hook = False self.assertEqual(self.hook.is_hooked(), False) self.hook.hook(mouse=False, keyboard=False) self.assertEqual(self.hook.is_hooked(), False)
def on_event(args): """Callback for keyboard and mouse events""" if isinstance(args, KeyboardEvent): if args.current_key == 'A' and args.event_type == 'key down' and 'Lcontrol' in args.pressed_key: print("Ctrl + A was pressed"); if args.current_key == 'K' and args.event_type == 'key down': print("K was pressed"); if args.current_key == 'M' and args.event_type == 'key down' and 'U' in args.pressed_key: hk.unhook_mouse() print("Unhook mouse") if args.current_key == 'K' and args.event_type == 'key down' and 'U' in args.pressed_key: hk.unhook_keyboard() print("Unhook keyboard") if isinstance(args, MouseEvent): if args.current_key == 'RButton' and args.event_type == 'key down': print ("Right button pressed") if args.current_key == 'WheelButton' and args.event_type == 'key down': print("Wheel button pressed") hk = Hook() hk.handler = on_event main_thread_id = win32api.GetCurrentThreadId() t = Timer(5.0, on_timer) # Quit after 5 seconds t.start() hk.hook(keyboard=True, mouse=True)