Python 游戏自动化脚本:后台键鼠操作实现原理
概述
在游戏自动化开发中,后台键鼠操作是一项核心技能。通过模拟人工操作,我们可以让游戏窗口在后台运行脚本,同时处理其他任务,甚至实现多开同步控制。与前台操作不同,后台操作不占用系统焦点,能够避免被检测为异常输入,但需要深入理解 Windows 消息机制。
基本原理
Windows 系统中的输入操作本质上是向特定窗口发送消息。虽然 SendInput 函数功能强大,但它通常只能对前台窗口生效。要实现后台操作,我们需要利用 PostMessageW 或 SendMessage 函数直接向目标窗口的消息队列投递消息。
- PostMessageW:将消息放入目标线程的消息队列后立即返回,不等待消息处理结果。适合大多数非阻塞场景。
- SendMessage:直接调用窗口过程处理消息,直到处理完成才返回。适合需要同步结果的场景。
本文主要讲解使用 PostMessageW 进行后台模拟的实现方式。
PostMessageW 声明
BOOL PostMessageW(
HWND hWnd,
UINT Msg,
WPARAM wParam,
LPARAM lParam
);
- hWnd:目标窗口句柄(Handle)。
- Msg:消息 ID,如键盘按下、鼠标移动等。
- wParam:取决于具体消息的参数。
- lParam:取决于具体消息的参数,通常包含坐标或按键状态。
键盘消息实现
键盘操作主要涉及两个消息:
- WM_KEYDOWN (0x100):按键按下。
- WM_KEYUP (0x101):按键释放。
虚拟按键码映射
Windows 使用虚拟键码(Virtual Key Code)来标识按键。对于特殊按键(如回车、方向键),有固定的十六进制值;对于普通字符,可以通过 VkKeyScanA 获取。
from ctypes import windll
from ctypes.wintypes import HWND
import string
import time
# 加载用户32库
PostMessageW = windll.user32.PostMessageW
MapVirtualKeyW = windll.user32.MapVirtualKeyW
VkKeyScanA = windll.user32.VkKeyScanA
# 定义常用消息常量
WM_KEYDOWN = 0x100
WM_KEYUP = 0x101
# 虚拟按键码字典
VkCode = {
"back": 0x08, "tab": 0x09, "return": , : ,
: , : , : , : ,
: , : , : , : ,
: , : , : , : ,
: , : , : , : ,
: , : , : , : ,
: , : , : , : ,
: , : , : , : ,
: , : , : , : ,
: , : , : , : ,
: , : , : , : , : ,
: , : , : , : , : ,
: , : , : , : ,
: , : , : , :
}
() -> :
(key) == key string.printable:
VkKeyScanA((key)) &
:
VkCode.get(key, )
():
vk_code = get_virtual_keycode(key)
scan_code = MapVirtualKeyW(vk_code, )
lparam = (scan_code << ) |
PostMessageW(handle, WM_KEYDOWN, vk_code, lparam)
():
vk_code = get_virtual_keycode(key)
scan_code = MapVirtualKeyW(vk_code, )
lparam = (scan_code << ) |
PostMessageW(handle, WM_KEYUP, vk_code, lparam)
__name__ == :
sys
windll.shell32.IsUserAnAdmin():
windll.shell32.ShellExecuteW(, , sys.executable, __file__, , )
sys.exit()
win32gui
handle = windll.user32.FindWindowW(, )
handle:
classname = win32gui.GetClassName(handle)
classname == :
mainhandle = win32gui.FindWindowEx(handle, , , )
renderhandle = win32gui.FindWindowEx(mainhandle, , , )
clickhandle = renderhandle
:
clickhandle = handle
()
key_down(clickhandle, )
time.sleep()
key_up(clickhandle, )
:
()


