So I can use PIL to grab a screenshot of the desktop, and then use pywin32 to get its rectangle and crop out the part I want. However, if there's something in front of the window I want, it'll occlude the application I wanted a screenshot of. Is there any way to get what windows would say an application is currently displaying? It has that data somewhere, even when other windows are in front of it.
-
2"It has that data somewhere" not always true. What makes you say this? In many cases, the window must redraw when the order is changed. – S.Lott Jul 04 '09 at 02:46
-
Yes, question is meaningless, because what's not visible may not exist, do you want to get its last drawn state, because current state is what you see, nothing. – Anurag Uniyal Jul 04 '09 at 04:23
-
1It is like asking when a bigger shadow covers my shadow, what is the shape of my shadow. – Anurag Uniyal Jul 04 '09 at 04:25
-
@Anurag: except in this case, you can ask your shadow to draw itself on another surface =) – Claudiu Aug 27 '10 at 16:01
-
1Possible duplicate of [Python Screenshot of inactive window PrintWindow + win32gui](http://stackoverflow.com/questions/19695214/python-screenshot-of-inactive-window-printwindow-win32gui) – Tobias Kienzler Jul 25 '16 at 06:44
7 Answers
I posted working code in the answer here: Screenshot of inactive window PrintWindow + win32gui. It uses the PrintWindow
function.
This is the "correct" way to copy the image of a hidden window, but that doesn't mean that it will always work. It depends on the program implementing the proper message, WM_Print
response.
If you try to use PrintWindow
it doesn't work, then your only remaining option would be to bring the window to the front before taking a BitBlit
.
I've done the same thing by giving the application I want focus before taking the shot:
shell=win32com.client.Dispatch("Wscript.Shell")
success = shell.AppActivate(app_name) # Returns true if focus given successfully.

- 31,940
- 6
- 44
- 59
There is a way to do this, using the PrintWindow
function. It causes the window to redraw itself on another surface.

- 224,032
- 165
- 485
- 680
This code worked for me with applications in background, not minimized.
pip install pywin32
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)

- 121
- 1
- 4
If you can, try saving the order of the windows, then move your app to the front, screenshot, and move it back really quickly. Might produce a bit of annoying flicker, but it might be better than nothing.

- 272,448
- 266
- 850
- 1,236
-
yeah, unless there's a specialized function that can take a specific screenshot, that's how I'd do it too. – Geo Jul 03 '09 at 20:38
Maybe you can position the app offscreen, then take the screenshot, then put it back?

- 1,274
- 1
- 16
- 32
IIRC, not in Windows pre-vista - with Aero each window has it's own buffer, but before that, you would just use your method, of getting the rectangle. I'm not sure if pywin32 has Aero support or not.

- 19,767
- 8
- 75
- 88