К сожалению, это невозможно из-за способа, которым PIL получает размеры устройства отображения. Когда он получает контекст устройства, он получает один для всех подключенных мониторов:
screen = CreateDC("DISPLAY", NULL, NULL, NULL);
( display.c , строка 296, версия 1.1.7)
Однако, чтобы получить размеры дисплея, он использует этот код:
width = GetDeviceCaps(screen, HORZRES);
height = GetDeviceCaps(screen, VERTRES);
( display.c , строки 299-300, версия 1.1.7)
Который возвращает только размеры основного активного монитора. Все последующие операции выполняются с этими значениями ширины и высоты, в результате чего получается конечное изображение, размер которого равен только размеру основного дисплея.
Чтобы получить скриншот всех подключенных мониторов, эти две строки необходимо заменить на что-то вроде:
width = GetSystemMetrics(SM_CXVIRTUALSCREEN);
height = GetSystemMetrics(SM_CYVIRTUALSCREEN);
После чего вам нужно будет перекомпилировать PIL. Это даст вам размеры виртуального экрана, который является «... ограничивающим прямоугольником всех мониторов дисплея». [ MSDN ]
Более правильной реализацией было бы использование EnumDisplayMonitors для получения контекстов устройства для отдельных мониторов, наряду с изменением интерфейса ImageGrab.grab () (или добавлением новой функции), чтобы позволить выбор конкретный монитор, контекст устройства которого будет использоваться для оставшихся операций.