简化Python的Ctypes联合类型(仅保留Windows键盘事件代码)
Got it, let's fix this for you! The issue you're running into is that the original code probably relied on a union type to handle both mouse and keyboard inputs for the Windows SendInput API, but we can completely strip out all mouse-related code by restructuring how we define the input structures.
Here's the stripped-down, keyboard-only version of your script
This code removes all mouse-related classes/constants and only keeps what's needed to send keyboard presses:
import ctypes import time # Load only the necessary Windows API components user32 = ctypes.WinDLL('user32', use_last_error=True) # Keyboard-specific constants INPUT_KEYBOARD = 1 KEYEVENTF_KEYUP = 0x0002 # Define ONLY the keyboard input structure class KEYBDINPUT(ctypes.Structure): _fields_ = [ ("wVk", ctypes.c_ushort), # Virtual-key code ("wScan", ctypes.c_ushort), # Hardware scan code (we can leave this 0) ("dwFlags", ctypes.c_ulong), # Input flags ("time", ctypes.c_ulong), # Timestamp (unused here) ("dwExtraInfo", ctypes.POINTER(ctypes.c_ulong)) # Extra info (unused) ] # Define the INPUT structure to only hold keyboard data (no union needed!) class INPUT(ctypes.Structure): _fields_ = [ ("type", ctypes.c_ulong), # Mark this as a keyboard input ("ki", KEYBDINPUT) # Directly embed the keyboard input data ] def press_key(key_code): """Simulate pressing a key down""" input_down = INPUT() input_down.type = INPUT_KEYBOARD input_down.ki.wVk = key_code input_down.ki.dwFlags = 0 # No flags = key press user32.SendInput(1, ctypes.byref(input_down), ctypes.sizeof(INPUT)) def release_key(key_code): """Simulate releasing a key""" input_up = INPUT() input_up.type = INPUT_KEYBOARD input_up.ki.wVk = key_code input_up.ki.dwFlags = KEYEVENTF_KEYUP # Flag to signal key release user32.SendInput(1, ctypes.byref(input_up), ctypes.sizeof(INPUT)) def send_key(key_code): """Send a full key press (down + up)""" press_key(key_code) release_key(key_code) # Default to F15 (virtual key code 0x7E) DEFAULT_KEY = 0x7E def main(interval_seconds=5, key_code=DEFAULT_KEY): print(f"Starting to send key (0x{key_code:02X}) every {interval_seconds} seconds...") print("Press Ctrl+C to stop.") try: while True: send_key(key_code) print(f"Sent key at {time.strftime('%Y-%m-%d %H:%M:%S')}") time.sleep(interval_seconds) except KeyboardInterrupt: print("\nStopped.") if __name__ == "__main__": # Customize interval or key code here if needed (e.g., main(3, 0x7B) for F12 every 3s) main()
Why this works (and why your previous attempts failed)
When you removed the _INPUTunion and MOUSEINPUT before, you probably broke the memory layout that the SendInput API expects. The original union let the API read either mouse or keyboard data from the same memory space.
In this version:
- We've rewritten the
INPUTstructure to directly embed theKEYBDINPUTinstead of using a union. Since we only ever send keyboard inputs, thetypefield is always set toINPUT_KEYBOARD, which tells the API exactly how to interpret the data. - All mouse-related constants, classes, and logic are completely removed—no extra bloat.
- The
SendInputcall works exactly as before because the memory layout of our customINPUTstructure matches what the API expects for keyboard inputs.
Quick notes
- To use a different key, replace
DEFAULT_KEYwith the correct virtual key code (e.g., 0x70 for F1, 0x41 for 'A'). - The script runs until you press Ctrl+C to stop it.
内容的提问来源于stack exchange,提问作者Jean-Francois T.
相关产品推荐
相关产品推荐

