如何对非顶层EVE Online窗口截图?现有Python代码返回黑屏
解决EVE Online非顶层窗口截图全黑及HBITMAP处理问题
一、解决全黑截图问题
EVE Online采用Direct3D硬件加速渲染,普通GDI截图(如BitBlt)无法捕获显存中的渲染内容,导致截图全黑。推荐两种可行方案:
1. 使用PrintWindow并指定PW_RENDERFULLCONTENT参数
该参数会强制窗口完整渲染内容,包括Direct3D绘制的部分:
import win32gui import win32ui import win32con from PIL import Image def capture_eve_window(hwnd): # 获取窗口客户区尺寸 left, top, right, bottom = win32gui.GetClientRect(hwnd) width = right - left height = bottom - top # 获取窗口DC并创建兼容DC hwnd_dc = win32gui.GetWindowDC(hwnd) mfc_dc = win32ui.CreateDCFromHandle(hwnd_dc) save_dc = mfc_dc.CreateCompatibleDC() # 创建兼容位图 save_bitmap = win32ui.CreateBitmap() save_bitmap.CreateCompatibleBitmap(mfc_dc, width, height) save_dc.SelectObject(save_bitmap) # 调用PrintWindow,传入强制渲染参数 PW_RENDERFULLCONTENT = 0x00000002 win32gui.PrintWindow(hwnd, save_dc.GetSafeHdc(), PW_RENDERFULLCONTENT) # 将HBITMAP转换为PIL Image bmp_info = save_bitmap.GetInfo() bmp_str = save_bitmap.GetBitmapBits(True) img = Image.frombuffer('RGB', (bmp_info['bmWidth'], bmp_info['bmHeight']), bmp_str, 'raw', 'BGRX', 0, 1) # 释放资源 win32gui.DeleteObject(save_bitmap.GetHandle()) save_dc.DeleteDC() mfc_dc.DeleteDC() win32gui.ReleaseDC(hwnd, hwnd_dc) return img
2. 使用DWM窗口缩略图(更稳定)
若PrintWindow仍失效,可通过桌面窗口管理器(DWM)获取窗口缩略图数据:
import win32gui import ctypes from PIL import Image # 定义DWM相关结构体 class DWM_THUMBNAIL_PROPERTIES(ctypes.Structure): _fields_ = [ ("dwFlags", ctypes.c_uint), ("rcDestination", ctypes.wintypes.RECT), ("rcSource", ctypes.wintypes.RECT), ("opacity", ctypes.c_byte), ("fVisible", ctypes.c_bool), ("fSourceClientAreaOnly", ctypes.c_bool) ] DWM_TNP_VISIBLE = 0x00000002 DwmRegisterThumbnail = ctypes.windll.dwmapi.DwmRegisterThumbnail DwmUpdateThumbnailProperties = ctypes.windll.dwmapi.DwmUpdateThumbnailProperties DwmUnregisterThumbnail = ctypes.windll.dwmapi.DwmUnregisterThumbnail def capture_eve_dwm(hwnd): # 创建隐藏窗口接收缩略图 hwnd_thumb = win32gui.CreateWindowEx(0, win32gui.GetStockObject(win32con.WNDCLASS), "", 0, 0, 0, 1, 1, 0, 0, 0, None) # 注册窗口缩略图 h_thumb = ctypes.c_uint() DwmRegisterThumbnail(hwnd_thumb, hwnd, ctypes.byref(h_thumb)) # 获取目标窗口尺寸 left, top, right, bottom = win32gui.GetClientRect(hwnd) width = right - left height = bottom - top # 设置缩略图属性 props = DWM_THUMBNAIL_PROPERTIES() props.dwFlags = DWM_TNP_VISIBLE props.fVisible = True props.rcDestination = ctypes.wintypes.RECT(0, 0, width, height) DwmUpdateThumbnailProperties(h_thumb, ctypes.byref(props)) # 截取缩略图窗口内容 hwnd_dc = win32gui.GetWindowDC(hwnd_thumb) mfc_dc = win32ui.CreateDCFromHandle(hwnd_dc) save_dc = mfc_dc.CreateCompatibleDC() save_bitmap = win32ui.CreateBitmap() save_bitmap.CreateCompatibleBitmap(mfc_dc, width, height) save_dc.SelectObject(save_bitmap) save_dc.BitBlt((0,0), (width, height), mfc_dc, (0,0), win32con.SRCCOPY) # 转换为PIL Image bmp_info = save_bitmap.GetInfo() bmp_str = save_bitmap.GetBitmapBits(True) img = Image.frombuffer('RGB', (bmp_info['bmWidth'], bmp_info['bmHeight']), bmp_str, 'raw', 'BGRX', 0, 1) # 清理资源 DwmUnregisterThumbnail(h_thumb) win32gui.DestroyWindow(hwnd_thumb) win32gui.DeleteObject(save_bitmap.GetHandle()) save_dc.DeleteDC() mfc_dc.DeleteDC() win32gui.ReleaseDC(hwnd_thumb, hwnd_dc) return img
二、处理CreateCompatibleBitmap生成的HBITMAP
CreateCompatibleBitmap返回的HBITMAP句柄,在Python中可通过以下步骤转换为可操作图像:
- 调用
GetBitmapBits()获取位图原始字节数据 - 结合
GetInfo()获取的宽高信息,用PIL的Image.frombuffer()解析(注意GDI位图颜色格式为BGRX,需转换为RGB)
核心转换代码片段:
bmp_info = save_bitmap.GetInfo() bmp_str = save_bitmap.GetBitmapBits(True) img = Image.frombuffer('RGB', (bmp_info['bmWidth'], bmp_info['bmHeight']), bmp_str, 'raw', 'BGRX', 0, 1)
若需转换为numpy数组,直接执行:
import numpy as np img_np = np.array(img)
内容的提问来源于stack exchange,提问作者Mr.Z
相关产品推荐
相关产品推荐

