mirror of
				https://github.com/python-pillow/Pillow.git
				synced 2025-11-04 01:47:47 +03:00 
			
		
		
		
	Add option to capture all monitors on Windows (#3950)
Add option to capture all monitors on Windows
This commit is contained in:
		
						commit
						310d2c9005
					
				| 
						 | 
				
			
			@ -8,7 +8,11 @@ try:
 | 
			
		|||
 | 
			
		||||
    class TestImageGrab(PillowTestCase):
 | 
			
		||||
        def test_grab(self):
 | 
			
		||||
            for im in [ImageGrab.grab(), ImageGrab.grab(include_layered_windows=True)]:
 | 
			
		||||
            for im in [
 | 
			
		||||
                ImageGrab.grab(),
 | 
			
		||||
                ImageGrab.grab(include_layered_windows=True),
 | 
			
		||||
                ImageGrab.grab(all_screens=True),
 | 
			
		||||
            ]:
 | 
			
		||||
                self.assert_image(im, im.mode, im.size)
 | 
			
		||||
 | 
			
		||||
        def test_grabclipboard(self):
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -11,7 +11,7 @@ or the clipboard to a PIL image memory.
 | 
			
		|||
 | 
			
		||||
.. versionadded:: 1.1.3
 | 
			
		||||
 | 
			
		||||
.. py:function:: PIL.ImageGrab.grab(bbox=None, include_layered_windows=False)
 | 
			
		||||
.. py:function:: PIL.ImageGrab.grab(bbox=None, include_layered_windows=False, all_screens=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,7 +20,13 @@ 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.
 | 
			
		||||
                 Note that on Windows OS, the top-left point may be negative if ``all_screens=True`` is used.
 | 
			
		||||
    :param include_layered_windows: Includes layered windows. Windows OS only.
 | 
			
		||||
 | 
			
		||||
        .. versionadded:: 6.1.0
 | 
			
		||||
    :param all_screens: Capture all monitors. Windows OS only.
 | 
			
		||||
 | 
			
		||||
        .. versionadded:: 6.2.0
 | 
			
		||||
    :return: An image
 | 
			
		||||
 | 
			
		||||
.. py:function:: PIL.ImageGrab.grabclipboard()
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -29,7 +29,7 @@ else:
 | 
			
		|||
    raise ImportError("ImageGrab is macOS and Windows only")
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def grab(bbox=None, include_layered_windows=False):
 | 
			
		||||
def grab(bbox=None, include_layered_windows=False, all_screens=False):
 | 
			
		||||
    if sys.platform == "darwin":
 | 
			
		||||
        fh, filepath = tempfile.mkstemp(".png")
 | 
			
		||||
        os.close(fh)
 | 
			
		||||
| 
						 | 
				
			
			@ -37,8 +37,10 @@ def grab(bbox=None, include_layered_windows=False):
 | 
			
		|||
        im = Image.open(filepath)
 | 
			
		||||
        im.load()
 | 
			
		||||
        os.unlink(filepath)
 | 
			
		||||
        if bbox:
 | 
			
		||||
            im = im.crop(bbox)
 | 
			
		||||
    else:
 | 
			
		||||
        size, data = grabber(include_layered_windows)
 | 
			
		||||
        offset, size, data = grabber(include_layered_windows, all_screens)
 | 
			
		||||
        im = Image.frombytes(
 | 
			
		||||
            "RGB",
 | 
			
		||||
            size,
 | 
			
		||||
| 
						 | 
				
			
			@ -50,7 +52,9 @@ def grab(bbox=None, include_layered_windows=False):
 | 
			
		|||
            -1,
 | 
			
		||||
        )
 | 
			
		||||
        if bbox:
 | 
			
		||||
        im = im.crop(bbox)
 | 
			
		||||
            x0, y0 = offset
 | 
			
		||||
            left, top, right, bottom = bbox
 | 
			
		||||
            im = im.crop((left - x0, top - y0, right - x0, bottom - y0))
 | 
			
		||||
    return im
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -322,15 +322,15 @@ PyImaging_DisplayModeWin32(PyObject* self, PyObject* args)
 | 
			
		|||
PyObject*
 | 
			
		||||
PyImaging_GrabScreenWin32(PyObject* self, PyObject* args)
 | 
			
		||||
{
 | 
			
		||||
    int width, height;
 | 
			
		||||
    int includeLayeredWindows = 0;
 | 
			
		||||
    int x = 0, y = 0, width, height;
 | 
			
		||||
    int includeLayeredWindows = 0, all_screens = 0;
 | 
			
		||||
    HBITMAP bitmap;
 | 
			
		||||
    BITMAPCOREHEADER core;
 | 
			
		||||
    HDC screen, screen_copy;
 | 
			
		||||
    DWORD rop;
 | 
			
		||||
    PyObject* buffer;
 | 
			
		||||
 | 
			
		||||
    if (!PyArg_ParseTuple(args, "|i", &includeLayeredWindows))
 | 
			
		||||
    if (!PyArg_ParseTuple(args, "|ii", &includeLayeredWindows, &all_screens))
 | 
			
		||||
        return NULL;
 | 
			
		||||
 | 
			
		||||
    /* step 1: create a memory DC large enough to hold the
 | 
			
		||||
| 
						 | 
				
			
			@ -339,8 +339,15 @@ PyImaging_GrabScreenWin32(PyObject* self, PyObject* args)
 | 
			
		|||
    screen = CreateDC("DISPLAY", NULL, NULL, NULL);
 | 
			
		||||
    screen_copy = CreateCompatibleDC(screen);
 | 
			
		||||
 | 
			
		||||
    if (all_screens) {
 | 
			
		||||
        x = GetSystemMetrics(SM_XVIRTUALSCREEN);
 | 
			
		||||
        y = GetSystemMetrics(SM_YVIRTUALSCREEN);
 | 
			
		||||
        width = GetSystemMetrics(SM_CXVIRTUALSCREEN);
 | 
			
		||||
        height = GetSystemMetrics(SM_CYVIRTUALSCREEN);
 | 
			
		||||
    } else {
 | 
			
		||||
        width = GetDeviceCaps(screen, HORZRES);
 | 
			
		||||
        height = GetDeviceCaps(screen, VERTRES);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    bitmap = CreateCompatibleBitmap(screen, width, height);
 | 
			
		||||
    if (!bitmap)
 | 
			
		||||
| 
						 | 
				
			
			@ -354,7 +361,7 @@ PyImaging_GrabScreenWin32(PyObject* self, PyObject* args)
 | 
			
		|||
    rop = SRCCOPY;
 | 
			
		||||
    if (includeLayeredWindows)
 | 
			
		||||
        rop |= CAPTUREBLT;
 | 
			
		||||
    if (!BitBlt(screen_copy, 0, 0, width, height, screen, 0, 0, rop))
 | 
			
		||||
    if (!BitBlt(screen_copy, 0, 0, width, height, screen, x, y, rop))
 | 
			
		||||
        goto error;
 | 
			
		||||
 | 
			
		||||
    /* step 3: extract bits from bitmap */
 | 
			
		||||
| 
						 | 
				
			
			@ -376,7 +383,7 @@ PyImaging_GrabScreenWin32(PyObject* self, PyObject* args)
 | 
			
		|||
    DeleteDC(screen_copy);
 | 
			
		||||
    DeleteDC(screen);
 | 
			
		||||
 | 
			
		||||
    return Py_BuildValue("(ii)N", width, height, buffer);
 | 
			
		||||
    return Py_BuildValue("(ii)(ii)N", x, y, width, height, buffer);
 | 
			
		||||
 | 
			
		||||
error:
 | 
			
		||||
    PyErr_SetString(PyExc_IOError, "screen grab failed");
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue
	
	Block a user