说明
获取窗口句柄
寻找标题为title的窗口,激活该窗口并置于x_coor, y_coor处,title可利用visual studio的spy++.exe查看;SWP_NOSIZE指定了窗口大小不变
def get_winds(self, title: str):` `"""` `@description : 获取游戏句柄 ,并把游戏窗口置顶并激活窗口` `---------` `@param : 窗口名` `-------` `@Returns : 窗口句柄` `-------` `"""` `# self.__handle = win32gui.FindWindowEx(0, 0, "Qt5QWindowIcon", "MuMu模拟器")` `self.__handle = windll.user32.FindWindowW(None, title)` `self.__classname = win32gui.GetClassName(self.__handle)` `# print(self.__classname)` `if self.__classname == 'Qt5QWindowIcon':` `self.__mainhandle = win32gui.FindWindowEx(self.__handle, 0, "Qt5QWindowIcon", "MainWindowWindow")` `# print(self.__mainhandle)` `self.__centerhandle = win32gui.FindWindowEx(self.__mainhandle, 0, "Qt5QWindowIcon", "CenterWidgetWindow")` `# print(self.__centerhandle)` `self.__renderhandle = win32gui.FindWindowEx(self.__centerhandle, 0, "Qt5QWindowIcon", "RenderWindowWindow")` `# print(self.__renderhandle)` `self.__clickhandle = self.__renderhandle` `else:` `self.__clickhandle = self.__handle` `# self.__subhandle = win32gui.FindWindowEx(self.__renderhandle, 0, "subWin", "sub")` `# print(self.__subhandle)` `# self.__subsubhandle = win32gui.FindWindowEx(self.__subhandle, 0, "subWin", "sub")` `# print(self.__subsubhandle)` `# win32gui.ShowWindow(hwnd1, win32con.SW_RESTORE)` `# print(win32gui.GetWindowRect(hwnd1))` `win32gui.SetWindowPos(self.__handle, win32con.HWND_TOP, x_coor, y_coor, 0, 0, win32con.SWP_SHOWWINDOW | win32con.SWP_NOSIZE)` `print(self.__clickhandle)` `return self.__handle``
获得后台窗口截图
窗口上方有39个像素的边框,左、右、下则有8个像素的边框
def get_src(self):` `"""` `@description : 获得后台窗口截图` `---------` `@param : None` `-------` `@Returns : None` `-------` `"""`` ` `left, top, right, bot = win32gui.GetWindowRect(self.__handle)` `#Remove border around window (8 pixels on each side)` `bl = 8` `#Remove border on top` `bt = 39`` ` `width = int((right - left + 1) * scale) - 2 * bl` `height = int((bot - top + 1) * scale) - bt - bl` `# 返回句柄窗口的设备环境,覆盖整个窗口,包括非客户区,标题栏,菜单,边框` `hWndDC = win32gui.GetWindowDC(self.__handle)` `# 创建设备描述表` `mfcDC = win32ui.CreateDCFromHandle(hWndDC)` `# 创建内存设备描述表` `saveDC = mfcDC.CreateCompatibleDC()` `# 创建位图对象准备保存图片` `saveBitMap = win32ui.CreateBitmap()` `# 为bitmap开辟存储空间` `saveBitMap.CreateCompatibleBitmap(mfcDC, width, height)` `# 将截图保存到saveBitMap中` `saveDC.SelectObject(saveBitMap)` `# 保存bitmap到内存设备描述表` `saveDC.BitBlt((0, 0), (width, height), mfcDC, (bl, bt), win32con.SRCCOPY)` `###获取位图信息` `bmpinfo = saveBitMap.GetInfo()` `bmpstr = saveBitMap.GetBitmapBits(True)` `###生成图像` `im_PIL = Image.frombuffer('RGB', (bmpinfo['bmWidth'], bmpinfo['bmHeight']), bmpstr, 'raw', 'BGRX', 0, 1)` `# 内存释放` `win32gui.DeleteObject(saveBitMap.GetHandle())` `saveDC.DeleteDC()` `mfcDC.DeleteDC()` `win32gui.ReleaseDC(self.__handle, hWndDC)` `###PrintWindow成功,保存到文件,显示到屏幕` `im_PIL.save("src.jpg") # 保存` `# im_PIL.show() # 显示``
数字识别
依赖项——Tesseract OCR
下载并添加至系统环境变量
注意:这里将ocr识别范围限定为0-9的数字以提高准确率
截取范围为src.jpg中左上(x1,y1)到右下(x2,y2)的矩形区域
def get_num(self, x1, y1, x2, y2):` `"""` `@description : 获取屏幕截图中的数字` `---------` `@param : 截图中需要截取的含数字部分边界` `-------` `@Returns : num:int` `-------` `"""` ` img = Image.open("src.jpg")` `num_img = img.crop((x1, y1, x2, y2))` `num_img = ImageOps.invert(num_img)` `num = pytesseract.image_to_string(num_img, lang="eng",` `config='--psm 6 --oem 3 -c tessedit_char_whitelist=0123456789').strip()` `# num = pytesseract.image_to_string(num_img, lang="eng")` `try:` `print("数量为", int(num))` `return int(num)` `except:` `print("未检测到数字")` `return 0``
识别并点击图片位置
所需识别的图片模板事先准备好并放在同一目录下,输入图片文件路径
这里confidence设置为0.9
def mouse_click_image(self, name : str, times = 0.5):` `"""` `@Description : 鼠标左键点击识别到的图片位置` `---------` `@Args : name:输入图片名; times:单击后延时` `-------` `@Returns : None` `-------` `"""` `try:` `result = self.recognize(name)` `if result is None or result['confidence'] < 0.9:` `print("No results!")` `else:` `print(result['result'][0] + x_coor * scale + 8, " ",result['result'][1] + y_coor * scale + 39)` `self.mouse_click(result['result'][0] + x_coor * scale + 8, result['result'][1] + y_coor * scale + 39)` `except:` `raise Exception("error")``
后台文字输入
def type_str(self, msg: str):` `"""` `@Description : 打字` `---------` `@Args : msg:目标字符` `-------` `@Returns : None` `-------` `"""` `for i in msg:` `self.__PostMessageW(self.__handle, win32con.WM_CHAR, ord(i), 0)``
完整代码
GITEE网址: 项目-AutoClick.https://gitee.com/yaadon/auto-click
#!/usr/bin/env python``# -*- encoding: utf-8 -*-``'''``@File : AutoClick.py``@Time : 2021/10/09 15:10:01``@Author : Yaadon` `'''`` ``# here put the import lib``import win32con``import win32gui``import win32ui``import time``# import threading``import numpy as np``import os``from PIL import Image``from PIL import ImageOps``import aircv as ac``import pytesseract``from ctypes import windll, byref``from ctypes.wintypes import HWND, POINT``import string``# import sys``# import cv2``# from memory_pic import *``# import win32api``# import autopy``# from PIL import ImageGrab`` ``scale = 1.25 # 电脑的缩放比例``radius = 5 # 随机半径``x_coor = 10 # 窗口位置``y_coor = 10 # 窗口位置`` ``class AutoClick():` `"""` `@description :自动点击类,包含后台截图、图像匹配` `---------` `@param :` `-------` `@Returns :` `-------` `"""` ` __PostMessageW = windll.user32.PostMessageW` `__SendMessageW = windll.user32.SendMessageW` `__MapVirtualKeyW = windll.user32.MapVirtualKeyW` `__VkKeyScanA = windll.user32.VkKeyScanA` `__ClientToScreen = windll.user32.ClientToScreen`` ` `__WM_KEYDOWN = 0x100` `__WM_KEYUP = 0x101` `__WM_MOUSEMOVE = 0x0200` `__WM_LBUTTONDOWN = 0x0201` `__WM_LBUTTONUP = 0x202` `__WM_MOUSEWHEEL = 0x020A` `__WHEEL_DELTA = 120` `__WM_SETCURSOR = 0x20` `__WM_MOUSEACTIVATE = 0x21`` ` `__HTCLIENT = 1` `__MA_ACTIVATE = 1`` ` `__VkCode = {` `"back": 0x08,` `"tab": 0x09,` `"return": 0x0D,` `"shift": 0x10,` `"control": 0x11,` `"menu": 0x12,` `"pause": 0x13,` `"capital": 0x14,` `"escape": 0x1B,` `"space": 0x20,` `"end": 0x23,` `"home": 0x24,` `"left": 0x25,` `"up": 0x26,` `"right": 0x27,` `"down": 0x28,` `"print": 0x2A,` `"snapshot": 0x2C,` `"insert": 0x2D,` `"delete": 0x2E,` `"lwin": 0x5B,` `"rwin": 0x5C,` `"numpad0": 0x60,` `"numpad1": 0x61,` `"numpad2": 0x62,` `"numpad3": 0x63,` `"numpad4": 0x64,` `"numpad5": 0x65,` `"numpad6": 0x66,` `"numpad7": 0x67,` `"numpad8": 0x68,` `"numpad9": 0x69,` `"multiply": 0x6A,` `"add": 0x6B,` `"separator": 0x6C,` `"subtract": 0x6D,` `"decimal": 0x6E,` `"divide": 0x6F,` `"f1": 0x70,` `"f2": 0x71,` `"f3": 0x72,` `"f4": 0x73,` `"f5": 0x74,` `"f6": 0x75,` `"f7": 0x76,` `"f8": 0x77,` `"f9": 0x78,` `"f10": 0x79,` `"f11": 0x7A,` `"f12": 0x7B,` `"numlock": 0x90,` `"scroll": 0x91,` `"lshift": 0xA0,` `"rshift": 0xA1,` `"lcontrol": 0xA2,` `"rcontrol": 0xA3,` `"lmenu": 0xA4,` `"rmenu": 0XA5` `}`` ` `def __get_virtual_keycode(self, key: str):` `"""根据按键名获取虚拟按键码`` ` `Args:` `key (str): 按键名`` ` `Returns:` `int: 虚拟按键码` `"""` `if len(key) == 1 and key in string.printable:` `# https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-vkkeyscana` `return self.__VkKeyScanA(ord(key)) & 0xff` `else:` `return self.__VkCode[key]`` `` ` `def __key_down(self, handle: HWND, key: str):` `"""按下指定按键`` ` `Args:` `handle (HWND): 窗口句柄` `key (str): 按键名` `"""` `vk_code = self.__get_virtual_keycode(key)` `scan_code = self.__MapVirtualKeyW(vk_code, 0)` `# https://docs.microsoft.com/en-us/windows/win32/inputdev/wm-keydown` `wparam = vk_code` `lparam = (scan_code << 16) | 1` `self.__PostMessageW(handle, self.__WM_KEYDOWN, wparam, lparam)`` `` ` `def __key_up(self, handle: HWND, key: str):` `"""放开指定按键`` ` `Args:` `handle (HWND): 窗口句柄` `key (str): 按键名` `"""` `vk_code = self.__get_virtual_keycode(key)` `scan_code = self.__MapVirtualKeyW(vk_code, 0)` `# https://docs.microsoft.com/en-us/windows/win32/inputdev/wm-keyup` `wparam = vk_code` `lparam = (scan_code << 16) | 0XC0000001` `self.__PostMessageW(handle, self.__WM_KEYUP, wparam, 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 __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 __move_to(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-mousemove` `wparam = 0` `lparam = y << 16 | x` `self.__PostMessageW(handle, self.__WM_MOUSEMOVE, wparam, lparam)`` `` ` `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)`` `` ` `def __left_up(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-lbuttonup` `wparam = 0` `lparam = y << 16 | x` `self.__PostMessageW(handle, self.__WM_LBUTTONUP, wparam, lparam)`` `` ` `def __scroll(self, handle: HWND, delta: int, x: int, y: int):` `"""在坐标(x, y)滚动鼠标滚轮`` ` `Args:` `handle (HWND): 窗口句柄` `delta (int): 为正向上滚动,为负向下滚动` `x (int): 横坐标` `y (int): 纵坐标` `"""` `self.__move_to(handle, x, y)` `# https://docs.microsoft.com/en-us/windows/win32/inputdev/wm-mousewheel` `wparam = delta << 16` `p = POINT(x, y)` `self.__ClientToScreen(handle, byref(p))` `lparam = p.y << 16 | p.x` `self.__PostMessageW(handle, self.__WM_MOUSEWHEEL, wparam, lparam)`` `` ` `def __scroll_up(self, handle: HWND, x: int, y: int):` `"""在坐标(x, y)向上滚动鼠标滚轮`` ` `Args:` `handle (HWND): 窗口句柄` `x (int): 横坐标` `y (int): 纵坐标` `"""` `self.__scroll(handle, self.__WHEEL_DELTA, x, y)`` `` ` `def __scroll_down(self, handle: HWND, x: int, y: int):` `"""在坐标(x, y)向下滚动鼠标滚轮`` ` `Args:` `handle (HWND): 窗口句柄` `x (int): 横坐标` `y (int): 纵坐标` `"""` `self.__scroll(handle, -self.__WHEEL_DELTA, x, y)`` `` ` `def get_winds(self, title: str):` `"""` `@description : 获取游戏句柄 ,并把游戏窗口置顶并激活窗口` `---------` `@param : 窗口名` `-------` `@Returns : 窗口句柄` `-------` `"""` `# self.__handle = win32gui.FindWindowEx(0, 0, "Qt5QWindowIcon", "MuMu模拟器")` `self.__handle = windll.user32.FindWindowW(None, title)` `self.__classname = win32gui.GetClassName(self.__handle)` `# print(self.__classname)` `if self.__classname == 'Qt5QWindowIcon':` `self.__mainhandle = win32gui.FindWindowEx(self.__handle, 0, "Qt5QWindowIcon", "MainWindowWindow")` `# print(self.__mainhandle)` `self.__centerhandle = win32gui.FindWindowEx(self.__mainhandle, 0, "Qt5QWindowIcon", "CenterWidgetWindow")` `# print(self.__centerhandle)` `self.__renderhandle = win32gui.FindWindowEx(self.__centerhandle, 0, "Qt5QWindowIcon", "RenderWindowWindow")` `# print(self.__renderhandle)` `self.__clickhandle = self.__renderhandle` `else:` `self.__clickhandle = self.__handle` `# self.__subhandle = win32gui.FindWindowEx(self.__renderhandle, 0, "subWin", "sub")` `# print(self.__subhandle)` `# self.__subsubhandle = win32gui.FindWindowEx(self.__subhandle, 0, "subWin", "sub")` `# print(self.__subsubhandle)` `# win32gui.ShowWindow(hwnd1, win32con.SW_RESTORE)` `# print(win32gui.GetWindowRect(hwnd1))` `win32gui.SetWindowPos(self.__handle, win32con.HWND_TOP, x_coor, y_coor, 0, 0, win32con.SWP_SHOWWINDOW | win32con.SWP_NOSIZE)` `print(self.__clickhandle)` `return self.__handle` ` ` `def get_src(self):` `"""` `@description : 获得后台窗口截图` `---------` `@param : None` `-------` `@Returns : None` `-------` `"""`` ` `left, top, right, bot = win32gui.GetWindowRect(self.__handle)` `#Remove border around window (8 pixels on each side)` `bl = 8` `#Remove border on top` `bt = 39`` ` `width = int((right - left + 1) * scale) - 2 * bl` `height = int((bot - top + 1) * scale) - bt - bl` `# 返回句柄窗口的设备环境,覆盖整个窗口,包括非客户区,标题栏,菜单,边框` `hWndDC = win32gui.GetWindowDC(self.__handle)` `# 创建设备描述表` `mfcDC = win32ui.CreateDCFromHandle(hWndDC)` `# 创建内存设备描述表` `saveDC = mfcDC.CreateCompatibleDC()` `# 创建位图对象准备保存图片` `saveBitMap = win32ui.CreateBitmap()` `# 为bitmap开辟存储空间` `saveBitMap.CreateCompatibleBitmap(mfcDC, width, height)` `# 将截图保存到saveBitMap中` `saveDC.SelectObject(saveBitMap)` `# 保存bitmap到内存设备描述表` `saveDC.BitBlt((0, 0), (width, height), mfcDC, (bl, bt), win32con.SRCCOPY)` `###获取位图信息` `bmpinfo = saveBitMap.GetInfo()` `bmpstr = saveBitMap.GetBitmapBits(True)` `###生成图像` `im_PIL = Image.frombuffer('RGB', (bmpinfo['bmWidth'], bmpinfo['bmHeight']), bmpstr, 'raw', 'BGRX', 0, 1)` `# 内存释放` `win32gui.DeleteObject(saveBitMap.GetHandle())` `saveDC.DeleteDC()` `mfcDC.DeleteDC()` `win32gui.ReleaseDC(self.__handle, hWndDC)` `###PrintWindow成功,保存到文件,显示到屏幕` `im_PIL.save("src.jpg") # 保存` `# im_PIL.show() # 显示` ` ` ` ` `def recognize(self, objs):` `"""` `@description : 图像识别之模板匹配` `---------` `@param : 需要匹配的模板名` `-------` `@Returns : 将传进来的图片和全屏截图匹配如果找到就返回图像在屏幕的坐标 否则返回None` `-------` `"""` ` imobj = ac.imread(objs)` `imsrc = ac.imread('%s\\src.jpg' % os.getcwd())` `pos = ac.find_template(imsrc, imobj, 0.5)` `return pos`` `` ` `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)` ` ` `def mouse_click_image(self, name : str, times = 0.5):` `"""` `@Description : 鼠标左键点击识别到的图片位置` `---------` `@Args : name:输入图片名; times:单击后延时` `-------` `@Returns : None` `-------` `"""` `try:` `result = self.recognize(name)` `if result is None or result['confidence'] < 0.9:` `print("No results!")` `else:` `print(result['result'][0] + x_coor * scale + 8, " ",result['result'][1] + y_coor * scale + 39)` `self.mouse_click(result['result'][0] + x_coor * scale + 8, result['result'][1] + y_coor * scale + 39)` `except:` `raise Exception("error")`` ` ` def mouse_click_radius(self, x, y, times=0.5):` `"""` `@description : 在范围内随机位置单击(防检测)` `---------` `@param : 位置坐标x,y 单击后延时times(s)` `-------` `@Returns :`` -------` `"""` ` random_x = np.random.randint(-radius, radius)` `random_y = np.random.randint(-radius, radius)` `self.mouse_click(x + random_x, y + random_y)` `# self.__left_down(self.__clickhandle, int((x + random_x) / scale), int((y + random_y) / scale))` `# time.sleep(0.1)` `# self.__left_up(self.__clickhandle, int((x + random_x) / scale), int((y + random_y) / scale))` `time.sleep(times)`` `` ` `def push_key(self, key: str, times = 1):` `"""` `@Description : 按键` `---------` `@Args : key:按键 times:按下改键后距松开的延时` `-------` `@Returns : None` `-------` `"""` `self.__key_down(self.__clickhandle, key)` `time.sleep(times)` `self.__key_up(self.__clickhandle, key)` `time.sleep(0.5)` ` ` `def type_str(self, msg: str):` `"""` `@Description : 打字` `---------` `@Args : msg:目标字符` `-------` `@Returns : None` `-------` `"""` `for i in msg:` `self.__PostMessageW(self.__clickhandle, win32con.WM_CHAR, ord(i), 0)`` `` ``if __name__ == '__main__':` `click = AutoClick()` `click.get_winds("微信")` `click.get_src()` `# click.mouse_click(254, 536)` `click.mouse_click_image('test.png')` `# click.mouse_click(1086, 269) # 输入框` `# click.mouse_click(237, 211) # 输入框` `# click.mouse_click(1228, 201) # 输入框` `# click.type_str("123木头人abc")``
至此,就是我在学习后台自动化过程中查阅到的一篇完整代码。代码作者和下载网址均附上。
其中有一些小细节我展开说一下:
1.如果窗口中有多个图像与目标相符,如何进行匹配?
可以使用find_all_template
函数。
代码如下:
import aircv as ac ``# 读取源图像和模板图像` `im_src = ac.imread('source_image.png')` `im_template = ac.imread('template_image.png') ``# 查找所有匹配的区域` `matches = ac.find_all_template(im_src, im_template, threshold=0.5) ``# 遍历匹配结果并标记匹配区域` `for match in matches: `` x, y = match['result'] `` w, h = match['rectangle'][2][0] - match['rectangle'][0][0], match['rectangle'][2][1] - match['rectangle'][0][1] `` ac.rectangle(im_src, (x, y), (x+w, y+h), (0, 255, 0), 2) ``# 显示标记后的图像` `ac.imshow(im_src)` `ac.waitkey(0)
2.如何在后台窗口进行点击?
这个问题可能有点呆,我们这几讲以及上面的代码不就是讲的这个么?
我们看上面的代码click.mouse_click(1086, 269),是不是必须得先给定坐标?那是因为click的底层逻辑move_to以及left_down、left_up都是需要PostMessageW来传递坐标信息才能完成的。也就是要进行鼠标点击,必须获得后台窗口虚拟鼠标的位置。
那么问题就变成了,我们如何获得后台窗口虚拟鼠标的位置?
文心一言的回答
方法一:文心一言都知道,pyautogui只能获取前台窗口的鼠标位置。
方法二:用win32api.GetCursorPos()获得鼠标坐标。结论:也是前台鼠标位置。
方法三:ChatGPT让我安裝一個鼠標鉤子來監視鼠標消息。在鼠標鉤子回調函數中,處理WM_MOUSEMOVE消息並提取鼠標位置信息。
钩子怎么写我就先不放了,如果有需要的我可以单独开一讲。直接说结论吧,——还是不行
方法四:参照https://www.cnpython.com/qa/1403927的回答,尝试Retrieves the cursor position for the last message retrieved by the GetMessage
function.因为win32gui里没有GetMessage,我们就自己造一个。
`def move_to(self, x, y, times=0.5):` `"""` `@description : 移动鼠标` `---------` `@param : 位置坐标x,y 单击后延时times(s)` `-------` `@Returns :` `-------` `"""` `global xx,yy` `xx=x` `yy=y` `self.__move_to(self.__clickhandle, int(x), int(y))` `time.sleep(times)`
在move_to里加了一对全局变量xx,yy,把鼠标位置坐标存在变量里,再写一个单击的函数:
`def leftclick(self, times=0.5):` `"""` `@description : 单击左键` `---------` `@param : 单击后延时times(s)` `-------` `@Returns :` `-------` `"""`` ` `self.left_down(self.__clickhandle, int(xx), int(yy))` `time.sleep(times)` `self.left_up(self.__clickhandle, int(xx), int(yy))` `time.sleep(times)`
注意这个函数只能在PostMessage后面才能得到鼠标坐标。当然也是没办法,我自己想了一个折中的办法。如果有更好的解决方案也请私信我。
点击下方安全链接前往获取
CSDN大礼包:《Python入门&进阶学习资源包》免费分享
👉Python实战案例👈
光学理论是没用的,要学会跟着一起敲,要动手实操,才能将自己的所学运用到实际当中去,这时候可以搞点实战案例来学习。
👉Python书籍和视频合集👈
观看零基础学习视频,看视频学习是最快捷也是最有效果的方式,跟着视频中老师的思路,从基础到深入,还是很容易入门的。
👉Python副业创收路线👈
这些资料都是非常不错的,朋友们如果有需要《Python学习路线&学习资料》,点击下方安全链接前往获取
CSDN大礼包:《Python入门&进阶学习资源包》免费分享
本文转自 网络,如有侵权,请联系删除。