python用底层库做自动化的流程_调试日记

1.先用关键词拿到窗口顶层句柄

win_name = "工作台"
hwnd, window_text = get_qianniu_hwnd(win_name)
if hwnd:
    print(f"找到的窗口句柄: {hwnd}, 窗口标题: '{window_text}'")
else:
    print("没有找到匹配的窗口。")

2.用拿到的句柄去遍历输出所有的子控件句柄 文本 和类名信息,根据输出信息判断哪些是可以直接用的 哪些是需要继续用类名去定位索引的

运行这步时所有子控件将高亮 有的控件不能直接用的还需要重复用第三步去找子控件

把输出的调试信息记录备用

hwnd = 8981440  # 父窗口句柄,替换为实际值
# print(f"窗口句柄: {hwnd} ,窗口标题: {control_text}, 类名{class_name}")
controls = find_controls_by_text_pattern(hwnd)

3.按照控件类名调试看哪些索引的控件是需要用上的 写到dict字典里面并测试点击 这一步如果嵌套在多层级的控件可用父级hwnd

hwnd = 8981440  # 父窗口句柄,替换为实际值
class_name = "StandardButton"  # 要查找的控件类名
controls_dict = find_controls_by_class_name(hwnd, class_name)
for key, hwnd in controls_dict.items():
    #在这里调试看哪些索引的控件是需要用上的 写到dict字典里面
    highlight_window(hwnd)

dict = {"点击接待中心": controls_dict[13]}
for key, hwnd in dict.items():
    print(f"控件索引{key} 对应的控件句柄: {hwnd}")
    click_control(hwnd)
    

4.按照编辑控件类名去找到需要的编辑框并测试编辑输入

import win32con
import win32api
import win32gui
import re
import time
def get_hwnd(win_name):
 """
 查找并返回指定名称的顶层窗口的句柄和标题。

 此函数通过枚举所有可见的顶层窗口,并使用正则表达式匹配窗口标题,
 来查找与给定名称匹配的窗口。一旦找到匹配的窗口,就返回其句柄和标题。
 如果没有找到匹配的窗口,则返回None。
 调用:
 win_name = "工作台"
 hwnd, window_text = get_qianniu_hwnd(win_name)
 if hwnd:
 print(f"找到的窗口句柄: {hwnd}, 窗口标题: '{window_text}'")
 else:
 print("没有找到匹配的窗口。")


 参数:
 - win_name: 字符串,要查找的窗口标题的一部分。这个名称将被用于正则表达式匹配,
 因此可以是部分标题或完整标题的正则表达式模式。

 返回值:
 - hwnd: 找到的窗口的句柄。如果没有找到匹配的窗口,则为None。
 - window_text: 找到的窗口的标题文本。如果没有找到匹配的窗口,则为None。
 """
 # 使用列表作为包装器,以便在内部函数中修改
 found_window = [None]

 def enum_window_proc(hwnd, lParam):
 """
 EnumWindows回调函数,用于检查每个顶层窗口是否为目标窗口。
 如果窗口标题与给定的正则表达式匹配,保存该窗口的句柄和标题。
 """
 if win32gui.IsWindowVisible(hwnd):
 window_text = win32gui.GetWindowText(hwnd)
 pattern = re.compile(lParam)
 if pattern.search(window_text):
 # 保存找到的窗口句柄和标题到列表的第一个元素
 found_window[0] = (hwnd, window_text)

 # 执行枚举所有顶层窗口的操作
 win32gui.EnumWindows(enum_window_proc, f".*{win_name}.*")

 # 检查是否找到了匹配的窗口,并返回结果
 if found_window[0]:
 return found_window[0]
 else:
 return None, None # 如果没有找到,返回None


def highlight_window(hwnd):
 """
 绘制一个红色矩形框以高亮显示指定窗口或控件。

 参数:
 - hwnd: 需要高亮显示的窗口或控件的句柄。

 说明:
 - 该函数获取目标窗口的设备上下文(DC),使用红色画笔在窗口的边缘绘制一个矩形框。
 这个矩形框可以用于视觉上标识和高亮显示特定的UI元素,非常适合用于UI自动化测试、调试,
 或者用户界面的演示中。
 - 注意,绘制的矩形框在窗口重绘时可能会消失,如果需要持续高亮,可能需要在适当时机重新调用此函数。
 """
 try:
 # 获取窗口的设备上下文(DC),用于绘图
 dc = win32gui.GetWindowDC(hwnd)
 # 设置画笔的样式、宽度和颜色
 red_pen = win32gui.CreatePen(win32con.PS_SOLID, 2, win32api.RGB(255, 0, 0)) # 红色画笔
 old_pen = win32gui.SelectObject(dc, red_pen)
 # 设置画刷为透明
 old_brush = win32gui.SelectObject(dc, win32gui.GetStockObject(win32con.NULL_BRUSH))
 # 获取窗口的边界
 left, top, right, bottom = win32gui.GetWindowRect(hwnd)
 # 转换坐标系统
 left, top = win32gui.ScreenToClient(hwnd, (left, top))
 right, bottom = win32gui.ScreenToClient(hwnd, (right, bottom))
 # 绘制矩形框
 win32gui.Rectangle(dc, left, top, right, bottom)
 # 恢复旧的画笔和画刷
 win32gui.SelectObject(dc, old_pen)
 win32gui.SelectObject(dc, old_brush)
 # 删除创建的画笔
 win32gui.DeleteObject(red_pen)
 # 释放设备上下文
 win32gui.ReleaseDC(hwnd, dc)
 except:
 print(f"{hwnd}这是一个无效句柄")



def find_controls_by_text_pattern(hwnd):
 """
 自动化测试工具:
 在指定窗口中查找文本匹配特定模式的所有子控件。
 调用示例:
hwnd = 8981440  # 父窗口句柄,替换为实际值
# print(f"窗口句柄: {hwnd} ,窗口标题: {control_text}, 类名{class_name}")
controls = find_controls_by_text_pattern(hwnd)
 参数:
 - hwnd: 父窗口或顶层窗口的句柄。

 返回值:
 - 一个字典,其中键是匹配到的文本,值是对应控件的句柄(hwnd)。
 """
 matched_controls = {}

 def enum_child_proc(hwnd, _):
 # 尝试获取控件的文本
 control_text = win32gui.GetWindowText(hwnd)
 class_name = win32gui.GetClassName(hwnd)
 # 检查文本是否匹配给定的模式
 matched_controls[control_text] = hwnd
 highlight_window(hwnd)
 print(f"窗口句柄: {hwnd} ,窗口标题: {control_text}, 类名{class_name}")
 # 这里只是为了演示,所以找到第一个匹配的窗口后就返回

 # 枚举所有子控件
 win32gui.EnumChildWindows(hwnd, enum_child_proc, None)

 return matched_controls

def click_control(hwnd):
    """
    模拟鼠标点击指定句柄(hwnd)的控件。
    调用:
        hwnd = 3284220  # 控件的句柄,替换为实际值
        click_control(hwnd)
    参数:
    - hwnd: 控件的句柄。
    """
    # 获取控件的客户区坐标(相对于控件的左上角)
    left, top, right, bottom = win32gui.GetClientRect(hwnd)
    # 计算点击位置(这里简单地取中点)
    click_x = left + (right - left) // 2
    click_y = top + (bottom - top) // 2

    # 将客户区坐标转换为屏幕坐标
    screen_x, screen_y = win32gui.ClientToScreen(hwnd, (click_x, click_y))

    # 发送鼠标点击消息
    win32api.SendMessage(hwnd, win32con.WM_LBUTTONDOWN, win32con.MK_LBUTTON, win32api.MAKELONG(click_x, click_y))
    win32api.SendMessage(hwnd, win32con.WM_LBUTTONUP, 0, win32api.MAKELONG(click_x, click_y))



def find_controls_by_class_name(hwnd, class_name):
    """
    枚举指定父窗口下所有匹配给定类名的子控件,并存储在字典中。
    调用:
        hwnd = 402930  # 父窗口句柄,替换为实际值
        class_name = "StandardButton"  # 要查找的控件类名
        controls_dict = find_controls_by_class_name(hwnd, class_name)
        dict={"点击搜索":controls_dict[15],"联系中":controls_dict[17],"最近联系":controls_dict[18],"我的好友":controls_dict[19]}
        for key, hwnd in dict.items():
            print(f"控件索引{key} 对应的控件句柄: {hwnd}")
            click_control(hwnd)
            time.sleep(1)
    参数:
    - parent_hwnd: 父窗口的句柄。
    - class_name: 要查找的控件类名。

    返回值:
    - 一个字典,键为控件的索引,值为对应的控件句柄。
    """
    controls_dict = {}

    def enum_child_proc(hwnd, lParam):
        if win32gui.GetClassName(hwnd) == class_name:
            # 将控件句柄添加到字典中,使用字典的当前长度作为索引
            lParam[len(lParam)] = hwnd
        return True

    # 使用闭包函数枚举子窗口
    win32gui.EnumChildWindows(hwnd, enum_child_proc, controls_dict)

    return controls_dict

 

猜你喜欢

转载自blog.csdn.net/dianqiyisheng/article/details/139042846