admin
2025-06-10 568c763084b926a6f2d632b7ac65b9ec8280752f
win32_util.py
@@ -2,30 +2,71 @@
import cv2
import numpy
import win32api
import win32con
import win32gui
import win32ui
import ctypes
from ctypes import wintypes
from utils import invalid_hwnds_manager
def is_visible(hwnd):
    return win32gui.IsWindowVisible(hwnd)
# 定义常量
SMTO_NORMAL = 0x0000
SMTO_BLOCK = 0x0001
SMTO_ABORTIFHUNG = 0x0002
SMTO_NOTIMEOUTIFNOTHUNG = 0x0008
text_hwnds_doing = set()
def get_title(hwnd):
    length = ctypes.c_int(256)
    buffer = ctypes.create_unicode_buffer(length.value)
    ctypes.windll.user32.SendMessageTimeoutW(
        hwnd,
        ctypes.c_int(0x000D),  # WM_GETTEXT
        ctypes.c_int(255),
        ctypes.c_void_p(buffer),
        ctypes.c_int(0x0002),  # SMTO_ABORTIFHUNG
        ctypes.c_int(1000),
        ctypes.pointer(ctypes.c_int(0))
    )
    return buffer.value
def getText(hwnd):
    bufSize = win32gui.SendMessage(hwnd, win32con.WM_GETTEXTLENGTH, 0, 0) + 1
    buffer = array.array('b', b'\x00\x00' * bufSize)
    win32gui.SendMessage(hwnd, win32con.WM_GETTEXT, bufSize, buffer)
    text = win32gui.PyGetString(buffer.buffer_info()[0], bufSize - 1)
    return text.replace("\x00", "").strip()
    text_hwnds_doing.add(hwnd)
    try:
        bufSize = win32gui.SendMessage(hwnd, win32con.WM_GETTEXTLENGTH, 0, 0) + 1
        buffer = array.array('b', b'\x00\x00' * bufSize)
        win32gui.SendMessage(hwnd, win32con.WM_GETTEXT, bufSize, buffer)
        text = win32gui.PyGetString(buffer.buffer_info()[0], bufSize - 1)
        return text.replace("\x00", "").strip()
    finally:
        text_hwnds_doing.discard(hwnd)
# 根据标题模糊匹配
def search_window(title):
def search_window(title, max_count=3):
    invalid_hwnds = invalid_hwnds_manager.get_hwnds()
    hwnds = []
    try:
        hwnd = win32gui.GetDesktopWindow()
        temp = None
        while True:
            if temp and win32gui.IsWindowVisible(temp):
                str_ = getText(temp)
                if str_.find(title) > -1:
                    hwnds.append(temp)
            if temp not in invalid_hwnds:
                if temp and win32gui.IsWindowVisible(temp):
                    str_ = getText(temp)
                    if str_.find(title) > -1:
                        hwnds.append(temp)
                        if len(hwnds) >= max_count:
                            break
            temp = win32gui.FindWindowEx(hwnd, temp, None, None)
            if not temp:
                break
@@ -51,7 +92,7 @@
# rect格式为:(左,上,右,下坐标)
def window_capture(hwnd, rect, scale):
def window_capture(hwnd, rect, scale, is_test=False):
    rect_ = win32gui.GetWindowRect(hwnd)
    ow = rect_[2] - rect_[0]
    oh = rect_[3] - rect_[1]
@@ -69,15 +110,40 @@
    saveDC = mfcDC.CreateCompatibleDC()
    # 创建位图对象准备保存图片
    saveBitMap = win32ui.CreateBitmap()
    # 为bitmap开辟存储空间
    saveBitMap.CreateCompatibleBitmap(mfcDC, w, h)
    # 将截图保存到saveBitMap中
    saveDC.SelectObject(saveBitMap)
    # 保存bitmap到内存设备描述表
    saveDC.BitBlt((0, 0), (ow, h), mfcDC, (rect[0], rect[1]), win32con.SRCCOPY)
    # saveDC.BitBlt((0, 0), (w, h), mfcDC, (0, 0), win32con.SRCCOPY)
    # 保存数据
    # saveBitMap.SaveBitmapFile(saveDC, "test.png")
    if not is_test:
        # 为bitmap开辟存储空间
        saveBitMap.CreateCompatibleBitmap(mfcDC, w, h)
        # 将截图保存到saveBitMap中
        saveDC.SelectObject(saveBitMap)
        # 保存bitmap到内存设备描述表
        saveDC.BitBlt((0, 0), (ow, h), mfcDC, (rect[0], rect[1]), win32con.SRCCOPY)
    else:
        # 为bitmap开辟存储空间
        saveBitMap.CreateCompatibleBitmap(mfcDC, ow, oh)
        # 将截图保存到saveBitMap中
        saveDC.SelectObject(saveBitMap)
        # 保存bitmap到内存设备描述表
        saveDC.BitBlt((0, 0), (ow, oh), mfcDC, (0, 0), win32con.SRCCOPY)
        # 保存数据
        saveBitMap.SaveBitmapFile(saveDC, "test_origin.png")
        # 内存释放
        win32gui.DeleteObject(saveBitMap.GetHandle())
        saveDC.DeleteDC()
        mfcDC.DeleteDC()
        win32gui.ReleaseDC(hwnd, hWndDC)
        #########################保存最新的数据##########################
        hWndDC = win32gui.GetWindowDC(hwnd)
        mfcDC = win32ui.CreateDCFromHandle(hWndDC)
        saveDC = mfcDC.CreateCompatibleDC()
        # 创建位图对象准备保存图片
        saveBitMap = win32ui.CreateBitmap()
        saveBitMap.CreateCompatibleBitmap(mfcDC, w, h)
        # 将截图保存到saveBitMap中
        saveDC.SelectObject(saveBitMap)
        saveDC.BitBlt((0, 0), (ow, h), mfcDC, (rect[0], rect[1]), win32con.SRCCOPY)
        saveBitMap.SaveBitmapFile(saveDC, "test_origin_clip.png")
    signedIntsArray = saveBitMap.GetBitmapBits(True)
@@ -93,6 +159,26 @@
    return im_opencv
def move_window(hwnd, x, y):
    """
    移动窗口
    :param hwnd:
    :param x:
    :param y:
    :return:
    """
    try:
        # 获取窗口的当前矩形区域
        rect = win32gui.GetWindowRect(hwnd)
        width = rect[2] - rect[0]
        height = rect[3] - rect[1]
        # 移动窗口到指定位置 (x, y),并保持窗口的宽度和高度不变
        win32gui.MoveWindow(hwnd, x, y, width, height, True)
        print(f"窗口已移动到位置 ({x}, {y})")
    except Exception as e:
        print(f"移动窗口失败: {e}")
if __name__ == "__main__":
    # print(search_window("副屏1"))
    # visual_click(0x00152876, (110, 90))