# 需要安装pywin32,numpy,cv2模块
import time
import win32api
import win32con
import win32gui
import win32ui
import numpy
import cv2
class Util(object):
def __init__(self, hwnd) -> None:
self.hwnd = hwnd
def capture_screen(self):
try:
left, top, right, bot = win32gui.GetWindowRect(self.hwnd)
width = right - left
height = bot - top
# 返回句柄窗口的设备环境,覆盖整个窗口,包括非客户区,标题栏,菜单,边框
while self.hwnd == 0:
print('hwnd==0')
return
hWndDC = win32gui.GetWindowDC(self.hwnd)
# 创建设备描述表
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, (0, 0), win32con.SRCCOPY)
# 方法三(第一部分):opencv+numpy保存
# 获取位图信息
signedIntsArray = saveBitMap.GetBitmapBits(True)
# 方法三(第二部分):opencv+numpy保存
# PrintWindow成功,保存到文件,显示到屏幕
im_opencv = numpy.frombuffer(signedIntsArray, dtype='uint8')
im_opencv.shape = (height, width, 4)
cv2.cvtColor(im_opencv, cv2.COLOR_BGRA2RGB)
cv2.imencode(".bmp", im_opencv)[1].tofile('截图'+str(self.hwnd)+'.bmp')
# 内存释放
win32gui.DeleteObject(saveBitMap.GetHandle())
saveDC.DeleteDC()
mfcDC.DeleteDC()
win32gui.ReleaseDC(self.hwnd, hWndDC)
# cv2.namedWindow('im_opencv') #命名窗口
# cv2.imshow("im_opencv",im_opencv) #显示
# cv2.waitKey(0)
# cv2.destroyAllWindows()
# 方法一
# saveBitMap.SaveBitmapFile(saveDC,"img_Winapi.bmp")
return
except :
print('异常')
def get_hwnd(title):
hwnd = win32gui.FindWindow(0, title)
return hwnd
def get_son_hwnd(parent):
if not parent:
return
son_hwnd = []
win32gui.EnumChildWindows(
parent, lambda hwnd, param: param.append(hwnd), son_hwnd)
print('son_hwnd:', son_hwnd)
return son_hwnd[0]
def get_window_hwnd():
return win32gui.GetDesktopWindow()
def click(self, x, y):
posi = win32api.MAKELONG(int(x), int(y))
win32api.SendMessage(self.hwnd, win32con.WM_LBUTTONDOWN,
win32con.MK_LBUTTON, posi)
win32api.SendMessage(self.hwnd, win32con.WM_LBUTTONUP,
win32con.MK_LBUTTON, posi)
def swipe(self, template, similarity, numb1: int, numb2: int):
while True:
time.sleep(3)
self.capture_screen()
tmp = self.match_template(template, similarity)
if max(numb2, numb1) > len(tmp[1]):
continue
else:
posi = win32api.MAKELONG(
int(tmp[1][numb1][0]), int(tmp[1][numb1][1]))
posi2 = win32api.MAKELONG(
int(tmp[1][numb2][0]), int(tmp[1][numb2][1]))
win32api.SendMessage(self.hwnd, win32con.WM_LBUTTONDOWN,
win32con.MK_LBUTTON, posi)
win32api.SendMessage(self.hwnd, win32con.WM_MOUSEMOVE, 0, 0)
win32api.SendMessage(self.hwnd, win32con.WM_LBUTTONUP,
win32con.MK_LBUTTON, posi2)
time.sleep(5)
self.capture_screen()
return
def find_and_click(self, template, similarity):
while True:
if self.find_image(template, similarity)[0] is True:
posi = self.find_image(template, similarity)
self.click(posi[1][0], posi[1][1])
time.sleep(3)
self.capture_screen()
if self.find_image(template, similarity)[0] is True:
self.find_and_click(template, similarity)
return posi
else:
return posi
time.sleep(10)
self.capture_screen()
def find_click_once(self, template, similarity):
while True:
if self.find_image(template, similarity)[0] is True:
posi = self.find_image(template, similarity)
self.click(posi[1][0], posi[1][1])
return posi
self.capture_screen()
def find_two_click(self, template1, template2, similarity):
while True:
self.capture_screen()
t = self.find_image(template1, similarity)
if t[0] is True:
tmp = self.match_template(template2, similarity)
min = 1000
x = 0
y = 0
for i in tmp[1]:
if abs(i[1]-t[1][1]) < min:
min = abs(i[1]-t[1][1])
x = i[0]
y = i[1]
self.click(x, y)
print(x, y)
return (x, y)
def find_all_and_click(self, template, similarity, numb):
while True:
tmp = self.match_template(template, similarity)
if tmp[0] is True:
if len(tmp[1]) > numb:
self.click(tmp[1][numb][0], tmp[1][numb][1])
print(tmp)
return tmp
self.capture_screen()
# TM_CCOEFF相关系数匹配
# TM_CCOEFF_NORMED归一化相关系数匹配
# TM_CCORR相关匹配.模板图像相乘,数值大最佳匹配,数值小最差匹配
# TM_CCORR_NORMED归一化相关匹配
# TM_SQDIFF平方差匹配.最佳匹配=0
# TM_SQDIFF_NORMED标准平方差匹配
def find_image(self, template: str, similarity: float):
try:
scr = cv2.imdecode(numpy.fromfile(
'截图'+str(self.hwnd)+'.bmp', dtype=numpy.uint8), 0)
tp = cv2.imdecode(numpy.fromfile(template, dtype=numpy.uint8), 0)
result = cv2.matchTemplate(scr, tp, cv2.TM_CCOEFF_NORMED)
except cv2.error:
print('file error')
return False, None
h, w = tp.shape[:2]
min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(result)
if max_val < similarity:
return False, None
else:
posi = (max_loc[0]+w//2, max_loc[1]+h//2,
max_loc[0], max_loc[1]-h, max_loc[0]+w, max_loc[1]-h)
return True, posi
def match_template(self, template: str, similarity: float):
try:
scr = cv2.imdecode(numpy.fromfile(
'截图'+str(self.hwnd)+'.bmp', dtype=numpy.uint8), 0)
tp = cv2.imdecode(numpy.fromfile(template, dtype=numpy.uint8), 0)
except cv2.error:
print('file err')
posi = []
h, w = tp.shape[:2]
match = cv2.matchTemplate(scr, tp, cv2.TM_CCOEFF_NORMED)
indices = (-match).argpartition(100, axis=None)[:100]
unreveled_indices = numpy.array(
numpy.unravel_index(indices, match.shape)).T
for location in unreveled_indices:
y, x = location
confidence = match[y][x]
if confidence >= similarity:
posi.append((x+w//2, y+h//2))
tmp = [] # 接收posi坐标
for i in range(len(posi)-1):
for j in range(i+1, len(posi)):
if abs(posi[i][0]-posi[j][0]) <= 3 and abs(posi[i][1]-posi[j][1]) <= 3:
tmp.append(j)
for i in reversed(list(set(tmp))):
posi.pop(i)
posi.sort(key=lambda x: x[1])
return True, posi
可以使用按键精灵的按键抓抓
def get_child_windows(parent):
'''
获得parent的所有子窗口句柄
返回子窗口句柄列表
'''
if not parent:
return
hwndChildList = []
win32gui.EnumChildWindows(parent, lambda hwnd, param: param.append(hwnd), hwndChildList)
return hwndChildList