def window_full_shot(hwnd, gray=0):
hwnd = get_hwnd(hwnd)[0]
print(hwnd)
print(win32gui.GetClassName(hwnd))
l, t, r, b = win32gui.GetWindowRect(hwnd)
h = b - t
w = r - l
hwindc = win32gui.GetWindowDC(hwnd)
srcdc = win32ui.CreateDCFromHandle(hwindc)
memdc = srcdc.CreateCompatibleDC()
bmp = win32ui.CreateBitmap()
bmp.CreateCompatibleBitmap(srcdc, w, h)
memdc.SelectObject(bmp)
memdc.BitBlt((0, 0), (w, h), srcdc, (0, 0), win32con.SRCCOPY)
signedIntsArray = bmp.GetBitmapBits(True)
img = np.fromstring(signedIntsArray, dtype='uint8')
img.shape = (h, w, 4)
print(type(img))
srcdc.DeleteDC()
memdc.DeleteDC()
win32gui.ReleaseDC(hwnd, hwindc)
win32gui.DeleteObject(bmp.GetHandle())
if gray == 0:
return cv2.cvtColor(img, cv2.COLOR_BGRA2BGR)
else:
return cv2.cvtColor(img, cv2.COLOR_BGRA2GRAY)
I use this code to shot two windows, one could got a right img, another it ins't work, just like that. the right code the bad code
Applications made with frameworks such as electron app, QT, WPF... will print black screen in response to GetDC
or GetWindowDC
.
The only way around it is to make sure the target application is visible and take a screenshot of desktop at the specific coordinates where the target application is at.
Windows GDI functions generally ignore alpha channel. But if you retrieve the screenshot in 32-bit, then GetDIBits
will set the all alpha values set to 255 (at least in Windows 10).
About code sample(C++), please refer: https://stackoverflow.com/a/53404526/11128312
Python code:
import win32gui
import win32ui
import win32con
from ctypes import windll
from PIL import Image
import time
import ctypes
hwnd_target = win32gui.FindWindow(None, 'Calculator') # used for test
left, top, right, bot = win32gui.GetWindowRect(hwnd_target)
w = right - left
h = bot - top
win32gui.SetForegroundWindow(hwnd_target)
time.sleep(1.0)
hdesktop = win32gui.GetDesktopWindow()
hwndDC = win32gui.GetWindowDC(hdesktop)
mfcDC = win32ui.CreateDCFromHandle(hwndDC)
saveDC = mfcDC.CreateCompatibleDC()
saveBitMap = win32ui.CreateBitmap()
saveBitMap.CreateCompatibleBitmap(mfcDC, w, h)
saveDC.SelectObject(saveBitMap)
result = saveDC.BitBlt((0, 0), (w, h), mfcDC, (left, top), win32con.SRCCOPY)
bmpinfo = saveBitMap.GetInfo()
bmpstr = saveBitMap.GetBitmapBits(True)
im = Image.frombuffer(
'RGB',
(bmpinfo['bmWidth'], bmpinfo['bmHeight']),
bmpstr, 'raw', 'BGRX', 0, 1)
win32gui.DeleteObject(saveBitMap.GetHandle())
saveDC.DeleteDC()
mfcDC.DeleteDC()
win32gui.ReleaseDC(hdesktop, hwndDC)
if result == None:
#PrintWindow Succeeded
im.save("test.png")