Files
AUTO-MAS-test/app/utils/device_manager/postMessage.py
2025-09-27 03:32:43 +08:00

157 lines
5.2 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import ctypes
import asyncio
# 加载 user32.dll
user32 = ctypes.windll.user32
# Windows 消息常量
WM_KEYDOWN = 0x0100
WM_KEYUP = 0x0101
async def post_key_to_hwnd(hwnd: int, vk_code: int) -> bool:
"""
使用 PostMessage 向指定窗口句柄发送一个完整的按键(按下 + 释放)。
!由于 PostMessage 是异步的,并不能保证按键一定被处理。
参数:
hwnd (int): 目标窗口句柄
vk_code (int): 虚拟键码
注意:
- 此函数不检查 hwnd 是否有效,也不等待消息处理(异步)。
- 如果 hwnd 无效PostMessage 会静默失败。
"""
if hwnd <= 0:
raise ValueError("hwnd 必须是正整数")
if not (0 <= vk_code <= 0xFFFF):
raise ValueError("vk_code 必须是有效的虚拟键码0~65535")
user32.PostMessageW(hwnd, WM_KEYDOWN, vk_code, 0)
user32.PostMessageW(hwnd, WM_KEYUP, vk_code, 0)
return True
async def send_key_to_hwnd_sync(hwnd: int, vk_code: int) -> bool:
"""
使用 SendMessage 向指定窗口句柄同步发送一个完整的按键(按下 + 释放)。
参数:
hwnd (int): 目标窗口句柄
vk_code (int): 虚拟键码
返回:
bool:
- 对于 SendMessage返回值是目标窗口过程WindowProc对消息的返回值。
- 通常非零表示成功,但具体含义由目标窗口定义。
- 如果 hwnd 无效,会返回 0。
注意:
- 此调用是**同步阻塞**的:当前线程会等待目标窗口处理完消息才返回。
- 如果目标窗口无响应hung当前程序也会卡住
"""
if hwnd <= 0:
raise ValueError("hwnd 必须是正整数")
if not (0 <= vk_code <= 0xFFFF):
raise ValueError("vk_code 必须是有效的虚拟键码0~65535")
# 发送 WM_KEYDOWN
result_down = user32.SendMessageW(hwnd, WM_KEYDOWN, vk_code, 0)
# 发送 WM_KEYUP
result_up = user32.SendMessageW(hwnd, WM_KEYUP, vk_code, 0)
return bool(result_down and result_up)
async def post_keys_to_hwnd(
hwnd: int, vk_codes: list[int], hold_time: float = 0.05
) -> bool:
"""
使用 PostMessage 向指定窗口句柄同时发送多个按键
!由于 PostMessage 是异步的,并不能保证按键一定被处理。
参数:
hwnd (int): 目标窗口句柄
vk_codes (List[int]): 虚拟键码列表
hold_time (float): 按键保持时间(秒),默认 0.05 秒
返回:
bool: 总是返回 TruePostMessage 不提供错误反馈)
注意:
- 此函数不检查 hwnd 是否有效,也不等待消息处理(异步)。
- 如果 hwnd 无效PostMessage 会静默失败。
- 按键顺序:先按下所有键,等待,然后按相反顺序释放所有键。
"""
if hwnd <= 0:
raise ValueError("hwnd 必须是正整数")
if not vk_codes:
raise ValueError("vk_codes 不能为空")
# 验证所有虚拟键码
for vk_code in vk_codes:
if not (0 <= vk_code <= 0xFFFF):
raise ValueError(f"vk_code {vk_code} 必须是有效的虚拟键码0~65535")
# 按下所有按键
for vk_code in vk_codes:
user32.PostMessageW(hwnd, WM_KEYDOWN, vk_code, 0)
# 保持按键状态
await asyncio.sleep(hold_time)
# 按相反顺序释放所有按键(模拟真实按键行为)
for vk_code in reversed(vk_codes):
user32.PostMessageW(hwnd, WM_KEYUP, vk_code, 0)
return True
async def post_keys_to_hwnd_sync(
hwnd: int, vk_codes: list[int], hold_time: float = 0.05
) -> bool:
"""
使用 SendMessage 向指定窗口句柄同步发送多个按键
先按下所有按键,等待指定时间,然后释放所有按键。
参数:
hwnd (int): 目标窗口句柄
vk_codes (List[int]): 虚拟键码列表
hold_time (float): 按键保持时间(秒),默认 0.05 秒
返回:
bool: 如果所有消息都成功发送则返回 True
注意:
- 此调用是**同步阻塞**的:当前线程会等待目标窗口处理完每个消息才继续。
- 如果目标窗口无响应hung当前程序也会卡住
- 按键顺序:先按下所有键,等待,然后按相反顺序释放所有键。
"""
if hwnd <= 0:
raise ValueError("hwnd 必须是正整数")
if not vk_codes:
raise ValueError("vk_codes 不能为空")
# 验证所有虚拟键码
for vk_code in vk_codes:
if not (0 <= vk_code <= 0xFFFF):
raise ValueError(f"vk_code {vk_code} 必须是有效的虚拟键码0~65535")
# 按下所有按键
down_results = []
for vk_code in vk_codes:
result = user32.SendMessageW(hwnd, WM_KEYDOWN, vk_code, 0)
down_results.append(result)
# 保持按键状态
await asyncio.sleep(hold_time)
# 按相反顺序释放所有按键(模拟真实按键行为)
up_results = []
for vk_code in reversed(vk_codes):
result = user32.SendMessageW(hwnd, WM_KEYUP, vk_code, 0)
up_results.append(result)
# 如果所有按键操作都成功,则返回 True
return all(down_results) and all(up_results)