Search code examples
pythonpython-3.xscreenpywin32win32gui

Python app capturing with scaling monitor


I'm trying to capture a window (in the example code I'll use firefox), I'm running 2 monitors the first one in 2736x1824 with 200% scaling and the second one in 1920x1080 with 100% scaling.

    from win32 import win32gui

    def enum_cb(hwnd, results):
       # CallBack function for enumeration
       winlist.append((hwnd, win32gui.GetWindowText(hwnd)))
    def get_screens():
        win32gui.EnumWindows(enum_cb, winlist)
        return [(hwnd, title) for hwnd, title in winlist if title]
    def get_screensbyname(screen_name):
       # Function who gets a screen by name
       winlist = get_screens()
       screens = [(hwnd, title) for hwnd, title in winlist if screen_name in title.lower()]
       while len(screens) <= 0:
           winlist = get_screens()
           screens = [(hwnd, title) for hwnd, title in winlist if screen_name in title.lower()]
       return screens
    winlist = []
    windows = get_screensbyname('firefox')
    window = windows[0][0]
    wRect = win32gui.GetWindowRect(window)
    cRect = win32gui.GetClientRect(window)
    print('GetWindowRect ', wRect)
    print('GetCLientRect ', cRect)

If the window is on the first screen it outputs

GetWindowRect (-7, -7, 1374, 878)
GetCLientRect (0, 0, 1368, 878)

If the window is on the second screen it outputs

GetWindowRect (2728, 345, 4664, 1401)
GetCLientRect (0, 0, 1920, 1048)

Now, to my understanding, it ignores the given scaling on the monitor. Since if I manually apply the scaling (using a calculator) the first output changes to

GetWindowRect (-14, -14, 2748, 1756)
GetCLientRect (0, 0, 2736, 1756)

How can I apply the scaling or the dpi awerness that is set on the monitor the window is on?

I need it to capture the inside area and stream it to a file or on the other screen


Solution

  • The solution is relatively simple add the following lines

    import ctypes
    ctypes.windll.shcore.SetProcessDpiAwareness(2)
    

    It also works setting SetProcessDpiAwareness(1) don't know the difference between these two. If anyone could explain it it would be nice.

    NOTE: this answer will be set as solution tomorrow