def grab(region=None): hwin = win32gui.GetDesktopWindow() if region: left, top, x2, y2 = region width = x2 - left + 1 height = y2 - top + 1 else: width = win32api.GetSystemMetrics(win32con.SM_CXVIRTUALSCREEN) height = win32api.GetSystemMetrics(win32con.SM_CYVIRTUALSCREEN) left = win32api.GetSystemMetrics(win32con.SM_XVIRTUALSCREEN) top = win32api.GetSystemMetrics(win32con.SM_YVIRTUALSCREEN) hwindc = win32gui.GetWindowDC(hwin) srcdc = win32ui.CreateDCFromHandle(hwindc) memdc = srcdc.CreateCompatibleDC() bmp = win32ui.CreateBitmap() bmp.CreateCompatibleBitmap(srcdc, width, height) memdc.SelectObject(bmp) memdc.BitBlt((0, 0), (width, height), srcdc, (left, top), win32con.SRCCOPY) signedIntsArray = bmp.GetBitmapBits(True) img = np.fromstring(signedIntsArray, dtype="uint8") img.shape = (height, width, 4) srcdc.DeleteDC() memdc.DeleteDC() win32gui.ReleaseDC(hwin, hwindc) win32gui.DeleteObject(bmp.GetHandle()) return img
def screenshot(widget): path = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'screenshot.png') if _WIN32: targetWindow = win32gui.FindWindow(None, APP_NAME) left, top, right, bot = win32gui.GetClientRect(targetWindow) w = right - left h = bot - top hwndDC = win32gui.GetWindowDC(targetWindow) mfcDC = win32ui.CreateDCFromHandle(hwndDC) saveDC = mfcDC.CreateCompatibleDC() saveBitMap = win32ui.CreateBitmap() saveBitMap.CreateCompatibleBitmap(mfcDC, w, h) saveDC.SelectObject(saveBitMap) result = windll.user32.PrintWindow(targetWindow, saveDC.GetSafeHdc(), 1) if result != 0: #bmpinfo = saveBitMap.GetInfo() bmpstr = saveBitMap.GetBitmapBits(True) img = Image.frombuffer('RGB', (w, h), bmpstr, 'raw', 'BGRX', 0, 1) img.save(path) #img = img.convert("RGB") #data = img.tobytes("raw","RGB") #converting to QImage with altering window size causes crash / erroneous images #qimg = QImage(data, img.size[0], img.size[1], QImage.Format_RGB888) #qimg.save(path) else: print("Win32 failed, backup qt function used") widget.screenCap = widget.screen().grabWindow(widget.long_qdesktop_id, widget.geometry().x(), widget.geometry().y(), widget.width(), widget.height()).save(path, 'png') win32gui.DeleteObject(saveBitMap.GetHandle()) saveDC.DeleteDC() mfcDC.DeleteDC() win32gui.ReleaseDC(targetWindow, hwndDC) else: widget.screenCap = widget.screen().grabWindow(widget.long_qdesktop_id, widget.geometry().x(), widget.geometry().y(), widget.width(), widget.height()).save(path, 'png')
def get_screenshot(self): wDC = win32gui.GetWindowDC(self.hwnd) dcObj = win32ui.CreateDCFromHandle(wDC) cDC = dcObj.CreateCompatibleDC() dataBitMap = win32ui.CreateBitmap() dataBitMap.CreateCompatibleBitmap(dcObj, self.w, self.h) cDC.SelectObject(dataBitMap) cDC.BitBlt((0, 0), (self.w, self.h), dcObj, (self.cropped_x, self.cropped_y), win32con.SRCCOPY) signedIntsArray = dataBitMap.GetBitmapBits(True) # img = np.fromstring(signedIntsArray, dtype='uint8') img = np.frombuffer(signedIntsArray, dtype='uint8') img.shape = (self.h, self.w, 4) dcObj.DeleteDC() cDC.DeleteDC() win32gui.ReleaseDC(self.hwnd, wDC) win32gui.DeleteObject(dataBitMap.GetHandle()) img = img[..., :3] img = np.ascontiguousarray(img) return img
def window_capture(filename): hwnd = 0 # 窗口的编号,0号表示当前活跃窗口 # 根据窗口句柄获取窗口的设备上下文DC(Divice Context) hwndDC = win32gui.GetWindowDC(hwnd) # 根据窗口的DC获取mfcDC mfcDC = win32ui.CreateDCFromHandle(hwndDC) # mfcDC创建可兼容的DC saveDC = mfcDC.CreateCompatibleDC() # 创建bigmap准备保存图片 saveBitMap = win32ui.CreateBitmap() w, h = get_real_resolution() #注意这个是获取真实的屏幕分辨率 # 为bitmap开辟空间win32api.GetSystemMetrics(2880) saveBitMap.CreateCompatibleBitmap(mfcDC, w, h) # 高度saveDC,将截图保存到saveBitmap中 saveDC.SelectObject(saveBitMap) # 截取从左上角(0,0)长宽为(w,h)的图片 saveDC.BitBlt((0, 0), (w, h), mfcDC, (0, 0), win32con.SRCCOPY) saveBitMap.SaveBitmapFile(saveDC, filename)
def capture_screen(hwnd, w, h): # https://stackoverflow.com/questions/19695214/python-screenshot-of-inactive-window-printwindow-win32gui hwndDC = win32gui.GetWindowDC(hwnd) mfcDC = win32ui.CreateDCFromHandle(hwndDC) saveDC = mfcDC.CreateCompatibleDC() saveBitMap = win32ui.CreateBitmap() saveBitMap.CreateCompatibleBitmap(mfcDC, w, h) saveDC.SelectObject(saveBitMap) result = windll.user32.PrintWindow(hwnd, saveDC.GetSafeHdc(), 0) 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(hwnd, hwndDC) if result == 1: return im return None
def screenshot(self, output='screen_shot.png'): window_title = self._getWindowTitle() width, height = constants.BASE_WIDTH, constants.BASE_HEIGHT try: hwin = win32gui.FindWindow('LDPlayerMainFrame', window_title) hwindc = win32gui.GetWindowDC(hwin) srcdc = win32ui.CreateDCFromHandle(hwindc) memdc = srcdc.CreateCompatibleDC() bmp = win32ui.CreateBitmap() bmp.CreateCompatibleBitmap(srcdc, width, height) memdc.SelectObject(bmp) memdc.BitBlt((0, 0), (width, height), srcdc, (0, self._getDnToolbarHeight()), win32con.SRCCOPY) signedIntsArray = bmp.GetBitmapBits(True) img = np.frombuffer(signedIntsArray, dtype='uint8') img.shape = (height, width, 4) srcdc.DeleteDC() memdc.DeleteDC() win32gui.ReleaseDC(hwin, hwindc) win32gui.DeleteObject(bmp.GetHandle()) return img[:, :, :3] except: return super().screenshot(output=output)
def captureWindow(self): if _WIN32: targetWindow = win32gui.FindWindow(None, 'Pokémon Tower Battle') left, top, right, bot = win32gui.GetClientRect(targetWindow) w = right - left h = bot - top hwndDC = win32gui.GetWindowDC(targetWindow) mfcDC = win32ui.CreateDCFromHandle(hwndDC) saveDC = mfcDC.CreateCompatibleDC() saveBitMap = win32ui.CreateBitmap() saveBitMap.CreateCompatibleBitmap(mfcDC, w, h) saveDC.SelectObject(saveBitMap) result = windll.user32.PrintWindow(targetWindow, saveDC.GetSafeHdc(), 1) if result != 0: bmpstr = saveBitMap.GetBitmapBits(True) self.screenCap = Image.frombuffer('RGB', (w, h), bmpstr, 'raw', 'BGRX', 0, 1) else: #backup function if windows fails self.screenCap = self.screen().grabWindow(self.long_qdesktop_id, self.geometry().x(), self.geometry().y(), self.width(), self.height()).toImage() win32gui.DeleteObject(saveBitMap.GetHandle()) saveDC.DeleteDC() mfcDC.DeleteDC() win32gui.ReleaseDC(targetWindow, hwndDC) else: #must have screen on top self.screenCap = self.screen().grabWindow(self.long_qdesktop_id, self.geometry().x(), self.geometry().y(), self.width(), self.height()).toImage()
def __get_image(hwnd: int, rect: RECT, print_window: bool = False): width: LONG = rect.right - rect.left height: LONG = rect.bottom - rect.top # If the window closes while it's being manipulated, it could cause a crash try: windowDC: int = win32gui.GetWindowDC(hwnd) dcObject = win32ui.CreateDCFromHandle(windowDC) # Causes a 10-15x performance drop. But allows recording hardware accelerated windows if (print_window): windll.user32.PrintWindow(hwnd, dcObject.GetSafeHdc(), PW_RENDERFULLCONTENT) compatibleDC = dcObject.CreateCompatibleDC() bitmap: HBITMAP = win32ui.CreateBitmap() bitmap.CreateCompatibleBitmap(dcObject, width, height) compatibleDC.SelectObject(bitmap) compatibleDC.BitBlt((0, 0), (width, height), dcObject, (rect.left, rect.top), win32con.SRCCOPY) except (win32ui.error, pywintypes.error): errorImage = np.array([0, 0, 0, 1], dtype="uint8") return errorImage image: np._BufferType = np.frombuffer(bitmap.GetBitmapBits(True), dtype='uint8') image.shape = (height, width, 4) try: dcObject.DeleteDC() compatibleDC.DeleteDC() win32gui.ReleaseDC(hwnd, windowDC) win32gui.DeleteObject(bitmap.GetHandle()) except win32ui.error: pass return image
def GetScreenImg(self): if self.hwnd is None: raise Exception( "HWND is none. HWND not called or invalid window name provided." ) l, t, r, b = win32gui.GetWindowRect(self.hwnd) self.winLeft, self.winTop, self.winRight, self.winBottom = win32gui.GetClientRect( self.hwnd) # Calculate Width of Window w = self.winRight - self.winLeft # Calculate Height of Window h = self.winBottom - self.winTop wDC = win32gui.GetWindowDC(self.hwnd) dcObj = win32ui.CreateDCFromHandle(wDC) cDC = dcObj.CreateCompatibleDC() dataBitMap = win32ui.CreateBitmap() dataBitMap.CreateCompatibleBitmap(dcObj, w, h) cDC.SelectObject(dataBitMap) #First 2 tuples are top-left and bottom-right of destination #Third tuple is the start position in source cDC.BitBlt((0, 0), (w, h), dcObj, (0, 0), win32con.SRCCOPY) #result = windll.user32.PrintWindow(self.hwnd, cDC.GetSafeHdc(),0) bmInfo = dataBitMap.GetInfo() im = np.frombuffer(dataBitMap.GetBitmapBits(True), dtype=np.uint8) # Numpy Implementation #bmStr = dataBitMap.GetBitmapBits(True) #im = Image.frombuffer('RGB',(bmInfo['bmWidth'],bmInfo['bmHeight']),bmStr,'raw','BGRX',0,1) PIL is too slow dcObj.DeleteDC() cDC.DeleteDC() win32gui.ReleaseDC(self.hwnd, wDC) win32gui.DeleteObject(dataBitMap.GetHandle()) #Bitmap has 4 channels like: BGRA. Discard Alpha and flip order to RGB if im.size < 4: return np.zeros((1, 1, 3), dtype=np.uint8) return np.array( im.reshape(bmInfo['bmHeight'], bmInfo['bmWidth'], 4)[:, :, -2::-1])
def screen_shot(server, sleep_time, lasting_time, running): path_i = "D:\\new" timedic = { "屏幕变化": "屏幕变化", "不限": "不限", "1s": 1, "2s": 2, "5s": 5, "10s": 10, "30s": 30, "1min": 60, "5min": 300, "10min": 600, "30min": 1800, "1h": 3600, "12h": 43200, "24h": 86400 } start = time.time() # 获取桌面 desktop = win32gui.GetDesktopWindow() # 分辨率适应 width = win32api.GetSystemMetrics(win32con.SM_CXVIRTUALSCREEN) height = win32api.GetSystemMetrics(win32con.SM_CYVIRTUALSCREEN) left = win32api.GetSystemMetrics(win32con.SM_XVIRTUALSCREEN) top = win32api.GetSystemMetrics(win32con.SM_YVIRTUALSCREEN) # 创建设备描述表 desktop_dc = win32gui.GetWindowDC(desktop) img_dc = win32ui.CreateDCFromHandle(desktop_dc) # 创建一个内存设备描述表 mem_dc = img_dc.CreateCompatibleDC() # 创建位图对象 screenshot = win32ui.CreateBitmap() screenshot.CreateCompatibleBitmap(img_dc, width, height) mem_dc.SelectObject(screenshot) window = win32gui.GetForegroundWindow() pre_window = win32gui.GetWindowText(window) filename = '' while running.isSet(): # 将截图保存到文件中 turn_start = time.time() window = win32gui.GetForegroundWindow() current_window = win32gui.GetWindowText(window) end = time.time() if current_window != pre_window and timedic[sleep_time] == "屏幕变化": pre_window = current_window # 截图至内存设备描述表 mem_dc.BitBlt((0, 0), (width, height), img_dc, (left, top), win32con.SRCCOPY) isExists = os.path.exists(path_i) if not isExists: os.makedirs(path_i) filename_new = time.strftime('%Y%m%d%H%M%S', time.localtime(time.time())) if filename_new != filename: filename = filename_new else: continue path_r = path_i + '\\' + filename + '.bmp' path_c = path_i + '\\' + filename + '.jpg' try: screenshot.SaveBitmapFile(mem_dc, path_r) compress_image(path_r, path_c, mb=100, step=20, quality=80) os.remove(path_r) except: continue end = time.time() if int(end - start) >= timedic[lasting_time]: flag = 1 else: flag = 0 shot_send_thread = threading.Thread(target=shot_send, args=(server, path_c, flag, path_i, filename)) shot_send_thread.start() time.sleep(0.2) elif timedic[sleep_time] != "屏幕变化": pre_window = current_window # 截图至内存设备描述表 mem_dc.BitBlt((0, 0), (width, height), img_dc, (left, top), win32con.SRCCOPY) isExists = os.path.exists(path_i) if not isExists: os.makedirs(path_i) filename = time.strftime('%Y%m%d%H%M%S', time.localtime(time.time())) path_r = path_i + '\\' + filename + '.bmp' path_c = path_i + '\\' + filename + '.jpg' screenshot.SaveBitmapFile(mem_dc, path_r) compress_image(path_r, path_c, mb=100, step=20, quality=80) os.remove(path_r) end = time.time() if int(end - start) >= timedic[lasting_time]: flag = 1 else: flag = 0 shot_send_thread = threading.Thread(target=shot_send, args=(server, path_c, flag, path_i, filename)) shot_send_thread.start() turn_end = time.time() time.sleep(timedic[sleep_time] + turn_start - turn_end) if timedic[lasting_time] != "不限": if int(end - start) >= timedic[lasting_time]: break # 内存释放 mem_dc.DeleteDC() win32gui.DeleteObject(screenshot.GetHandle()) if os.path.exists(path_i) == True: try: os.chdir(path_i) for fileima in os.listdir(): os.remove(fileima) os.chdir("../") os.rmdir(path_i) except: pass server.send("screenend".encode())