-
-
Notifications
You must be signed in to change notification settings - Fork 2.4k
Allow HWND to be passed to ImageGrab.grab() on Windows #8516
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 5 commits
607acbf
28e5b92
9622266
f682197
7763350
a44b306
288d77e
4b88670
a6c941a
acba5c4
c5e89ee
e053be3
ca9f4f8
80d5b42
d2683e0
b4a480f
25af4f1
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -316,29 +316,42 @@ PyImaging_DisplayModeWin32(PyObject *self, PyObject *args) { | |
| /* -------------------------------------------------------------------- */ | ||
| /* Windows screen grabber */ | ||
|
|
||
| typedef HANDLE(__stdcall *Func_GetWindowDpiAwarenessContext)(HANDLE); | ||
| typedef HANDLE(__stdcall *Func_SetThreadDpiAwarenessContext)(HANDLE); | ||
|
|
||
| PyObject * | ||
| PyImaging_GrabScreenWin32(PyObject *self, PyObject *args) { | ||
| int x = 0, y = 0, width, height; | ||
| int includeLayeredWindows = 0, all_screens = 0; | ||
| int x = 0, y = 0, width = -1, height; | ||
| int includeLayeredWindows = 0, screens = 0; | ||
| HBITMAP bitmap; | ||
| BITMAPCOREHEADER core; | ||
| HDC screen, screen_copy; | ||
| HWND wnd; | ||
| DWORD rop; | ||
| PyObject *buffer; | ||
| HANDLE dpiAwareness; | ||
| HMODULE user32; | ||
| Func_GetWindowDpiAwarenessContext GetWindowDpiAwarenessContext_function; | ||
| Func_SetThreadDpiAwarenessContext SetThreadDpiAwarenessContext_function; | ||
|
|
||
| if (!PyArg_ParseTuple(args, "|ii", &includeLayeredWindows, &all_screens)) { | ||
| if (!PyArg_ParseTuple( | ||
| args, "|ii" F_HANDLE, &includeLayeredWindows, &screens, &wnd | ||
| )) { | ||
| return NULL; | ||
| } | ||
|
|
||
| /* step 1: create a memory DC large enough to hold the | ||
| entire screen */ | ||
|
|
||
| screen = CreateDC("DISPLAY", NULL, NULL, NULL); | ||
| if (screens == -1) { | ||
| screen = GetDC(wnd); | ||
| if (screen == NULL) { | ||
| PyErr_SetString(PyExc_OSError, "unable to get device context for handle"); | ||
| return NULL; | ||
| } | ||
| } else { | ||
| screen = CreateDC("DISPLAY", NULL, NULL, NULL); | ||
| } | ||
| screen_copy = CreateCompatibleDC(screen); | ||
|
|
||
| // added in Windows 10 (1607) | ||
|
|
@@ -347,15 +360,34 @@ PyImaging_GrabScreenWin32(PyObject *self, PyObject *args) { | |
| SetThreadDpiAwarenessContext_function = (Func_SetThreadDpiAwarenessContext | ||
| )GetProcAddress(user32, "SetThreadDpiAwarenessContext"); | ||
| if (SetThreadDpiAwarenessContext_function != NULL) { | ||
| // DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE = ((DPI_CONTEXT_HANDLE)-3) | ||
| dpiAwareness = SetThreadDpiAwarenessContext_function((HANDLE)-3); | ||
| if (screens == -1) { | ||
| GetWindowDpiAwarenessContext_function = (Func_GetWindowDpiAwarenessContext | ||
| )GetProcAddress(user32, "GetWindowDpiAwarenessContext"); | ||
| DPI_AWARENESS_CONTEXT dpiAwarenessContext = | ||
| GetWindowDpiAwarenessContext_function(wnd); | ||
| if (dpiAwarenessContext != NULL) { | ||
radarhere marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| dpiAwareness = | ||
| SetThreadDpiAwarenessContext_function(dpiAwarenessContext); | ||
|
||
| } else { | ||
| dpiAwareness = SetThreadDpiAwarenessContext_function((HANDLE)-3); | ||
| } | ||
| } else { | ||
| // DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE = ((DPI_CONTEXT_HANDLE)-3) | ||
| dpiAwareness = SetThreadDpiAwarenessContext_function((HANDLE)-3); | ||
| } | ||
| } | ||
|
|
||
| if (all_screens) { | ||
| if (screens == 1) { | ||
| x = GetSystemMetrics(SM_XVIRTUALSCREEN); | ||
| y = GetSystemMetrics(SM_YVIRTUALSCREEN); | ||
| width = GetSystemMetrics(SM_CXVIRTUALSCREEN); | ||
| height = GetSystemMetrics(SM_CYVIRTUALSCREEN); | ||
| } else if (screens == -1) { | ||
| RECT rect; | ||
| if (GetClientRect(wnd, &rect)) { | ||
| width = rect.right; | ||
| height = rect.bottom; | ||
| } | ||
| } else { | ||
| width = GetDeviceCaps(screen, HORZRES); | ||
| height = GetDeviceCaps(screen, VERTRES); | ||
|
|
@@ -367,6 +399,10 @@ PyImaging_GrabScreenWin32(PyObject *self, PyObject *args) { | |
|
|
||
| FreeLibrary(user32); | ||
|
|
||
| if (width == -1) { | ||
| goto error; | ||
| } | ||
|
|
||
| bitmap = CreateCompatibleBitmap(screen, width, height); | ||
| if (!bitmap) { | ||
| goto error; | ||
|
|
@@ -412,15 +448,23 @@ PyImaging_GrabScreenWin32(PyObject *self, PyObject *args) { | |
|
|
||
| DeleteObject(bitmap); | ||
| DeleteDC(screen_copy); | ||
| DeleteDC(screen); | ||
| if (screens == -1) { | ||
| ReleaseDC(wnd, screen); | ||
| } else { | ||
| DeleteDC(screen); | ||
| } | ||
|
|
||
| return Py_BuildValue("(ii)(ii)N", x, y, width, height, buffer); | ||
|
|
||
| error: | ||
| PyErr_SetString(PyExc_OSError, "screen grab failed"); | ||
|
|
||
| DeleteDC(screen_copy); | ||
| DeleteDC(screen); | ||
| if (screens == -1) { | ||
| ReleaseDC(wnd, screen); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You added this for the
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ok, I've updated the commit to add it or success as well. |
||
| } else { | ||
| DeleteDC(screen); | ||
| } | ||
|
|
||
| return NULL; | ||
| } | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.