问题
在使用自己写的 Python开发游戏自动化后台脚本过程中,发现其对安卓模拟器这种Qt5QWindowIcon类名的窗口不起作用,下面是解决办法
过程
首先通过spy++确定了需要发送消息的窗口不是最上层的Qt5QWindowIcon类,而是第四级RenderWindowWindow,Qt5QWindowIcon这一窗口
其次通过监视其鼠标消息,发现实际用鼠标点击的消息队列如下:
并且需要注意的是在WM_LBUTTONDOWN这条消息中,fwKeys参数为MK_LBUTTON,而原代码中没有考虑这一参数,直接设置0.
在进一步的验证过程中,发现只要涵盖最后三条消息即可成功。
解决
首先修改原左键按下函数:
def __left_down(self, handle: HWND, x: int, y: int):
"""在坐标(x, y)按下鼠标左键
Args:
handle (HWND): 窗口句柄
x (int): 横坐标
y (int): 纵坐标
"""
# https://docs.microsoft.com/en-us/windows/win32/inputdev/wm-lbuttondown
wparam = 0x001 # MK_LBUTTON
lparam = y << 16 | x
self.__PostMessageW(handle, self.__WM_LBUTTONDOWN, wparam, lparam)
补充参数:
__SendMessageW = windll.user32.SendMessageW
__WM_SETCURSOR = 0x20
__WM_MOUSEACTIVATE = 0x21
__HTCLIENT = 1
__MA_ACTIVATE = 1
补充函数:
def __set_cursor(self, handle: HWND, msg):
"""
@Description : Sent to a window if the mouse causes the cursor to move within a window and mouse input is not captured
---------
@Args : handle (HWND): 窗口句柄, msg : setcursor消息
-------
@Returns :
-------
"""
# https://docs.microsoft.com/en-us/windows/win32/menurc/wm-setcursor
lparam = (msg << 16) | self.__HTCLIENT
self.__SendMessageW(handle, self.__WM_SETCURSOR, handle, lparam)
def __activate_mouse(self, handle: HWND):
"""
@Description : 激活窗口接受鼠标消息
---------
@Args : handle (HWND): 窗口句柄
-------
@Returns :
-------
"""
# https://docs.microsoft.com/en-us/windows/win32/inputdev/wm-mouseactivate
lparam = (self.__WM_LBUTTONDOWN << 16) | self.__HTCLIENT
self.__SendMessageW(handle, self.__WM_MOUSEACTIVATE, self.__handle, lparam)
完整的点击函数为:
def mouse_click(self, x, y, times=0.5):
"""
@description : 单击左键
---------
@param : 位置坐标x,y 单击后延时times(s)
-------
@Returns :
-------
"""
self.__set_cursor(self.__clickhandle, self.__WM_MOUSEACTIVATE)
self.__move_to(self.__clickhandle, int(x / scale), int(y / scale))
self.__activate_mouse(self.__clickhandle)
self.__set_cursor(self.__clickhandle, self.__WM_LBUTTONDOWN)
self.__left_down(self.__clickhandle, int(x / scale), int(y / scale))
self.__move_to(self.__clickhandle, int(x / scale), int(y / scale))
self.__left_up(self.__clickhandle, int(x / scale), int(y / scale))
time.sleep(times)
仅含最后3条消息的精简版点击函数:
def mouse_click(self, x, y, times=0.5):
"""
@description : 单击左键
---------
@param : 位置坐标x,y 单击后延时times(s)
-------
@Returns :
-------
"""
# self.__set_cursor(self.__clickhandle, self.__WM_MOUSEACTIVATE)
# self.__move_to(self.__clickhandle, int(x / scale), int(y / scale))
# self.__activate_mouse(self.__clickhandle)
# self.__set_cursor(self.__clickhandle, self.__WM_LBUTTONDOWN)
self.__left_down(self.__clickhandle, int(x / scale), int(y / scale))
self.__move_to(self.__clickhandle, int(x / scale), int(y / scale))
self.__left_up(self.__clickhandle, int(x / scale), int(y / scale))
time.sleep(times)