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.
saveisn't working. Are the file date/time changing?