前提
pywin32
安装python包
pip install pywin32
pip install pillow
执行代码
import win32gui
import win32gui, re
from PIL import ImageGrab
class WindowMgr:
"""Encapsulates some calls to the winapi for window management"""
def __init__(self):
"""Constructor"""
self._handle = None
def find_window(self, class_name, window_name=None):
"""基于类名来查找窗口"""
self._handle = win32gui.FindWindow(class_name, window_name)
def _window_enum_callback(self, hwnd, class_name_wildcard_list):
"""传递给win32gui.EnumWindows(),检查所有打开的顶级窗口"""
class_name, wildcard = class_name_wildcard_list
if win32gui.GetClassName(hwnd) == class_name and re.match(wildcard,
str(win32gui.GetWindowText(hwnd))) is not None:
self._handle = hwnd
def find_window_wildcard(self, class_name, wildcard):
"""根据类名,查找一个顶级窗口,确保其类名相符,且标题可以用正则表达式匹配对应的通配符"""
self._handle = None
win32gui.EnumWindows(self._window_enum_callback, [class_name, wildcard])
return self._handle
def set_foreground(self):
"""put the window in the foreground"""
win32gui.SetForegroundWindow(self._handle)
def get_hwnd(self):
"""return hwnd for further use"""
return self._handle
def child_handler(cid, child_info_list):
rect = win32gui.GetWindowRect(cid)
class_name = win32gui.GetClassName(cid)
title = win32gui.GetWindowText(cid)
child_info_list.append([cid, title,class_name, rect])
def get_child_info(hid):
child_info_list = []
win32gui.EnumChildWindows(hid, child_handler, child_info_list)
return child_info_list
def _MyCallback(hwnd, extra):
windows = extra
temp = []
temp.append(hex(hwnd))
temp.append(win32gui.GetClassName(hwnd))
temp.append(win32gui.GetWindowText(hwnd))
windows[hwnd] = temp
def find_all_child_hid(hid):
res = []
def find_child_hid(hid, res, child_hid=None, class_name=None, title=None):
# 参数:父窗口句柄,子窗口句柄,子类名,子类标题
c_id = win32gui.FindWindowEx(hid, child_hid, class_name, title)
if c_id != 0:
res.append(c_id)
find_child_hid(hid, res, child_hid=c_id)
find_child_hid(hid, res)
return res
if __name__ == '__main__':
# hid = win32gui.FindWindow(None, "OBS*")
# myWindowMgr = WindowMgr()
# '''查找一个类名为XLMAIN,窗口标题中含【银行余额】字符串的窗口,并返回它的句柄;如果没找到,返回None'''
# excelHwnd = myWindowMgr.find_window_wildcard(None, "OBS*")
# print(excelHwnd)
windows = {}
win32gui.EnumWindows(_MyCallback, windows)
hld = win32gui.FindWindow("Qt631QWindowIcon", 'OBS 29.0.2 (64-bit, windows) - 配置文件: 未命名 - 场景: 未命名')
if hld is not None and hld > 0:
print("obs窗口找到")
# source = win32gui.FindWindowEx(hld, None, None, "来源")
# print("根据标题查找来源")
# print(source)
# source = find_all_child_hid(hld)
# print(source)
source = get_child_info(hld)
# print(source)
for item in source:
print(item)
# 截图保存
# image = ImageGrab.grab(item[3])
# image.show()
# image.save('target_'+str(item[0])+'.png')
# for i in source:
# title = win32gui.GetWindowText(i)
# classname = win32gui.GetClassName(i)
# print(title)
# print(classname)
# if source is not None and source > 0:
# print("来源窗口找到")
# items = win32gui.FindWindowEx(source, None, None, None)
# print("列表窗口")
只能获取到最外层窗体,获取不了列表信息就放弃了。
pywinauto
pip install pywinauto
pip install pillow
pip install opencv-python
pip install numpy
pip install matplotlib
代码如下
from pywinauto.application import Application
import cv2
import numpy as np
import os
import time
# 找图 返回最近似的点
def search_returnPoint(img, template, template_size):
"""
查找一张图片是否在另一张图片中的,如果在则返回位置
:param img:
:param template:
:param template_size:
:return:
"""
img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
template_ = cv2.cvtColor(template, cv2.COLOR_BGR2GRAY)
result = cv2.matchTemplate(img_gray, template_, cv2.TM_CCOEFF_NORMED)
threshold = 0.9
# res大于70%
loc = np.where(result >= threshold)
# 使用灰度图像中的坐标对原始RGB图像进行标记
point = ()
for pt in zip(*loc[::-1]):
cv2.rectangle(img, pt, (pt[0] + template_size[1], pt[1] + + template_size[0]), (7, 249, 151), 2)
point = pt
if point == ():
return (False, None, None)
return (True, point[0] + template_size[1] / 2, point[1])
def ifImgExist(big_img_path, search_img_path):
"""
查找一张图片是否在另一张图片中的,如果在则返回位置
:param big_img_path:
:param search_img_path:
:return:
"""
scale = 1
img = cv2.imdecode(np.fromfile(os.path.join(big_img_path), dtype=np.uint8),
cv2.IMREAD_COLOR) # cv2.imread(big_img_path) # 要找的大图
img = cv2.resize(img, (0, 0), fx=scale, fy=scale)
template = cv2.imdecode(np.fromfile(os.path.join(search_img_path), dtype=np.uint8),
cv2.IMREAD_COLOR) # cv2.imread(search_img_path) # 图中的小图
template = cv2.resize(template, (0, 0), fx=scale, fy=scale)
template_size = template.shape[:2]
return search_returnPoint(img, template, template_size)
if __name__ == '__main__':
base_dir = r"D:\livebroadcast\test01"
close_img = os.path.join(base_dir, "close.png")
open_img = os.path.join(base_dir, "open.png")
select_producut = "果冻面膜"
# select_producut = "玫瑰纯露"
app = Application(backend="uia").connect(title_re="OBS 29.0.2.*")
# 查到这个记事本的控件树
# dlg_spec = app['无标题 - Notepad']
# dlg_spec.print_control_identifiers()
win = app["OBS 29.0.2 (64-bit, windows) - 配置文件: 未命名 - 场景: 未命名"]
con_list = win.child_window(title=u"来源")
# con_list.print_control_identifiers()
lists = con_list.child_window(control_type="List")
# lists.print_control_identifiers()
lists_children = lists.children()
for child in lists_children:
name = child.element_info.name
if name != "背景" and name != "窗口采集":
screen_shot_path = os.path.join(base_dir, child.element_info.name + "_" + str(int(time.time())) + '.png')
child.capture_as_image().save(screen_shot_path)
if (name == select_producut):
# 展示选中图像
exist_img = ifImgExist(screen_shot_path, close_img)
if (exist_img[0] == True):
# 如果图像没有打开则打开
# child.click(coords=(exist_img[1], exist_img[2])) #这种方式报错
coords = child.rectangle()
mouse_coord = (int(exist_img[1]),
int((coords.bottom - coords.top) / 2) + int(exist_img[2]))
child.click_input(coords=mouse_coord)# 相对偏移
else:
# 关闭其他图像
exist_img = ifImgExist(screen_shot_path, open_img)
if (exist_img[0] == True):
# 如果图像没有关闭则关闭
print("图像没有关闭")
coords = child.rectangle()
mouse_coord = (int(exist_img[1]),
int((coords.bottom - coords.top) / 2) + int(exist_img[2]))
child.click_input(coords=mouse_coord)
else:
# 如果图像已经关闭则不用关闭
print("图像已经关闭")
# real_lists = lists.child_window(control_type="ListItem")
print("结束")