I am using win32gui to try and send key inputs to my minecraft window, to move my character even while the game is minimized / unfocused. It's supposed to send W for 1 second, release it, then do the same thing with A, wait 1 second and repeat. Instead it just presses W, then A and never releases them again. How can I fix this?
here is the code
import time
import win32gui
import win32con
def find_minecraft_window():
hwnd = None
def enum_windows_proc(inner_hwnd, lParam):
nonlocal hwnd
if "Minecraft" in win32gui.GetWindowText(inner_hwnd):
hwnd = inner_hwnd
return False
return True
try:
win32gui.EnumWindows(enum_windows_proc, None)
except Exception as e:
print(f"Exception during window enumeration: {e}")
return hwnd
def is_window_valid(hwnd):
return win32gui.IsWindow(hwnd)
def hold_key(hwnd, key, duration):
if not is_window_valid(hwnd):
raise ValueError("Invalid window handle")
try:
win32gui.SendMessage(hwnd, win32con.WM_KEYDOWN, key, 0)
time.sleep(duration)
win32gui.SendMessage(hwnd, win32con.WM_KEYUP, key, 0)
time.sleep(0.5) # Small delay to ensure the game registers the key release
except Exception as e:
print(f"Exception during key press: {e}")
def main():
print("Starting Minecraft key press script...")
hwnd = find_minecraft_window()
if hwnd is None:
print("Minecraft window not found!")
return
print(f"Minecraft window found: {hwnd}")
try:
while True:
# Validate window handle before each key press
if not is_window_valid(hwnd):
print("Window handle became invalid, trying to find Minecraft window again.")
hwnd = find_minecraft_window()
if hwnd is None:
print("Minecraft window not found!")
return
# hold 'W' for 2 seconds, then 'A' for 1 second
hold_key(hwnd, ord('1'), 1)
hold_key(hwnd, ord('2'), 1)
# Restart loop
time.sleep(1)
except KeyboardInterrupt:
print("Script stopped by user.")
if __name__ == "__main__":
main()
Following the documentation for WM_KEYUP
, the lParam field requires several bits to be set:
bits | meaning |
---|---|
0-15 | The repeat count ... The repeat count is always 1 for a WM_KEYUP message. |
... | ... |
30 | The previous key state. The value is always 1 for a WM_KEYUP message. |
31 | The transition state. The value is always 1 for a WM_KEYUP message. |
I cannot try this out right away, but something like this should set bits 1, 30, and 31 for lParam:
win32gui.SendMessage(hwnd, win32con.WM_KEYUP, key, (3<<30) + 1)