Package: winput
winputCapture and send keyboard and mouse input on Windowswinputis a smallextensionthat gives you the ability tocaptureandsendanykeyboard and mouse input.It does this by providing asimple interfacetouser32.dllTiny documentationAbout winputwinput must not be used to record the user's input without their consent!winputis supposed toreplacethe outdated extensionPyHook.Using winputTo install winput you can use thePyPI:pip install winputTo use winput in a script, you have to import the packagewinputusingimport winputor a wildcard import:from winput import *Capturing mouse inputThere are two ways you can get input from the mouse.1. You can get the current position of the mouse cursor usingget_mouse_pos() -> (x, y)2. You can hook onto the Windows message system to receive an Event every timethe state of the mouse changes:hook_mouse( callback_function )The function will be supplied with aMouseEventas it's only argument.class MouseEvent:
    position        # [length-2-tuple] the screen coordinates at which the event occured
    action          # [int] which type of event occured - can be any of the mouse-wParams (see below)
    time            # [int] time in ms since system startup
    additional_data # [int] information for specific mouse events (which X-Button, amount of mouse-wheel-movement)
    type            # [string] = "MouseEvent"Youhave to run a message loopto use a hook! (see[Running a message loop]below)Remember to unhook when you're done capturing by using:unhook_mouse()The following mouse-wParams exist:WM_MOUSEMOVE    = 0x0200 # the mouse has been moved

WM_LBUTTONDOWN  = 0x0201 # left mouse button pressed
WM_LBTTONUP     = 0x0202 # left mouse button released

WM_RBUTTONDOWN  = 0x0204 # right mouse button pressed
WM_RBUTTONUP    = 0x0205 # right mouse button released

WM_MBUTTONDOWN  = 0x0207 # middle mouse button pressed
WM_MBUTTONUP    = 0x0208 # middle mouse button released

WM_MOUSEWHEEL   = 0x020A # mouse wheel moved
WM_MOUSEHWHEEL  = 0x020E # mouse wheel moved (horizontal)

WM_XBUTTONDOWN  = 0x020B # extra button pressed
WM_XBUTTONUP    = 0x020C # extra button releasedCapturing keyboard inputIf you want to monitor keyboard input you also have to hook onto the Windows message system.hook_keyboard( callback_function )The function will be supplied with aKeyboardEventas it's only argument.class KeyboardEvent:
    action  # [int] which type of event occured - can be any of the keyboard-wParams
    vkCode  # [int] virtual key code -- which key has been pressed
    time    # [int] time in ms since system startup
    type    # [string] = "KeyboardEvent"Youhave to run a message loopto use a hook! (seeRunning a message loopbelow)Again, remember to unhook when you're done capturing by using:unhook_keyboard()The following keyboard-wParams exist:WM_KEYDOWN      = 0x0100 # key pressed
WM_KEYUP        = 0x0101 # key released

WM_SYSKEYDOWN   = 0x0104 # system-key pressed
WM_SYSKEYUP     = 0x0105 # system-key releasedReturn values for callback functionsThe callback (hook) functions mentioned above are expected to return aflag.
The following flags exist:FlagValueMeaningWP_CONTINUE0x00Continue normallyWP_UNHOOK0x01Remove this hookWP_STOP0x02Stops the message loopWP_DONT_PASS_INPUT_ON0x04Does not call any other hooks (i.e. input isn't passed on to other programs)If the callback function returnsNone,WP_CONTINUEis assumed.WARNING:UsingWP_DONT_PASS_INPUT_ONwill also prevent the inputs to be passed on to Windows. If you do this for a mouse hook, the mouse willnot moveand you might loose control over your computer. Same goes for keyboard hooks. The keyboard events willnot be passed onto the rest of your system. You may loose control over your computer.Running a message loopIf you're using a hook, you have to keep updating the Windows messages.You can either do this by usingwait_messages()to enter an infinite message loop, which you can stop by callingstop()Or you can have your own loop that repeatedly (at least 100x per second) callsget_message()Virtual Key Codes (VK codes)Virtual key codes or vk_codes are numerical representations of given keys.To get a list of all virtual key codes, take a look overhere.All VK codes are members of the mainwinputmodule and the submodulewinput.vk_codes.If you want to import all the VK codes without performing a package-wide wildcard import, you can usefrom winput.vk_codes import *You can also convert the virtual key codes to a literal representation using a predefined dict.vk_code_dict.get(vk_code, "VK_UNKNOWN") -> stringSending mouse inputTo set the position of the mouse cursor, you can useset_mouse_pos(x, y)To make sure this also works with high DPI values, please use the DPI awareness functions below.To move the mouse cursor by a given amount, you can usemove_mouse(dx, dy)A mouse button can be pressed usingpress_mouse_button(mouse_button)and released usingrelease_mouse_button(mouse_button)or pressed and released usingclick_mouse_button(mouse_button)The following mouse buttons exist:LEFT_MOUSE_BUTTON   = LMB   = 1
RIGHT_MOUSE_BUTTON  = RMB   = 2
MIDDLE_MOUSE_BUTTON = MMB   = 4
EXTRA_MOUSE_BUTTON1 = XMB1  = 8
EXTRA_MOUSE_BUTTON2 = XMB2  = 16The mousewheel can be moved usingmove_mousewheel(amount[, horizontal = False])Sending keyboard inputTo press a key, you can usepress_key(vk_code)to release it, you can userelease_key(vk_code)and to press and release it, you can useclick_key(vk_code)DPI awarenessTo make the process running winput DPI aware, use the following function:set_DPI_aware(per_monitor=True)To get the DPI scaling factor for a given window handle (HWND), useget_window_scaling_factor(hwnd)ExampleCapturing the mouse and keyboardimportwinputdefmouse_callback(event):ifevent.action==winput.WM_LBUTTONDOWN:print("Left mouse button press at{}".format(event.position))defkeyboard_callback(event):ifevent.vkCode==winput.VK_ESCAPE:# quit on pressing escapereturnwinput.WP_STOP# alternatively you could also call:# winput.stop()print("Press escape to quit")# hook inputwinput.hook_mouse(mouse_callback)winput.hook_keyboard(keyboard_callback)# enter message loopwinput.wait_messages()# remove input hookwinput.unhook_mouse()winput.unhook_keyboard()Capturing keyboard without passthroughimportwinputdefkeyboard_callback(event:winput.KeyboardEvent)->int:ifevent.key==winput.VK_ESCAPE:print("quitting")returnwinput.WP_UNHOOK|winput.WP_STOPprint(winput.vk_code_dict.get(event.key,"VK_UNKNOWN"))returnwinput.WP_DONT_PASS_INPUT_ONwinput.hook_keyboard(keyboard_callback)winput.wait_messages()Sending inputimportwinputfromwinput.vk_codesimport*importtimedefslow_click(vk_code):# delay each keypress by 1/10 of a secondtime.sleep(0.1)winput.click_key(vk_code)# open the RUN menu (WIN + R)winput.press_key(VK_LWIN)winput.click_key(VK_R)winput.release_key(VK_LWIN)time.sleep(0.5)# enter "notepad.exe"slow_click(VK_N)slow_click(VK_O)slow_click(VK_T)slow_click(VK_E)slow_click(VK_P)slow_click(VK_A)slow_click(VK_D)slow_click(VK_OEM_PERIOD)slow_click(VK_E)slow_click(VK_X)slow_click(VK_E)slow_click(VK_RETURN)time.sleep(1)# enter "hello world"slow_click(VK_H)slow_click(VK_E)slow_click(VK_L)slow_click(VK_L)slow_click(VK_O)slow_click(VK_SPACE)slow_click(VK_W)slow_click(VK_O)slow_click(VK_R)slow_click(VK_L)slow_click(VK_D)