diff --git a/Tests/test_imagegrab.py b/Tests/test_imagegrab.py index a2e7a028df2..97014cef8e3 100644 --- a/Tests/test_imagegrab.py +++ b/Tests/test_imagegrab.py @@ -9,8 +9,11 @@ class TestImageGrab(PillowTestCase): def test_grab(self): - im = ImageGrab.grab() - self.assert_image(im, im.mode, im.size) + for im in [ + ImageGrab.grab(), + ImageGrab.grab(include_layered_windows=True) + ]: + self.assert_image(im, im.mode, im.size) def test_grabclipboard(self): if sys.platform == "darwin": diff --git a/docs/reference/ImageGrab.rst b/docs/reference/ImageGrab.rst index 39aaef6bc12..ed7482e99f5 100644 --- a/docs/reference/ImageGrab.rst +++ b/docs/reference/ImageGrab.rst @@ -11,7 +11,7 @@ or the clipboard to a PIL image memory. .. versionadded:: 1.1.3 -.. py:function:: PIL.ImageGrab.grab(bbox=None) +.. py:function:: PIL.ImageGrab.grab(bbox=None, include_layered_windows=False) Take a snapshot of the screen. The pixels inside the bounding box are returned as an "RGB" image on Windows or "RGBA" on macOS. @@ -20,6 +20,7 @@ or the clipboard to a PIL image memory. .. versionadded:: 1.1.3 (Windows), 3.0.0 (macOS) :param bbox: What region to copy. Default is the entire screen. + :param include_layered_windows: Includes layered windows. Windows OS only. :return: An image .. py:function:: PIL.ImageGrab.grabclipboard() diff --git a/src/PIL/ImageGrab.py b/src/PIL/ImageGrab.py index d0fe76ef4a8..bfb5456d353 100644 --- a/src/PIL/ImageGrab.py +++ b/src/PIL/ImageGrab.py @@ -29,7 +29,7 @@ import subprocess -def grab(bbox=None): +def grab(bbox=None, include_layered_windows=False): if sys.platform == "darwin": fh, filepath = tempfile.mkstemp('.png') os.close(fh) @@ -38,7 +38,7 @@ def grab(bbox=None): im.load() os.unlink(filepath) else: - size, data = grabber() + size, data = grabber(include_layered_windows) im = Image.frombytes( "RGB", size, data, # RGB, 32-bit line padding, origin lower left corner diff --git a/src/display.c b/src/display.c index 49143b72e0e..ab005d4b468 100644 --- a/src/display.c +++ b/src/display.c @@ -323,11 +323,16 @@ PyObject* PyImaging_GrabScreenWin32(PyObject* self, PyObject* args) { int width, height; + int includeLayeredWindows = 0; HBITMAP bitmap; BITMAPCOREHEADER core; HDC screen, screen_copy; + DWORD rop; PyObject* buffer; + if (!PyArg_ParseTuple(args, "|i", &includeLayeredWindows)) + return NULL; + /* step 1: create a memory DC large enough to hold the entire screen */ @@ -346,7 +351,10 @@ PyImaging_GrabScreenWin32(PyObject* self, PyObject* args) /* step 2: copy bits into memory DC bitmap */ - if (!BitBlt(screen_copy, 0, 0, width, height, screen, 0, 0, SRCCOPY)) + rop = SRCCOPY; + if (includeLayeredWindows) + rop |= CAPTUREBLT; + if (!BitBlt(screen_copy, 0, 0, width, height, screen, 0, 0, rop)) goto error; /* step 3: extract bits from bitmap */