屏幕截图的尺寸与 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!
我已尝试查看 MoveWindow
和 BitBlt
函数的文档,但找不到问题所在。由于 MoveWindow
函数,目标和源矩形参数假定为 (0,0)。宽度和高度参数相同。我也尝试过使用 bRepaint
参数进行试验,但没有什么不同。
有什么建议吗?
在对这个问题进行了更多的试验之后,我终于找到了问题所在。
在评论中,我说 ctypes.windll.shcore.SetProcessDpiAwareness(1)
不起作用。然而,它做到了。当我放大高度和宽度时,屏幕截图和 window 之间的尺寸非常适合。但是,宽度和高度不适用于较小尺寸的原因(我最初将宽度和高度设置为 500)是因为 Microsoft Edge 不允许这样做。如果宽度在某个阈值内,则 window 的实际宽度将变为 Microsoft Edge 希望的最小宽度。一个简单的解决方法是将宽度和高度设置为更大的分辨率,并且成功了!
非常感谢评论中的每一个人,尤其是@IInspectable。
我正在尝试使用 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!
我已尝试查看 MoveWindow
和 BitBlt
函数的文档,但找不到问题所在。由于 MoveWindow
函数,目标和源矩形参数假定为 (0,0)。宽度和高度参数相同。我也尝试过使用 bRepaint
参数进行试验,但没有什么不同。
有什么建议吗?
在对这个问题进行了更多的试验之后,我终于找到了问题所在。
在评论中,我说 ctypes.windll.shcore.SetProcessDpiAwareness(1)
不起作用。然而,它做到了。当我放大高度和宽度时,屏幕截图和 window 之间的尺寸非常适合。但是,宽度和高度不适用于较小尺寸的原因(我最初将宽度和高度设置为 500)是因为 Microsoft Edge 不允许这样做。如果宽度在某个阈值内,则 window 的实际宽度将变为 Microsoft Edge 希望的最小宽度。一个简单的解决方法是将宽度和高度设置为更大的分辨率,并且成功了!
非常感谢评论中的每一个人,尤其是@IInspectable。