Как получить окно или полноэкранный скриншот в Python 3k?(без PIL) - PullRequest
7 голосов
/ 16 июля 2010

В Python 3 я бы хотел получить дескриптор другого окна (не являющегося частью моего приложения), чтобы я мог:

a) напрямую захватить это окно как снимок экрана или

b) определить его положение и размер и записать его другим способом

В случае, если это важно, я использую Windows XP (правка: работает и в Windows 7).

Я нашел это решение , но это не совсем то, что мне нужно, поскольку оно полноэкранное и, что более важно, PIL, насколько я знаю, пока не поддерживает 3.x.

Ответы [ 2 ]

15 голосов
/ 16 июля 2010

Вот как вы можете сделать это, используя PIL на win32. Учитывая дескриптор окна (hwnd), вам нужны только последние 4 строки кода. Предшествующий просто ищет окно с «firefox» в заголовке. Поскольку исходный код PIL доступен, вы сможете изучить метод ImageGrab.grab(bbox) и выяснить код win32, необходимый для этого.

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()
10 голосов
/ 19 июля 2010

Арс дал мне все кусочки.Я просто собираю кусочки здесь для тех, кто хочет получить скриншот в Python 3.x.Далее мне нужно выяснить, как работать с битовой картой win32 без использования PIL.

Получить снимок экрана (передать hwnd для окна вместо полноэкранного режима):

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')

Получить дескриптор окна по заголовку (чтобы перейти к вышеуказанной функции):

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]
...