如何使用Python自动检测并点击Windows程序弹窗的确认按钮
工单系统闲置确认弹窗自动点击方案(Python实现)
方案选型说明
优先采用Win32事件钩子+后台消息点击的实现逻辑,相比定时遍历窗口、固定坐标模拟点击的方案有几个明显优势:
- 事件驱动触发,弹窗生成后10ms内即可响应,无轮询延迟,CPU占用趋近于0
- 核心点击逻辑通过Windows消息实现,不需要把弹窗切到前台,后台完成操作,完全不打断当前正在进行的工作,用户几乎感知不到弹窗存在
- 不依赖固定屏幕坐标,适配不同分辨率、窗口位置变动的场景
- 内置兜底兼容逻辑,碰到自绘UI读不到控件的特殊程序,也能通过短暂切前台+坐标点击完成操作,点击后自动切回原工作窗口
依赖准备
只需要安装pywin32库调用Win32接口即可,执行以下命令安装:
pip install pywin32
完整实现代码
import win32gui import win32con import win32api import ctypes # 配置项:根据实际弹窗内容调整关键字 EVENT_OBJECT_CREATE = 0x8000 WINEVENT_OUTOFCONTEXT = 0x0000 TARGET_POPUP_KEYWORD = "你是否仍在使用本程序?" TARGET_BTN_KEYWORD = "是" def win_event_callback(hWinEventHook, event, hwnd, idObject, idChild, dwEventThread, dwmsEventTime): # 仅处理顶层窗口创建事件 if idObject != win32con.OBJID_WINDOW: return # 匹配目标弹窗标题 window_title = win32gui.GetWindowText(hwnd) if TARGET_POPUP_KEYWORD not in window_title: return # 优先遍历子控件找确认按钮,发后台点击消息 confirm_btn = None def enum_child_proc(child_hwnd, param): nonlocal confirm_btn if not win32gui.IsWindowVisible(child_hwnd): return True child_text = win32gui.GetWindowText(child_hwnd) if TARGET_BTN_KEYWORD in child_text: confirm_btn = child_hwnd return False return True win32gui.EnumChildWindows(hwnd, enum_child_proc, None) if confirm_btn: # 发送点击消息,全程后台无感知 win32api.SendMessage(confirm_btn, win32con.BM_CLICK, 0, 0) return # 兜底逻辑:自绘UI取不到子按钮时,用坐标点击 prev_foreground_hwnd = win32gui.GetForegroundWindow() win32gui.SetForegroundWindow(hwnd) win32api.Sleep(1) # 取窗口位置计算按钮坐标,默认适配常规弹窗右下确认按钮布局,可根据实际UI调整偏移量 left, top, right, bottom = win32gui.GetWindowRect(hwnd) click_x = right - 80 click_y = bottom - 40 # 模拟鼠标点击 win32api.SetCursorPos((click_x, click_y)) win32api.mouse_event(win32con.MOUSEEVENTF_LEFTDOWN, click_x, click_y, 0, 0) win32api.mouse_event(win32con.MOUSEEVENTF_LEFTUP, click_x, click_y, 0, 0) # 把焦点切回之前的工作窗口 win32gui.SetForegroundWindow(prev_foreground_hwnd) if __name__ == "__main__": # 注册全局窗口创建事件钩子 event_hook = win32gui.SetWinEventHook( EVENT_OBJECT_CREATE, EVENT_OBJECT_CREATE, 0, win_event_callback, 0, 0, WINEVENT_OUTOFCONTEXT ) # 启动Windows消息循环保持监听 msg = ctypes.wintypes.MSG() while ctypes.windll.user32.GetMessageW(ctypes.byref(msg), 0, 0, 0) != 0: ctypes.windll.user32.TranslateMessage(ctypes.byref(msg)) ctypes.windll.user32.DispatchMessageW(ctypes.byref(msg))
使用说明
- 如果实际弹窗的标题、按钮文案和描述有出入,可以用Spy++工具抓取准确的窗口文本、类名,替换代码开头的关键字常量即可适配
- 想要静默后台运行不弹出命令行黑框,只需要把脚本后缀从
.py改成.pyw,用pythonw.exe启动即可 - 需要开机自动运行的话,给脚本创建快捷方式,放到系统启动目录(运行窗口输入
shell:startup即可打开对应目录)就能实现开机自启 - 兜底逻辑里的坐标偏移量可以根据实际工单程序的弹窗按钮位置调整,常规系统默认样式的弹窗不需要修改
内容的提问来源于stack exchange,提问作者Pez18000
相关产品推荐
相关产品推荐

