如何在Windows最小化窗口中通过win32api实现无需最大化的模拟点击
解决最小化Windows应用窗口的点击操作问题
问题核心
你当前用mouse_event模拟物理鼠标点击的方式,依赖窗口在屏幕上的可见位置,所以窗口最小化时完全失效。要实现后台点击,必须直接向目标窗口发送鼠标消息,而非操作系统全局鼠标。
解决方案
使用Windows API的SendMessage函数,直接给目标窗口发送WM_LBUTTONDOWN和WM_LBUTTONUP消息。这种方式不依赖窗口的显示状态,即使最小化也能生效。
整合后的完整代码
将截图、图像识别和后台点击逻辑整合:
from ctypes import windll import win32gui, win32ui, win32con import numpy as np from PIL import Image import cv2 import time # 配置参数 TARGET_WINDOW_TITLE = 'app title' TEMPLATE_IMAGE_PATH = 'VI.jpg' MATCH_THRESHOLD = 0.8 # 查找目标窗口句柄 hwnd = win32gui.FindWindow(None, TARGET_WINDOW_TITLE) if not hwnd: print("未找到目标窗口") exit() # 截图最小化窗口(保留原有有效逻辑) left, top, right, bot = win32gui.GetWindowRect(hwnd) w = right - left h = bot - top hwndDC = win32gui.GetWindowDC(hwnd) mfcDC = win32ui.CreateDCFromHandle(hwndDC) saveDC = mfcDC.CreateCompatibleDC() saveBitMap = win32ui.CreateBitmap() saveBitMap.CreateCompatibleBitmap(mfcDC, w, h) saveDC.SelectObject(saveBitMap) # 执行截图 result = windll.user32.PrintWindow(hwnd, saveDC.GetSafeHdc(), 3) if result != 1: print("截图失败") exit() # 转换为PIL图像 bmpinfo = saveBitMap.GetInfo() bmpstr = saveBitMap.GetBitmapBits(True) im = Image.frombuffer('RGB', (bmpinfo['bmWidth'], bmpinfo['bmHeight']), bmpstr, 'raw', 'BGRX', 0, 1) # 释放资源 win32gui.DeleteObject(saveBitMap.GetHandle()) saveDC.DeleteDC() mfcDC.DeleteDC() win32gui.ReleaseDC(hwnd, hwndDC) # 图像识别匹配 template = Image.open(TEMPLATE_IMAGE_PATH) template_np = np.array(template) screenshot_np = np.array(im) match_result = cv2.matchTemplate(screenshot_np, template_np, cv2.TM_CCOEFF_NORMED) min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(match_result) if max_val >= MATCH_THRESHOLD: print(f"找到目标,坐标:{max_loc}") # 转换为Windows消息要求的坐标格式(高16位存y,低16位存x) client_x, client_y = max_loc l_param = (client_y << 16) | (client_x & 0xFFFF) # 发送左键按下消息 windll.user32.SendMessageW(hwnd, win32con.WM_LBUTTONDOWN, win32con.MK_LBUTTON, l_param) # 模拟真实点击的短暂延迟 time.sleep(0.05) # 发送左键抬起消息 windll.user32.SendMessageW(hwnd, win32con.WM_LBUTTONUP, 0, l_param) print("已发送后台点击消息") else: print("未匹配到目标图像")
关键细节说明
SendMessageW直接与窗口句柄交互,完全不影响前台操作,你可以同时用鼠标处理其他任务- 坐标无需转换:
PrintWindow获取的截图坐标就是窗口客户区的相对坐标,直接打包成消息参数即可 - 消息参数规范:
WM_LBUTTONDOWN的wParam必须传入MK_LBUTTON标记,表示左键按下状态
内容的提问来源于stack exchange,提问作者Rhys
相关产品推荐
相关产品推荐

