How to Get a Window or Fullscreen Screenshot in Python 3k? (without PIL)

后端 未结 4 1300
醉酒成梦
醉酒成梦 2020-12-05 01:05

With python 3, I\'d like to get a handle to another window (not part of my application) such that I can either:

a) directly capture that window as a scre

相关标签:
4条回答
  • 2020-12-05 01:38

    The solution here gets a screenshot of a single Window (so can work if the Window is in the background).

    Other solutions of this page take picture of the part of the screen the window is on, and thus need to bring the Window to the front first.

    Python Screenshot of inactive window PrintWindow + win32gui

    0 讨论(0)
  • 2020-12-05 01:44

    Here's how you can do it using PIL on win32. Given a window handle (hwnd), you should only need the last 4 lines of code. The preceding simply search for a window with "firefox" in the title. Since PIL's source is available, you should be able to poke around the ImageGrab.grab(bbox) method and figure out the win32 code you need to make this happen.

    from PIL import ImageGrab
    import win32gui
    
    toplist, winlist = [], []
    def enum_cb(hwnd, results):
        winlist.append((hwnd, win32gui.GetWindowText(hwnd)))
    win32gui.EnumWindows(enum_cb, toplist)
    
    firefox = [(hwnd, title) for hwnd, title in winlist if 'firefox' in title.lower()]
    # just grab the hwnd for first window matching firefox
    firefox = firefox[0]
    hwnd = firefox[0]
    
    win32gui.SetForegroundWindow(hwnd)
    bbox = win32gui.GetWindowRect(hwnd)
    img = ImageGrab.grab(bbox)
    img.show()
    
    0 讨论(0)
  • 2020-12-05 01:44

    This will take a new opened window and make a screenshot of it and then crop it with PIL also possible to find your specific window with pygetwindow.getAllTitles() and then fill in your window name in z3 to get screenshot of only that window.

    If you definitely not want to use PIL you can maximize window with pygetwindow module and then make a screenshot with pyautogui module.

    Note: not tested on Windows XP (but tested on Windows 10)

    import pygetwindow
    import time
    import os
    import pyautogui
    import PIL
    
    # get screensize
    x,y = pyautogui.size()
    print(f"width={x}\theight={y}")
    
    x2,y2 = pyautogui.size()
    x2,y2=int(str(x2)),int(str(y2))
    print(x2//2)
    print(y2//2)
    
    # find new window title
    z1 = pygetwindow.getAllTitles()
    time.sleep(1)
    print(len(z1))
    # test with pictures folder
    os.startfile("C:\\Users\\yourname\\Pictures")
    time.sleep(1)
    z2 = pygetwindow.getAllTitles()
    print(len(z2))
    time.sleep(1)
    z3 = [x for x in z2 if x not in z1]
    z3 = ''.join(z3)
    time.sleep(3)
    
    # also able to edit z3 to specified window-title string like: "Sublime Text (UNREGISTERED)"
    my = pygetwindow.getWindowsWithTitle(z3)[0]
    # quarter of screen screensize
    x3 = x2 // 2
    y3 = y2 // 2
    my.resizeTo(x3,y3)
    # top-left
    my.moveTo(0, 0)
    time.sleep(3)
    my.activate()
    time.sleep(1)
    
    # save screenshot
    p = pyautogui.screenshot()
    p.save(r'C:\\Users\\yourname\\Pictures\\\\p.png')
    
    # edit screenshot
    im = PIL.Image.open('C:\\Users\\yourname\\Pictures\\p.png')
    im_crop = im.crop((0, 0, x3, y3))
    im_crop.save('C:\\Users\\yourname\\Pictures\\p.jpg', quality=100)
    
    # close window
    time.sleep(1)
    my.close()
    
    0 讨论(0)
  • 2020-12-05 01:47

    Ars gave me all the pieces. I am just putting the pieces together here for anyone else who needs to get a screenshot in python 3.x. Next I need to figure out how to work with a win32 bitmap without having PIL to lean on.

    Get a Screenshot (pass hwnd for a window instead of full screen):

    def screenshot(hwnd = None):
        import win32gui
        import win32ui
        import win32con
        from time import sleep
        if not hwnd:
            hwnd=win32gui.GetDesktopWindow()
        l,t,r,b=win32gui.GetWindowRect(hwnd)
        h=b-t
        w=r-l
        hDC = win32gui.GetWindowDC(hwnd)
        myDC=win32ui.CreateDCFromHandle(hDC)
        newDC=myDC.CreateCompatibleDC()
    
        myBitMap = win32ui.CreateBitmap()
        myBitMap.CreateCompatibleBitmap(myDC, w, h)
    
        newDC.SelectObject(myBitMap)
    
        win32gui.SetForegroundWindow(hwnd)
        sleep(.2) #lame way to allow screen to draw before taking shot
        newDC.BitBlt((0,0),(w, h) , myDC, (0,0), win32con.SRCCOPY)
        myBitMap.Paint(newDC)
        myBitMap.SaveBitmapFile(newDC,'c:\\tmp.bmp')
    

    Get a Window Handle by title (to pass to the above function):

    def _get_windows_bytitle(title_text, exact = False):
        def _window_callback(hwnd, all_windows):
            all_windows.append((hwnd, win32gui.GetWindowText(hwnd)))
        windows = []
        win32gui.EnumWindows(_window_callback, windows)
        if exact:
            return [hwnd for hwnd, title in windows if title_text == title]
        else:
            return [hwnd for hwnd, title in windows if title_text in title]
    
    0 讨论(0)
提交回复
热议问题