技术求助:如何通过Python实现后台窗口的鼠标/键盘模拟点击,搭建Metin2多开Farming Bot
Hey there! Let's work through this Metin2 bot challenge you're dealing with—background window automation for games can be finicky, especially since many older games (like Metin2) don't play nice with standard Windows input messages out of the box. Let's break down why your current code isn't working and share some practical fixes.
First, why your pywin32 code failed
There are two common culprits here:
- Wrong window handle: The main "Client" window is often just a border container—actual game input is handled by a child window (the DirectX/OpenGL render surface). Sending messages to the parent window won't trigger any in-game actions.
- Coordinate mismatch:
SendMessageexpects coordinates relative to the window's client area, not absolute screen coordinates. If you're passing screen positions directly, the game won't register the click in the right spot. - Input handling bypass: Many games use DirectInput instead of processing standard
WM_*messages, so sendingWM_LBUTTONDOWNmight be ignored entirely.
Solution 1: Use pywinauto (easiest for beginners)
Pywinauto is built specifically for Windows GUI automation and handles a lot of the low-level window logic for you. It works with background windows and doesn't hijack your real mouse/keyboard.
First, install it:
pip install pywinauto
Then try this code to interact with your Metin2 windows:
from pywinauto import Application import time # Connect to all Metin2 windows (matches any window with "Client" in the title) apps = Application().connect(title_re="Client.*", backend="win32") # Iterate over each connected window (for multi-client support) for window in apps.windows(): print(f"Interacting with window: {window.window_text()}") # Simulate a left click at (100, 100) in the window's client area window.click_input(coords=(100, 100), button="left") # Simulate holding SPACE for 2 seconds (for riding/attacking) window.type_keys("{SPACE down}") time.sleep(2) window.type_keys("{SPACE up}")
Notes for pywinauto:
- Use the
win32backend (default isuia, which works better for modern apps but not always for games). - If your windows have exact titles (like "Client 1", "Client 2"), use
title="Client 1"instead oftitle_re. - Run your script as administrator to avoid permission issues with the game window.
Solution 2: Fix your pywin32 code (more manual, but gives you control)
If you want to stick with pywin32, you need to target the correct child window and fix your coordinates. Here's how:
Use Spy++ to find the right child window:
- Open Spy++ (included with Windows SDK, or download it separately)
- Use the "Find Window" tool to pick your Metin2 window, then look at the child windows—you'll see one that's labeled something like "DirectX Window" or has no visible text. That's the one you need to send messages to.
Updated pywin32 code:
import win32gui import win32api import win32con import time def get_game_window_handle(main_window_title="Client"): # Get the main window handle main_hwnd = win32gui.FindWindow(None, main_window_title) if not main_hwnd: return None # Enumerate child windows to find the game render surface child_hwnds = [] def enum_child_callback(hwnd, extra): # Filter out invisible windows (adjust this based on your Spy++ findings) if win32gui.IsWindowVisible(hwnd): extra.append(hwnd) win32gui.EnumChildWindows(main_hwnd, enum_child_callback, child_hwnds) # Return the first visible child window (adjust index if needed) return child_hwnds[0] if child_hwnds else main_hwnd def send_background_click(hwnd, client_x, client_y): # Send left mouse down/up messages to the target window l_param = win32api.MAKELONG(client_x, client_y) win32api.SendMessage(hwnd, win32con.WM_LBUTTONDOWN, win32con.MK_LBUTTON, l_param) time.sleep(0.05) # Small delay to simulate real click win32api.SendMessage(hwnd, win32con.WM_LBUTTONUP, 0, l_param) def send_background_key(hwnd, key_code, hold_duration=1): # Send key down/up messages win32api.SendMessage(hwnd, win32con.WM_KEYDOWN, key_code, 0) time.sleep(hold_duration) win32api.SendMessage(hwnd, win32con.WM_KEYUP, key_code, 0) # Usage example game_hwnd = get_game_window_handle() if game_hwnd: print(f"Found game window: {game_hwnd}") # Click at (100, 100) in the game's client area send_background_click(game_hwnd, 100, 100) # Hold SPACE for 2 seconds send_background_key(game_hwnd, win32con.VK_SPACE, 2) else: print("Could not find Metin2 window!")
Bonus: Alternative tools/languages
If Python still gives you trouble, consider these options:
- AutoHotkey: Great for game automation, has built-in support for sending messages to background windows and handling multi-client setups. It's easier for simple scripts than Python in some cases.
- C# with Windows Forms/Win32 API: More powerful for low-level input, but steeper learning curve. Libraries like
InputSimulatorcan help with background input.
Important Notes
- Anti-cheat: Even though Metin2 is older, some servers have anti-bot measures. Be careful to avoid triggering bans—don't make your bot's actions too repetitive or human-impossible.
- Admin rights: Always run your script with the same privilege level as the game (if the game runs as admin, your script should too).
内容的提问来源于stack exchange,提问作者NewInProgramming




