@@ -286,29 +286,42 @@ PyImaging_DisplayModeWin32(PyObject *self, PyObject *args) {
286
286
/* -------------------------------------------------------------------- */
287
287
/* Windows screen grabber */
288
288
289
+ typedef HANDLE (__stdcall * Func_GetWindowDpiAwarenessContext )(HANDLE );
289
290
typedef HANDLE (__stdcall * Func_SetThreadDpiAwarenessContext )(HANDLE );
290
291
291
292
PyObject *
292
293
PyImaging_GrabScreenWin32 (PyObject * self , PyObject * args ) {
293
- int x = 0 , y = 0 , width , height ;
294
- int includeLayeredWindows = 0 , all_screens = 0 ;
294
+ int x = 0 , y = 0 , width = -1 , height ;
295
+ int includeLayeredWindows = 0 , screens = 0 ;
295
296
HBITMAP bitmap ;
296
297
BITMAPCOREHEADER core ;
297
298
HDC screen , screen_copy ;
299
+ HWND wnd ;
298
300
DWORD rop ;
299
301
PyObject * buffer ;
300
- HANDLE dpiAwareness ;
302
+ HANDLE dpiAwareness = NULL ;
301
303
HMODULE user32 ;
304
+ Func_GetWindowDpiAwarenessContext GetWindowDpiAwarenessContext_function ;
302
305
Func_SetThreadDpiAwarenessContext SetThreadDpiAwarenessContext_function ;
303
306
304
- if (!PyArg_ParseTuple (args , "|ii" , & includeLayeredWindows , & all_screens )) {
307
+ if (!PyArg_ParseTuple (
308
+ args , "|ii" F_HANDLE , & includeLayeredWindows , & screens , & wnd
309
+ )) {
305
310
return NULL ;
306
311
}
307
312
308
313
/* step 1: create a memory DC large enough to hold the
309
314
entire screen */
310
315
311
- screen = CreateDC ("DISPLAY" , NULL , NULL , NULL );
316
+ if (screens == -1 ) {
317
+ screen = GetDC (wnd );
318
+ if (screen == NULL ) {
319
+ PyErr_SetString (PyExc_OSError , "unable to get device context for handle" );
320
+ return NULL ;
321
+ }
322
+ } else {
323
+ screen = CreateDC ("DISPLAY" , NULL , NULL , NULL );
324
+ }
312
325
screen_copy = CreateCompatibleDC (screen );
313
326
314
327
// added in Windows 10 (1607)
@@ -317,15 +330,28 @@ PyImaging_GrabScreenWin32(PyObject *self, PyObject *args) {
317
330
SetThreadDpiAwarenessContext_function = (Func_SetThreadDpiAwarenessContext
318
331
)GetProcAddress (user32 , "SetThreadDpiAwarenessContext" );
319
332
if (SetThreadDpiAwarenessContext_function != NULL ) {
333
+ GetWindowDpiAwarenessContext_function = (Func_GetWindowDpiAwarenessContext
334
+ )GetProcAddress (user32 , "GetWindowDpiAwarenessContext" );
335
+ if (screens == -1 && GetWindowDpiAwarenessContext_function != NULL ) {
336
+ dpiAwareness = GetWindowDpiAwarenessContext_function (wnd );
337
+ }
320
338
// DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE = ((DPI_CONTEXT_HANDLE)-3)
321
- dpiAwareness = SetThreadDpiAwarenessContext_function ((HANDLE )- 3 );
339
+ dpiAwareness = SetThreadDpiAwarenessContext_function (
340
+ dpiAwareness == NULL ? (HANDLE )- 3 : dpiAwareness
341
+ );
322
342
}
323
343
324
- if (all_screens ) {
344
+ if (screens == 1 ) {
325
345
x = GetSystemMetrics (SM_XVIRTUALSCREEN );
326
346
y = GetSystemMetrics (SM_YVIRTUALSCREEN );
327
347
width = GetSystemMetrics (SM_CXVIRTUALSCREEN );
328
348
height = GetSystemMetrics (SM_CYVIRTUALSCREEN );
349
+ } else if (screens == -1 ) {
350
+ RECT rect ;
351
+ if (GetClientRect (wnd , & rect )) {
352
+ width = rect .right ;
353
+ height = rect .bottom ;
354
+ }
329
355
} else {
330
356
width = GetDeviceCaps (screen , HORZRES );
331
357
height = GetDeviceCaps (screen , VERTRES );
@@ -337,6 +363,10 @@ PyImaging_GrabScreenWin32(PyObject *self, PyObject *args) {
337
363
338
364
FreeLibrary (user32 );
339
365
366
+ if (width == -1 ) {
367
+ goto error ;
368
+ }
369
+
340
370
bitmap = CreateCompatibleBitmap (screen , width , height );
341
371
if (!bitmap ) {
342
372
goto error ;
@@ -382,15 +412,23 @@ PyImaging_GrabScreenWin32(PyObject *self, PyObject *args) {
382
412
383
413
DeleteObject (bitmap );
384
414
DeleteDC (screen_copy );
385
- DeleteDC (screen );
415
+ if (screens == -1 ) {
416
+ ReleaseDC (wnd , screen );
417
+ } else {
418
+ DeleteDC (screen );
419
+ }
386
420
387
421
return Py_BuildValue ("(ii)(ii)N" , x , y , width , height , buffer );
388
422
389
423
error :
390
424
PyErr_SetString (PyExc_OSError , "screen grab failed" );
391
425
392
426
DeleteDC (screen_copy );
393
- DeleteDC (screen );
427
+ if (screens == -1 ) {
428
+ ReleaseDC (wnd , screen );
429
+ } else {
430
+ DeleteDC (screen );
431
+ }
394
432
395
433
return NULL ;
396
434
}
0 commit comments