You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python在非激活MacromediaFlashPlayerActiveX窗口模拟鼠标点击失败求助

非激活窗口模拟Flash控件鼠标点击无效问题排查

问题描述

尝试在非激活窗口中模拟鼠标点击,目标是窗口内的MacromediaFlashPlayerActiveX控件。使用win32api.PostMessage发送WM_LBUTTONDOWN和WM_LBUTTONUP消息后,能看到按钮悬停阴影,点击位置已验证正确,但无法触发按钮点击;模拟键盘操作正常。相关代码如下:

# -*- coding:utf-8 -*-
import time

import win32api, win32gui, win32con


def click_minimize(hwnd, x, y):
    long_position = win32api.MAKELONG(x, y)
    win32api.PostMessage(hwnd, win32con.WM_LBUTTONDOWN, win32con.MK_LBUTTON, long_position)
    time.sleep(0.3)
    win32api.PostMessage(hwnd, win32con.WM_LBUTTONUP, 0000, long_position)


def flash_button_pos(child_hwnd):
    # Calculate mouse click position
    x1, y1, x2, y2 = win32gui.GetWindowRect(child_hwnd)
    if (x2 - x1) / (y2 - y1) < 1.4:
        length = x2 - x1
        hight = length / 1.4
        x = 0
        y = (y2 - y1 - hight) / 2
    else:
        hight = y2 - y1
        length = hight * 1.4
        x = (x2 - x1 - length) / 2
        y = 0
    x0 = int(0.171 * length + x)
    y0 = int(0.493 * hight + y)
    return x0, y0


if __name__ == '__main__':
    hwld = win32gui.FindWindow(None, "MyGamePython")
    hwnd_child_list = []
    win32gui.EnumChildWindows(hwld, lambda hWnd, param: param.append(hWnd), hwnd_child_list)
    child_hwnd = None
    for i in hwnd_child_list:
        if win32gui.GetClassName(i) == "MacromediaFlashPlayerActiveX":
            child_hwnd = i
    x0, y0 = flash_button_pos(child_hwnd)
    print(x0, y0)
    click_minimize(child_hwnd, x0, y0)

排查与解决建议

  • 修正坐标系统:WM_LBUTTON系列消息要求坐标为控件客户区的相对坐标,当前代码基于控件外框计算,需改为基于客户区尺寸:

    def flash_button_pos(child_hwnd):
        # 获取控件客户区大小(而非窗口外框)
        client_rect = win32gui.GetClientRect(child_hwnd)
        cx, cy = client_rect[2], client_rect[3]
        if cx / cy < 1.4:
            length = cx
            hight = length / 1.4
            x = 0
            y = (cy - hight) / 2
        else:
            hight = cy
            length = hight * 1.4
            x = (cx - length) / 2
            y = 0
        x0 = int(0.171 * length + x)
        y0 = int(0.493 * hight + y)
        return x0, y0
    
  • 补充鼠标移动消息:Flash控件可能需要先感知鼠标进入,再响应点击,在点击前添加WM_MOUSEMOVE消息:

    def click_minimize(hwnd, x, y):
        long_position = win32api.MAKELONG(x, y)
        # 先发送鼠标移动到目标位置的消息
        win32api.PostMessage(hwnd, win32con.WM_MOUSEMOVE, 0, long_position)
        time.sleep(0.05)
        win32api.PostMessage(hwnd, win32con.WM_LBUTTONDOWN, win32con.MK_LBUTTON, long_position)
        time.sleep(0.05) # 缩短延迟,模拟真实点击间隔
        win32api.PostMessage(hwnd, win32con.WM_LBUTTONUP, 0, long_position)
    
  • 修正消息参数:WM_LBUTTONUP的wParam应为0,原代码的0000写法不规范,虽然Python会解析为0,但建议直接写0避免潜在问题。

  • 改用同步消息发送:PostMessage是异步发送,控件可能未处理完前序消息就收到后续消息,改用SendMessage同步发送确保消息被处理:

    win32api.SendMessage(hwnd, win32con.WM_LBUTTONDOWN, win32con.MK_LBUTTON, long_position)
    time.sleep(0.05)
    win32api.SendMessage(hwnd, win32con.WM_LBUTTONUP, 0, long_position)
    
  • 尝试硬件级输入模拟:若Flash控件过滤非系统消息,可使用mouse_event模拟真实硬件输入(需转换为屏幕坐标):

    def click_with_hardware(child_hwnd, client_x, client_y):
        # 转换客户区坐标为屏幕坐标
        screen_x, screen_y = win32gui.ClientToScreen(child_hwnd, (client_x, client_y))
        # 移动鼠标到目标位置(绝对坐标需转为0-65535范围)
        win32api.mouse_event(win32con.MOUSEEVENTF_MOVE | win32con.MOUSEEVENTF_ABSOLUTE,
                            int(screen_x / win32api.GetSystemMetrics(0) * 65535),
                            int(screen_y / win32api.GetSystemMetrics(1) * 65535))
        time.sleep(0.05)
        win32api.mouse_event(win32con.MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0)
        time.sleep(0.05)
        win32api.mouse_event(win32con.MOUSEEVENTF_LEFTUP, 0, 0, 0, 0)
    
    # 主函数中调用
    click_with_hardware(child_hwnd, x0, y0)
    

内容的提问来源于stack exchange,提问作者Guf

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 22:01:19