kainev
kainev

Reputation: 265

Python - Screenshot of background/inactive window

I am attempting to take fast screenshots ready for processing with PIL/Numpy (~0.01s per screenshot) with Python 3.6. Ideally the window would not need to be in the foreground, i.e. even when another window is covering it, the screenshot is still successful.

So far I've modified the code for python 3 from this question: Python Screenshot of inactive window PrintWindow + win32gui

However, all it gets is black images.

import win32gui
import win32ui
from ctypes import windll
from PIL import Image

hwnd = win32gui.FindWindow(None, 'Calculator')

# Get window bounds
left, top, right, bot = win32gui.GetWindowRect(hwnd)
w = right - left
h = bot - top

hwndDC = win32gui.GetWindowDC(hwnd)
mfcDC = win32ui.CreateDCFromHandle(hwndDC)
saveDC = mfcDC.CreateCompatibleDC()

saveBitMap = win32ui.CreateBitmap()
saveBitMap.CreateCompatibleBitmap(mfcDC, w, h)

saveDC.SelectObject(saveBitMap)

result = windll.user32.PrintWindow(hwnd, saveDC.GetSafeHdc(), 1)
print(result)

bmp_info = saveBitMap.GetInfo()
bmp_str = saveBitMap.GetBitmapBits(True)
print(bmp_str)

im = Image.frombuffer(
    'RGB',
    (bmp_info['bmWidth'], bmp_info['bmHeight']),
    bmp_str, 'raw', 'BGRX', 0, 1)

win32gui.DeleteObject(saveBitMap.GetHandle())
saveDC.DeleteDC()
mfcDC.DeleteDC()
win32gui.ReleaseDC(hwnd, hwndDC)

if result == 1:
    im.save("screenshot.png")

Upvotes: 11

Views: 12507

Answers (2)

ajkula11
ajkula11

Reputation: 31

One possible cause of black screenshots can be running your script as a non-elevated user while trying to take screenshot of an elevated program, i.e. program that is run as admin.

Running your script as admin could, potentially, solve your problem.

Upvotes: 1

Alexandre Calil
Alexandre Calil

Reputation: 141

This code worked for me with applications in background, not minimized.

import win32gui
import win32ui

def background_screenshot(hwnd, width, height):
    wDC = win32gui.GetWindowDC(hwnd)
    dcObj=win32ui.CreateDCFromHandle(wDC)
    cDC=dcObj.CreateCompatibleDC()
    dataBitMap = win32ui.CreateBitmap()
    dataBitMap.CreateCompatibleBitmap(dcObj, width, height)
    cDC.SelectObject(dataBitMap)
    cDC.BitBlt((0,0),(width, height) , dcObj, (0,0), win32con.SRCCOPY)
    dataBitMap.SaveBitmapFile(cDC, 'screenshot.bmp')
    dcObj.DeleteDC()
    cDC.DeleteDC()
    win32gui.ReleaseDC(hwnd, wDC)
    win32gui.DeleteObject(dataBitMap.GetHandle())

hwnd = win32gui.FindWindow(None, windowname)
background_screenshot(hwnd, 1280, 780)

Upvotes: 10

Related Questions