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)
Answer from Alexandre Calil on Stack OverflowThis 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)
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.
I am performing image search on a certain window, that I am trying to automate.
At the same time, I show debug information in a borderless window on top of the screen.
This window interferes with the image search that I am trying to do.
The solution would be to not create a screenshot of the whole screen, but a certain window.
Solutions I have found on the internet require moving certain windows to the top, but this wouldn't work as the debug window is always on top. I know it is possible, because programs like OBS can only grab a certain window.
Simplified code (because required):
import python_imagesearch.imagesearch as imgsearch
searchResult = imgsearch.imagesearch("./imagery/shop.png",0.9)
I just started learning python so I don't know what it is capable of. Can I take a 'screenshot' of whats going on in a minimized user chosen window in the windows OS
First time posting here, i am very new to python, but i want to make a screenshot of a specific window, instead of all of the screen, this is my current code that makes a screenshot of all of the screen
from PIL import ImageGrab
screen = ImageGrab.grab(bbox=(0,0,1366,768))
screen.save('grabbed.png')
print("done")I searched on internet but the only solution that i found was to get the size and position of the selected window and then take a screenshot with those info so it only gets that window, howewer if there is something covering that window it wont take the screenshot correctly... is it atleast possible?
It's probably the fault of the game, not the fault of the screenshot utility. X11 sends applications a VisibilityNotify event to tell them that their window is fully visible, partially obscured or totally obscured. When the window is totally obscured, most applications don't bother updating their display, which saves resources. In other words, if nobody is there to see it, the tree doesn't fall.
I think that if you send the game window a VisibilityNotify event to pretend that it's visible, then you'll get your screenshot. You'll need to send the event after the window becomes obscured, since X11 itself will send its normal event at that time. Here's an untested script that sends a VisibilityNotify event, call it with the argument VisibilityPartiallyObscured or VisibilityUnobscured. I follow with a MapNotify event, I don't know if it's useful. You need Python and Python-xlib.
#! /usr/bin/env python
import re, sys, time
import Xlib.X, Xlib.XK, Xlib.display, Xlib.protocol
def parse_action(string):
state = {
'0': 0,
'1': 1,
'2': 2,
'unobscured': 0,
'partiallyobscured': 1,
'fullyobscured': 2,
'visibilityunobscured': 0,
'visibilitypartiallyobscured': 1,
'visibilityfullyobscured': 2,
}[string.lower()]
return state
def parse_window(display, arg):
wid = int(arg, 0)
return display.create_resource_object('window', wid)
def send_event(display, window, state):
window.send_event(Xlib.protocol.event.VisibilityNotify(window=window,
state=state))
window.send_event(Xlib.protocol.event.MapNotify(window=window,
event=window,
override=False))
display.sync()
if __name__ == "__main__":
display = Xlib.display.Display()
send_event(display, parse_window(display, sys.argv[1]), parse_action(sys.argv[2]))
If you don't have xwd and xwud already installed on your system I would be very surprised if you could not easily install them via package manager in a few seconds at most.
% man xwd
NAME xwd - dump an image of an X window SYNOPSIS xwd [-debug] [-help] [-nobdrs] [-out file] [-xy] [-frame] [-add value] [-root | -id id | -name name ] [-icmap] [-screen] [-silent] [-display display] DESCRIPTION Xwd is an X Window System window dumping utility. Xwd allows X users to store window images in a specially formatted dump file. This file can then be read by various other X utilities for redisplay, printing, editing, formatting, archiving, image processing, etc. The target win‐ dow is selected by clicking the pointer in the desired window. The keyboard bell is rung once at the beginning of the dump and twice when the dump is completed.
Understand this is a sort of a desktop session recording software - built into the X-server - it does enable you take screenshots, and much more. But you'll want to read the documentation a little before diving in - just to get familiar with it, I think.
Note - the target window does not need to be selected via mouse-cursor as mentioned above - that's just the default behavior when it's invoked without arguments. The entire interface is completely scriptable.
Just scroll a little more and...
-root This option indicates that the root window should be selected for the window dump, without requiring the user to select a window with the pointer. -id id This option indicates that the window with the specified resource id should be selected for the window dump, without requiring the user to select a window with the pointer.
If you'll take my advice you'll also look pretty closely at xdotool, though, admittedly it has limited relevance here. It scripts the mouse mostly, though it does offer some direct command-line interface to the X backend api - as @Gilles references. And it's pretty simple to use.
All that said, the primary issue is that your display is currently occupied. If your window must remain invisible it is possible to handle it in a few ways - though you'll have to try at them a little, I think, before you get them down. The way I would recommend is merely to configure your screen to be twice the size of your screen. That way you can just drag the window off of the screen and it will continue to update the display - but off screen. I can do this with nvidia's tools, and most can do this with xrandr, but, especially in Linux it seems, at least in my experience, display issues are often personal issues just because there are so many possible ways to configure them.
Another way this might be done is with a virtual X-server - such as xnest or xephyr. These servers nest an entire X-server within a window which can be backgrounded, or completely nonexistent if you prefer. Last I checked, which was some time ago unfortunately, these were using the xdummy-driver - and would therefore not be good choices for a video game that required video acceleration. Still, I'm sure your man pages could tell you more, and I can only hope I helped.
» pip install fast-ctypes-screenshots
» pip install windows-adb-screen-capture