import array 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): 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, max_count=3): invalid_hwnds = invalid_hwnds_manager.get_hwnds() hwnds = [] try: hwnd = win32gui.GetDesktopWindow() temp = None while True: 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 except: pass return hwnds def visual_click(hwnd, pos): position = pos[1] * pow(16, 4) + pos[0] win32gui.PostMessage(hwnd, win32con.WM_LBUTTONDOWN, 0x00000001, position) win32gui.PostMessage(hwnd, win32con.WM_LBUTTONUP, 0x00000000, position) def visual_keyboard(hwnd, code): win32gui.PostMessage(hwnd, win32con.WM_KEYDOWN, code, 0) win32gui.PostMessage(hwnd, win32con.WM_KEYUP, code, 0) def visual_keyboard_F5(hwnd): win32gui.PostMessage(hwnd, win32con.WM_KEYDOWN, win32con.VK_F5, 0) win32gui.PostMessage(hwnd, win32con.WM_KEYUP, win32con.VK_F5, 0) # rect格式为:(左,上,右,下坐标) def window_capture(hwnd, rect, scale, is_test=False): rect_ = win32gui.GetWindowRect(hwnd) ow = rect_[2] - rect_[0] oh = rect_[3] - rect_[1] ow = int(ow * scale) oh = int(oh * scale) w = rect[2] - rect[0] h = rect[3] - rect[1] if w == 0 or h == 0: return None # 返回句柄窗口的设备环境,覆盖整个窗口,包括非客户区,标题栏,菜单,边框 hWndDC = win32gui.GetWindowDC(hwnd) # 创建设备描述表 mfcDC = win32ui.CreateDCFromHandle(hWndDC) # 创建内存设备描述表 saveDC = mfcDC.CreateCompatibleDC() # 创建位图对象准备保存图片 saveBitMap = win32ui.CreateBitmap() 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) # 内存释放 win32gui.DeleteObject(saveBitMap.GetHandle()) saveDC.DeleteDC() mfcDC.DeleteDC() win32gui.ReleaseDC(hwnd, hWndDC) im_opencv = numpy.frombuffer(signedIntsArray, dtype='uint8') im_opencv.shape = (h, w, 4) cv2.cvtColor(im_opencv, cv2.COLOR_BGRA2RGB) 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)) window_capture(0x00010986, (0, 0, 1920, 895)) # pass