Skip to content

Commit

Permalink
Merge pull request #83 from Avasam/check-before-printwindow
Browse files Browse the repository at this point in the history
check before PrintWindow
  • Loading branch information
Toufool authored Nov 12, 2021
2 parents b9468f2 + cada37b commit b1b9beb
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 14 deletions.
2 changes: 1 addition & 1 deletion src/about.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ def retranslateUi(self, aboutAutoSplitWidget):
aboutAutoSplitWidget.setWindowTitle(_translate("aboutAutoSplitWidget", "About AutoSplit", None))
self.okButton.setText(_translate("aboutAutoSplitWidget", "OK", None))
self.createdbyLabel.setText(_translate("aboutAutoSplitWidget", "<html><head/><body><p>Created by <a href=\"https://twitter.com/toufool\"><span style=\" text-decoration: underline; color:#0000ff;\">Toufool</span></a> and <a href=\"https://twitter.com/faschz\"><span style=\" text-decoration: underline; color:#0000ff;\">Faschz</span></a></p></body></html>", None))
self.versionLabel.setText(_translate("aboutAutoSplitWidget", "Version: 1.5.1", None))
self.versionLabel.setText(_translate("aboutAutoSplitWidget", "Version: 1.5.2", None))
self.donatetextLabel.setText(_translate("aboutAutoSplitWidget", "If you enjoy using this program, please\n"
" consider donating. Thank you!", None))
self.donatebuttonLabel.setText(_translate("aboutAutoSplitWidget", "<html><head/><body><p><a href=\"https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=BYRHQG69YRHBA&item_name=AutoSplit+development&currency_code=USD&source=url\"><img src=\":/resources/donatebutton.png\"/></p></body></html>", None))
Expand Down
50 changes: 37 additions & 13 deletions src/capture_windows.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,18 @@
from ctypes import windll
from ctypes.wintypes import LONG, RECT
from ctypes.wintypes import LONG, RECT, HBITMAP
from typing import Dict
from win32 import win32gui
import sys
from packaging import version
import platform
import numpy as np
import win32ui
import win32con

# This is an undocumented nFlag value for PrintWindow
PW_RENDERFULLCONTENT = 0x00000002
accelerated_windows: Dict[int, bool] = {}
is_windows_11 = version.parse(platform.version()) >= version.parse("10.0.22000")


def capture_region(hwnd: int, rect: RECT):
Expand All @@ -19,26 +25,44 @@ def capture_region(hwnd: int, rect: RECT):
@return: The image of the region in the window in BGRA format
"""

# Windows 11 has some jank, and we're not ready to fully investigate it
# for now let's ensure it works at the cost of performance
is_accelerated_window = is_windows_11 or accelerated_windows.get(hwnd)

# The window type is not yet known, let's find out!
if is_accelerated_window is None:
# We need to get the image at least once to check if it's full black
image = __get_image(hwnd, rect, False)
# TODO check for first non-black pixel, no need to iterate through the whole image
is_accelerated_window = not np.count_nonzero(image)
accelerated_windows[hwnd] = is_accelerated_window
return __get_image(hwnd, rect, True) if is_accelerated_window else image

return __get_image(hwnd, rect, is_accelerated_window)


def __get_image(hwnd: int, rect: RECT, print_window=False):
width: LONG = rect.right - rect.left
height: LONG = rect.bottom - rect.top

windowDC = win32gui.GetWindowDC(hwnd)
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()
bmp = win32ui.CreateBitmap()
bmp.CreateCompatibleBitmap(dcObject, width, height)
compatibleDC.SelectObject(bmp)
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)

# Force render full content through PrintWindow. Workaround to capture hardware accelerated windows
windll.user32.PrintWindow(hwnd, dcObject.GetSafeHdc(), PW_RENDERFULLCONTENT)

img: np._BufferType = np.frombuffer(bmp.GetBitmapBits(True), dtype='uint8')
img.shape = (height, width, 4)
image: np._BufferType = np.frombuffer(bitmap.GetBitmapBits(True), dtype='uint8')
image.shape = (height, width, 4)

dcObject.DeleteDC()
compatibleDC.DeleteDC()
win32gui.ReleaseDC(hwnd, windowDC)
win32gui.DeleteObject(bmp.GetHandle())
win32gui.DeleteObject(bitmap.GetHandle())

return img
return image

0 comments on commit b1b9beb

Please sign in to comment.