0

I have these functions in my program, which are supposed to take a screenshot of a specific application by copying its bitmap data and then crop that down to specific coordinates. Last night I was helpfully told that I was missing the .BitBlt() command, and after adding that to my screenshot() function (and adjusting the crop command to account for the starting coordinates of additional monitors), I finally got a cropped screenshot of an application like I wanted. I noticed that it didn't actually line up to anything on-screen, though, so I began exporting the original screenshot to a file. What I discovered was very strange: every time that I ran the program, it was showing me a screenshot of the application I had selected from a specific moment in time in the past. I was working on this for more than an hour, and every single time that I ran the program it would output the same screenshot. I was regularly using this application (my web browser) for the entire time. Even if I changed tabs, which changed the application name and thus the program outcome, it would still show me this one specific screenshot from this one moment in time. After waking up this morning, I tried running the program again on a different application, and it just outputs a black screen.

Here is my code:

def screenshot(window_title):
    hwnd = win32gui.FindWindow(None, window_title)
    #win32gui.InvalidateRect(hwnd, None, None)
    win32gui.RedrawWindow(hwnd, None, None, win32con.RDW_INVALIDATE | win32con.RDW_UPDATENOW)
    win32gui.UpdateWindow(hwnd)
    time.sleep(0.1)
    hwnd_dc = win32gui.GetWindowDC(hwnd)
    mfc_dc = win32ui.CreateDCFromHandle(hwnd_dc)
    save_dc = mfc_dc.CreateCompatibleDC()
    save_bit_map = win32ui.CreateBitmap()
    region = win32gui.GetWindowRect(hwnd)
    save_bit_map.CreateCompatibleBitmap(mfc_dc, abs(region[0]-region[2]), abs(region[1]-region[3]))
    save_dc.SelectObject(save_bit_map)
    #result = windll.user32.PrintWindow(hwnd, saveDC.GetSafeHdc(), 1)
    #print(result)
    save_dc.BitBlt((0, 0), (abs(region[0]-region[2]), abs(region[1]-region[3])), mfc_dc, (0, 0), win32con.SRCCOPY)
    bmp_info = save_bit_map.GetInfo()
    bmp_str = save_bit_map.GetBitmapBits(True)
    img = Image.frombuffer('RGB',
                           (bmp_info['bmWidth'], bmp_info['bmHeight']),
                           bmp_str, 'raw', 'BGRX', 0, 1)
    win32gui.DeleteObject(save_bit_map.GetHandle())
    save_dc.DeleteDC()
    mfc_dc.DeleteDC()
    win32gui.ReleaseDC(hwnd, hwnd_dc)
    return img.convert('RGB')

def cropCapture(window_title, x1, y1, width, height):
    print("running cropCapture")
    if window_title and x1 and y1 and width and height:
        print("values are present")
        img = screenshot(window_title)
        file1 = Path(__file__).parent / Path(
            f"screenshot1.png")
        img.save(file1)
        if img:
            print("CropCapture successful")
        hwnd = win32gui.FindWindow(None, window_title)
        plc = win32gui.GetWindowRect(hwnd)
        monitors = get_monitors()
        monitor = monitors[int(selected_monitor)-1]
        print(monitor)
        print(plc)
        print(width)
        print(height)
        box = (int(x1) - (plc[0] - monitor.x),
           int(y1) - (plc[1] - monitor.y),
           int(x1) - (plc[0] - monitor.x) + width,
           int(y1) - (plc[1] - monitor.y) + height)
        print(box)
        crp = img.crop(box)
        if crp:
            print("crop successful")
        global timg
        timg = crp
        file2 = Path(__file__).parent / Path(
            f"screenshot2.png")
        timg.save(file2)
        tkimg = itk.PhotoImage(timg)
        tempimg = imgdisplay.create_image(0, 0, image=tkimg)
        tempimg.grid(row=0, column=0)

After doing some research, I tried redrawing and refreshing the application window however I could before taking the screenshot. None of that worked. Someone also suggested that I needed PrintWindow() in there somewhere, however I have no idea what this was supposed to do and I couldn't figure out what I needed to import to make it work in the first place so I just commented it out. I also couldn't figure out how to make InvalidateRect() work, so I commented that out as well.

4
  • 1
    Probably save isn't working. Are the file date/time changing? Commented Aug 23, 2024 at 18:29
  • Save seems to be working fine. I'm not using date/time, but it appears to be overwriting the files. I've also tried deleting the screenshots before running it, in which case the new screenshots have the same issues. Commented Aug 23, 2024 at 19:30
  • The program is also using an image variable internally, which has the same issue, and shouldn't be affected by the save command. I can even remove saving from the program altogether and I still experience the same issue. Saving the screenshots is tangential, I'm just using it to diagnose problems for now. Commented Aug 23, 2024 at 19:31
  • Question text looks kinda shitty, please format it. Also modify the code so it's a [SO]: How to create a Minimal, Reproducible Example (reprex (mcve)), so that anyone willing to help doesn't waste time figuring out the imports for exomple. Commented Nov 16, 2024 at 21:51

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.