Skip to content
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

pywin32 is already a requirement, Can an hwnd_exists function be added to pyvda.py? #48

Open
phpjunkie420 opened this issue Jul 28, 2024 · 0 comments

Comments

@phpjunkie420
Copy link

phpjunkie420 commented Jul 28, 2024

def hwnd_exists(hwnd) -> bool:
    _exists = False

    def enum_windows(hwnd, _hwnd):
        nonlocal _exists

        if hwnd == _hwnd:
            _exists = True

    win32gui.EnumWindows(enum_windows, hwnd)

    return _exists

I used the pyvda.utils.Managers().view_collection.GetViewsByZOrder() to get the hwnd, and with psutil.Process to create a class that wraps the whole app. I have four windows of PyCharm open and this will return a screenshot of each window that is attached to pycharm64.exe process.

import ctypes

import cv2 as cv
import numpy
import psutil
import pyvda
import pyvda.com_defns
import pyvda.utils
import win32con
import win32gui
import win32ui


class AppProcess(psutil.Process, pyvda.AppView):
    def __init__(self, hwnd: int):
        from win32process import GetWindowThreadProcessId as GetPID

        psutil.Process.__init__(self, pid = GetPID(hwnd)[1])
        pyvda.AppView.__init__(self, hwnd = hwnd)

    @property
    def window_title(self) -> str:
        return win32gui.GetWindowText(self.hwnd)

    @property
    def name(self):
        return psutil.Process.name(self)

    @property
    def screenshot(self):
        def hwnd_exists(hwnd: int) -> bool:
            _exists = False

            def enum_windows(hwnd, _hwnd):
                nonlocal _exists

                if _hwnd == hwnd:
                    _exists = True

            win32gui.EnumWindows(enum_windows, hwnd)

            return _exists

        def reshape(left: int, top: int, right: int, bottom: int):
            return right - left, bottom - top

        if not hwnd_exists(self.hwnd):
            return numpy.array([])

        ctypes.windll.user32.SetProcessDPIAware()

        width, height = reshape(*win32gui.GetWindowRect(self.hwnd))

        wdc = win32gui.GetWindowDC(self.hwnd)
        dc = win32ui.CreateDCFromHandle(wdc)
        cdc = dc.CreateCompatibleDC()
        bitmap = win32ui.CreateBitmap()
        bitmap.CreateCompatibleBitmap(dc, width, height)
        cdc.SelectObject(bitmap)
        cdc.BitBlt((0, 0), (width, height), dc, (0, 0), win32con.SRCCOPY)

        ctypes.windll.user32.PrintWindow(self.hwnd, cdc.GetSafeHdc(), 3)

        _screenshot = numpy.frombuffer(bitmap.GetBitmapBits(True), dtype = numpy.uint8).reshape((height, width, 4))

        dc.DeleteDC()
        cdc.DeleteDC()
        win32gui.ReleaseDC(self.hwnd, wdc)
        win32gui.DeleteObject(bitmap.GetHandle())

        return _screenshot


def get_handles_by_z_order():
    _: list[int] = []
    array = pyvda.utils.Managers().view_collection.GetViewsByZOrder()
    for view in array.iter(pyvda.com_defns.IApplicationView):
        if bool(view.GetShowInSwitchers()):
            _.append(view.GetThumbnailWindow())
    return _


if __name__ == '__main__':
    for hwnd in get_handles_by_z_order().copy():
        process = AppProcess(hwnd = hwnd)
        if process.name == 'pycharm64.exe':
            cv.imshow(winname = 'screenshot', mat = process.screenshot)
            cv.waitKey()

To change it up a bit...

if __name__ == '__main__':
    for hwnd in get_handles_by_z_order().copy():
        process = AppProcess(hwnd = hwnd)
        if process.name == 'ACMirage.exe':
            screenshot = cv.resize(
                src = process.screenshot,
                dsize = (0, 0),
                fx = 0.5,
                fy = 0.5
            )
            cv.imshow(winname = 'screenshot', mat = screenshot)
            cv.waitKey()

Screenshot 2024-07-28 152100

Anyway I see a point in having the def hwnd_exists(hwnd: int) -> bool: function.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant