CreateDCFromHandle select object Python 中的 TOP 坐标
CreateDCFromHandle select object TOP coordinate in Python
我需要在 Windows 上捕获特定应用程序 window,即使它没有聚焦或在前台,也没有 window 的顶部 header bar,为了简单起见,我在 'application_window_topbar_size' 变量中手动指定了哪个高度。
monitor_info = GetMonitorInfo(MonitorFromPoint((0,0))) # get screen information
work_area = monitor_info.get("Work")
screen_width = work_area[2] # if taskbar is on the left
screen_height = work_area[3] # if taskbar is on the left
target_window_hwnd = win32gui.FindWindow(None, ("Math Analysis - Google Chrome"))
application_window_topbar_size = 200 # just roughly for testing
hwndDC = win32gui.GetWindowDC(target_window_hwnd)
mfcDC = win32ui.CreateDCFromHandle(hwndDC)
saveDC = mfcDC.CreateCompatibleDC()
saveBitMap = win32ui.CreateBitmap()
saveBitMap.CreateCompatibleBitmap(mfcDC, screen_width, screen_height)
saveDC.SelectObject(saveBitMap)
# saveDC.BitBlt((0, 0), (screen_width, screen_height), mfcDC, (0, application_window_topbar_size),win32con.SRCCOPY)
result = windll.user32.PrintWindow(target_window_hwnd, saveDC.GetSafeHdc(), 3)
bmpinfo = saveBitMap.GetInfo()
bmpstr = saveBitMap.GetBitmapBits(True)
screen_image = Image.frombuffer('RGB', (bmpinfo['bmWidth'], bmpinfo['bmHeight']), bmpstr, 'raw', 'BGRX', 0, 1)
win32gui.DeleteObject(saveBitMap.GetHandle())
saveDC.DeleteDC()
mfcDC.DeleteDC()
win32gui.ReleaseDC(target_window_hwnd, hwndDC)
捕获例程应该适用于 windows 句柄“WM_PRINT”(感谢 IInspectable 的评论),但是 我无法弄清楚如何设置捕获区域的TOP坐标。换句话说,我想在没有顶栏的情况下捕获目标window。改变高度是一回事,从逻辑上讲,如果捕获矩形坐标从 0,0 开始,那么它只切割 window 的底部区域,而不是顶部。我尝试使用 BitBlt()
但失败了。
---------------- 以下替代版本基于 IInspectable 评论
target_window_hwnd = win32gui.FindWindow(None, ("Math Analysis - Google Chrome"))
application_window_topbar_size = 200 # just roughly for testing
hwndDC = win32gui.GetWindowDC(target_window_hwnd)
mfcDC = win32ui.CreateDCFromHandle(hwndDC)
saveDC = mfcDC.CreateCompatibleDC()
saveBitMap = win32ui.CreateBitmap()
l, t, r, b = win32gui.GetClientRect(target_window_hwnd)
screen_width = r - l
screen_height = b -t
saveBitMap.CreateCompatibleBitmap(mfcDC, screen_width, screen_height)
saveDC.SelectObject(saveBitMap)
result = windll.user32.PrintWindow(target_window_hwnd, saveDC.GetSafeHdc(), 3)
bmpinfo = saveBitMap.GetInfo()
bmpstr = saveBitMap.GetBitmapBits(True)
screen_image = Image.frombuffer('RGB', (bmpinfo['bmWidth'], bmpinfo['bmHeight']), bmpstr, 'raw', 'BGRX', 0, 1)
win32gui.DeleteObject(saveBitMap.GetHandle())
saveDC.DeleteDC()
mfcDC.DeleteDC()
win32gui.ReleaseDC(target_window_hwnd, hwndDC)
仍然,改变顶部坐标只影响高度,不影响捕获的内容(能够只捕获 window 的 'document area',不包括地址 bar/toolbar)。
经过长时间的搜索和尝试,我意识到最明显的解决方案是在制作屏幕截图后对其进行裁剪。这样,不需要的部分(在我的例子中是顶部栏)可以很容易地去掉。
使用 PIL Image 可以轻松裁剪:
box = (left, top, right, bottom)
screen_image.crop(box)
我需要在 Windows 上捕获特定应用程序 window,即使它没有聚焦或在前台,也没有 window 的顶部 header bar,为了简单起见,我在 'application_window_topbar_size' 变量中手动指定了哪个高度。
monitor_info = GetMonitorInfo(MonitorFromPoint((0,0))) # get screen information
work_area = monitor_info.get("Work")
screen_width = work_area[2] # if taskbar is on the left
screen_height = work_area[3] # if taskbar is on the left
target_window_hwnd = win32gui.FindWindow(None, ("Math Analysis - Google Chrome"))
application_window_topbar_size = 200 # just roughly for testing
hwndDC = win32gui.GetWindowDC(target_window_hwnd)
mfcDC = win32ui.CreateDCFromHandle(hwndDC)
saveDC = mfcDC.CreateCompatibleDC()
saveBitMap = win32ui.CreateBitmap()
saveBitMap.CreateCompatibleBitmap(mfcDC, screen_width, screen_height)
saveDC.SelectObject(saveBitMap)
# saveDC.BitBlt((0, 0), (screen_width, screen_height), mfcDC, (0, application_window_topbar_size),win32con.SRCCOPY)
result = windll.user32.PrintWindow(target_window_hwnd, saveDC.GetSafeHdc(), 3)
bmpinfo = saveBitMap.GetInfo()
bmpstr = saveBitMap.GetBitmapBits(True)
screen_image = Image.frombuffer('RGB', (bmpinfo['bmWidth'], bmpinfo['bmHeight']), bmpstr, 'raw', 'BGRX', 0, 1)
win32gui.DeleteObject(saveBitMap.GetHandle())
saveDC.DeleteDC()
mfcDC.DeleteDC()
win32gui.ReleaseDC(target_window_hwnd, hwndDC)
捕获例程应该适用于 windows 句柄“WM_PRINT”(感谢 IInspectable 的评论),但是 我无法弄清楚如何设置捕获区域的TOP坐标。换句话说,我想在没有顶栏的情况下捕获目标window。改变高度是一回事,从逻辑上讲,如果捕获矩形坐标从 0,0 开始,那么它只切割 window 的底部区域,而不是顶部。我尝试使用 BitBlt()
但失败了。
---------------- 以下替代版本基于 IInspectable 评论
target_window_hwnd = win32gui.FindWindow(None, ("Math Analysis - Google Chrome"))
application_window_topbar_size = 200 # just roughly for testing
hwndDC = win32gui.GetWindowDC(target_window_hwnd)
mfcDC = win32ui.CreateDCFromHandle(hwndDC)
saveDC = mfcDC.CreateCompatibleDC()
saveBitMap = win32ui.CreateBitmap()
l, t, r, b = win32gui.GetClientRect(target_window_hwnd)
screen_width = r - l
screen_height = b -t
saveBitMap.CreateCompatibleBitmap(mfcDC, screen_width, screen_height)
saveDC.SelectObject(saveBitMap)
result = windll.user32.PrintWindow(target_window_hwnd, saveDC.GetSafeHdc(), 3)
bmpinfo = saveBitMap.GetInfo()
bmpstr = saveBitMap.GetBitmapBits(True)
screen_image = Image.frombuffer('RGB', (bmpinfo['bmWidth'], bmpinfo['bmHeight']), bmpstr, 'raw', 'BGRX', 0, 1)
win32gui.DeleteObject(saveBitMap.GetHandle())
saveDC.DeleteDC()
mfcDC.DeleteDC()
win32gui.ReleaseDC(target_window_hwnd, hwndDC)
仍然,改变顶部坐标只影响高度,不影响捕获的内容(能够只捕获 window 的 'document area',不包括地址 bar/toolbar)。
经过长时间的搜索和尝试,我意识到最明显的解决方案是在制作屏幕截图后对其进行裁剪。这样,不需要的部分(在我的例子中是顶部栏)可以很容易地去掉。
使用 PIL Image 可以轻松裁剪:
box = (left, top, right, bottom)
screen_image.crop(box)