Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to Get a Window or Fullscreen Screenshot in Python 3k? (without PIL)

With python 3, I'd like to get a handle to another window (not part of my application) such that I can either:

  1. directly capture that window as a screenshot, or
  2. determine its position and size and capture it some other way

In case it is important, I am using Windows XP (edit: works in Windows 7 also).

I found this solution, but it is not quite what I need since it is full screen and more importantly, PIL to the best of my knowledge does not support 3.x yet.

like image 486
KobeJohn Avatar asked Jul 15 '10 22:07

KobeJohn


2 Answers

Here's how you can do it using PIL on win32. Given a window handle (hwnd), you should only need the last 4 lines of code. The preceding simply search for a window with "firefox" in the title. Since PIL's source is available, you should be able to poke around the ImageGrab.grab(bbox) method and figure out the win32 code you need to make this happen.

from PIL import ImageGrab
import win32gui

toplist, winlist = [], []
def enum_cb(hwnd, results):
    winlist.append((hwnd, win32gui.GetWindowText(hwnd)))
win32gui.EnumWindows(enum_cb, toplist)

firefox = [(hwnd, title) for hwnd, title in winlist if 'firefox' in title.lower()]
# just grab the hwnd for first window matching firefox
firefox = firefox[0]
hwnd = firefox[0]

win32gui.SetForegroundWindow(hwnd)
bbox = win32gui.GetWindowRect(hwnd)
img = ImageGrab.grab(bbox)
img.show()
like image 177
ars Avatar answered Oct 04 '22 02:10

ars


Ars gave me all the pieces. I am just putting the pieces together here for anyone else who needs to get a screenshot in python 3.x. Next I need to figure out how to work with a win32 bitmap without having PIL to lean on.

Get a Screenshot (pass hwnd for a window instead of full screen):

def screenshot(hwnd = None):
    import win32gui
    import win32ui
    import win32con
    from time import sleep
    if not hwnd:
        hwnd=win32gui.GetDesktopWindow()
    l,t,r,b=win32gui.GetWindowRect(hwnd)
    h=b-t
    w=r-l
    hDC = win32gui.GetWindowDC(hwnd)
    myDC=win32ui.CreateDCFromHandle(hDC)
    newDC=myDC.CreateCompatibleDC()

    myBitMap = win32ui.CreateBitmap()
    myBitMap.CreateCompatibleBitmap(myDC, w, h)

    newDC.SelectObject(myBitMap)

    win32gui.SetForegroundWindow(hwnd)
    sleep(.2) #lame way to allow screen to draw before taking shot
    newDC.BitBlt((0,0),(w, h) , myDC, (0,0), win32con.SRCCOPY)
    myBitMap.Paint(newDC)
    myBitMap.SaveBitmapFile(newDC,'c:\\tmp.bmp')

Get a Window Handle by title (to pass to the above function):

def _get_windows_bytitle(title_text, exact = False):
    def _window_callback(hwnd, all_windows):
        all_windows.append((hwnd, win32gui.GetWindowText(hwnd)))
    windows = []
    win32gui.EnumWindows(_window_callback, windows)
    if exact:
        return [hwnd for hwnd, title in windows if title_text == title]
    else:
        return [hwnd for hwnd, title in windows if title_text in title]
like image 21
KobeJohn Avatar answered Oct 04 '22 04:10

KobeJohn