屏幕截图的尺寸与 Pywin32 中调整大小 window 的尺寸不匹配

Dimensions of screenshot doesn't match dimensions of resized window in Pywin32

我正在尝试使用 pywin32 截取 Microsoft Edge window。此屏幕截图随后将用于机器学习算法以在 Microsoft Edge 中玩游戏。正如您可能猜到的那样,该程序将多次截取屏幕截图,因此我需要屏幕截图尽可能快。为了提高速度,我的程序会将 Microsoft Edge window 调整为较小的分辨率(具体来说,调整为 600 x 600)。然而,当屏幕截图没有显示完整时 window 即使我已将其移动到指定位置。

我的程序:

import win32gui 
import win32ui 
import win32con 
import win32api  
from PIL import Image
import time



# grab a handle to the main desktop window 
hdesktop = win32gui.GetDesktopWindow() 

 
# determine the size of all monitors in pixels 
width = 600
height = 600 
left = 0 
top = 0 
 
# set window to correct location
print("You have 3 second to click the desired window!")
for i in range(3, 0, -1):
    print(i)
    time.sleep(1)
hwnd = win32gui.GetForegroundWindow()
win32gui.MoveWindow(hwnd, 0, 0, width, height, True)
 
# create a device context 
desktop_dc = win32gui.GetWindowDC(hdesktop) 
img_dc = win32ui.CreateDCFromHandle(desktop_dc) 
 
# create a memory based device context 
mem_dc = img_dc.CreateCompatibleDC() 
 
# create a bitmap object 
screenshot = win32ui.CreateBitmap() 
screenshot.CreateCompatibleBitmap(img_dc, width, height) 
mem_dc.SelectObject(screenshot) 
 
 
# copy the screen into our memory device context 
mem_dc.BitBlt((0, 0), (width, height), img_dc, (left, top),win32con.SRCCOPY) 
 

bmpinfo = screenshot.GetInfo()
bmpstr = screenshot.GetBitmapBits(True)
im = Image.frombuffer(
    'RGB',
    (bmpinfo['bmWidth'], bmpinfo['bmHeight']),
    bmpstr, 'raw', 'BGRX', 0, 1)

im.show()
# free our objects 
mem_dc.DeleteDC() 
win32gui.DeleteObject(screenshot.GetHandle()) 

我的程序首先通过win32gui.MoveWindow(hwnd, 0, 0, width, height, True)移动并调整所需的window(取自win32gui.GetForegroundWindow())的大小然后,它尝试通过截取整个桌面来截取window window (hdesktop = win32gui.GetDesktopWindow() ) 然后将其裁剪到所需的坐标 (mem_dc.BitBlt((0, 0), (width, height), img_dc, (left, top),win32con.SRCCOPY) )。然后,我将 win32 屏幕截图转换为 PIL 图像,以便查看。请注意,所需坐标与最初用于移动 window 的坐标相同。但是,当我尝试 运行 这个程序时,屏幕截图并没有捕获整个 window!

我已尝试查看 MoveWindowBitBlt 函数的文档,但找不到问题所在。由于 MoveWindow 函数,目标和源矩形参数假定为 (0,0)。宽度和高度参数相同。我也尝试过使用 bRepaint 参数进行试验,但没有什么不同。

有什么建议吗?


在对这个问题进行了更多的试验之后,我终于找到了问题所在。 在评论中,我说 ctypes.windll.shcore.SetProcessDpiAwareness(1) 不起作用。然而,它做到了。当我放大高度和宽度时,屏幕截图和 window 之间的尺寸非常适合。但是,宽度和高度不适用于较小尺寸的原因(我最初将宽度和高度设置为 500)是因为 Microsoft Edge 不允许这样做。如果宽度在某个阈值内,则 window 的实际宽度将变为 Microsoft Edge 希望的最小宽度。一个简单的解决方法是将宽度和高度设置为更大的分辨率,并且成功了!

非常感谢评论中的每一个人,尤其是@IInspectable。