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
|