Get window position & size with python
Asked Answered
E

8

44

How can I get and set the window (any windows program) position and size with python?

Ewing answered 22/8, 2011 at 1:24 Comment(2)
A window owned by the current process, or any top-level window shown on the desktop?Michaels
I'd like to know if there is any way to do this without having to install third party software or non-native libraries. It seems logically that it should be possible. If not though, then why not?.Daemon
S
49

Assuming you're on Windows, try using pywin32's win32gui module with its EnumWindows and GetWindowRect functions.

If you're using Mac OS X, you could try using appscript.

For Linux, you can try one of the many interfaces to X11.

Edit: Example for Windows (not tested):

import win32gui

def callback(hwnd, extra):
    rect = win32gui.GetWindowRect(hwnd)
    x = rect[0]
    y = rect[1]
    w = rect[2] - x
    h = rect[3] - y
    print("Window %s:" % win32gui.GetWindowText(hwnd))
    print("\tLocation: (%d, %d)" % (x, y))
    print("\t    Size: (%d, %d)" % (w, h))

def main():
    win32gui.EnumWindows(callback, None)

if __name__ == '__main__':
    main()
Stanfordstang answered 22/8, 2011 at 1:29 Comment(7)
could you give me an example for windows?Bothnia
Any suggestions on how to do it under linux (preferably gnome)?Quadrant
@seler: As my answer said, you can try one of the interfaces to X11. Personally, I'd use xpyb. Iterate through the windows, finding the ones you want, and then get their geometries. The geometries contain the position and size of the windows.Stanfordstang
for a linux solution, see #1381284Natalienatalina
does not work for me: open windows calculator, make it to full screen on full hd monitor and getting strange value: Window Calculator: Location: (-7, -7) Size: (1550, 838). It has strict disproportion for 1.25 rate and stable shift for -7, -7 for top left point. looks really strangeUnderlie
@Underlie any idea on how to fix these issues? I also face the sameBibbie
what hwnd means!?Echoechoic
I
16

You can get the window coordinates using the GetWindowRect function. For this, you need a handle to the window, which you can get using FindWindow, assuming you know something about the window (such as its title).

To call Win32 API functions from Python, use pywin32.

Invalidism answered 22/8, 2011 at 1:29 Comment(1)
+ For suggesting to use FindWindow instead of enumTessin
C
9

As Greg Hewgill mentioned, if you know the name of the window, you can simply use win32gui's FindWindow, and GetWindowRect. This is perhaps a little cleaner and efficient than previous methods.

from win32gui import FindWindow, GetWindowRect

# FindWindow takes the Window Class name (can be None if unknown), and the window's display text. 
window_handle = FindWindow(None, "Diablo II")
window_rect   = GetWindowRect(window_handle)

print(window_rect)
#(0, 0, 800, 600)

For future reference: PyWin32GUI has now moved to Github

Crofter answered 19/8, 2020 at 14:5 Comment(1)
I'm getting (-32000, -32000, -31840, -31972) when the window is fullscreen (e.g. Diablo / Overwatch)Ruff
M
7

this can return window rect from window title

Code

import ctypes
from ctypes.wintypes import HWND, DWORD, RECT

def GetWindowRectFromName(name:str)-> tuple:
    hwnd = ctypes.windll.user32.FindWindowW(0, name)
    rect = ctypes.wintypes.RECT()
    ctypes.windll.user32.GetWindowRect(hwnd, ctypes.pointer(rect))
    # print(hwnd)
    # print(rect)
    return (rect.left, rect.top, rect.right, rect.bottom)

if __name__ == "__main__":
    print(GetWindowRectFromName('CALC'))
    pass

Environment

Python 3.8.2 | packaged by conda-forge | (default, Apr 24 2020, 07:34:03) [MSC v.1916 64 bit (AMD64)] on win32 Windows 10 Pro 1909

Mello answered 7/7, 2020 at 7:54 Comment(1)
if you using windows, ctypes.windll.user32 and ctypes.wintypes are loaded on default.Mello
D
4

For Linux you can use the tool I made here. The tool was meant for a slightly different use but you can use the API directly for your needs.

Install tool

sudo apt-get install xdotool xprop xwininfo
git clone https://github.com/Pithikos/winlaunch.git && cd winlaunch

In terminal

>>> from winlaunch import *
>>> wid, pid = launch('firefox')
>>> win_pos(wid)
[3210, 726]

wid and pid stand for window id and process id respectively.

Dwelling answered 1/2, 2016 at 20:57 Comment(1)
Thx a lot for this tool!Stambaugh
S
3

This code will work on windows. It return the position and size of the active window.

from win32gui import GetWindowRect, GetForegroundWindow
print(GetWindowRect(GetForegroundWindow()))
Stichometry answered 24/11, 2019 at 11:40 Comment(0)
C
3

Something not mentioned in any of the other responses is that in newer Windows (Vista and up), "the Window Rect now includes the area occupied by the drop shadow.", which is what win32gui.GetWindowRect and ctypes.windll.user32.GetWindowRect are interfacing with.

If you want to get the positions and sizes without the dropshadow, you can:

  1. Manually remove them. In my case there were 10 pixels on the left, bottom and right which had to be pruned.
  2. Use the dwmapi to extract the DWMWA_EXTENDED_FRAME_BOUNDS as mentioned in the article

On using the dwmapi.DwmGetWindowAttribute (see here):

This function takes four arguments: The hwnd, the identifier for the attribute we are interested in, a pointer for the data structure in which to write the attribute, the size of this data structure. The identifier we get by checking this enum. In our case, the attribute DWMWA_EXTENDED_FRAME_BOUNDS is on position 9.

import ctypes
from ctypes.wintypes import HWND, DWORD, RECT

dwmapi = ctypes.WinDLL("dwmapi")

hwnd = 133116    # refer to the other answers on how to find the hwnd of your window

rect = RECT()
DMWA_EXTENDED_FRAME_BOUNDS = 9
dwmapi.DwmGetWindowAttribute(HWND(hwnd), DWORD(DMWA_EXTENDED_FRAME_BOUNDS),
                             ctypes.byref(rect), ctypes.sizeof(rect))

print(rect.left, rect.top, rect.right, rect.bottom)

Lastly: "Note that unlike the Window Rect, the DWM Extended Frame Bounds are not adjusted for DPI".

Cibis answered 17/4, 2021 at 11:37 Comment(0)
H
0

None of these solutions worked for me on Mac/OSX. Most functions from pygetwindow are not implemented for OSX at this time (see pygetwindow/_pygetwindow_macos.py on Github).

Using the few functions that are implemented, this code will list all windows by name, then fetch each window's geometry in the format (top-left-X, top-left-Y, width, height):

import pygetwindow as gw # pip3 install pygetwindow

windows = gw.getAllTitles()
for win in windows:
    geometry = gw.getWindowGeometry(win)
    print(f'Window title: {win}')
    print(f'> top-left X coordinate: {geometry[0]}')
    print(f'> top-left Y coordinate: {geometry[1]}')
    print(f'> width: {geometry[2]}')
    print(f'> height: {geometry[3]}\n')

Example output:

Window title: iTerm2 IPython: ~/
> top-left X coordinate: 597.0
> top-left Y coordinate: 178.0
> width: 843.0
> height: 722.0

Window title: Google Chrome Get window position & size with python - Stack Overflow
> top-left X coordinate: 0.0
> top-left Y coordinate: 25.0
> width: 815.0
> height: 875.0

Window title: Finder Macintosh HD
> top-left X coordinate: 260.0
> top-left Y coordinate: 135.0
> width: 920.0
> height: 436.0

For reference, list of currently implemented pygetwindow functions:

- gw.getActiveWindow()
- gw.getAllTitles()
- gw.getWindowsAt()
- gw.getWindowGeometry(title)

This is working for me with this environment:

Python 3.11.6
PyGetWindow 0.0.9
OSX Ventura 13.5
Herald answered 2/11, 2023 at 1:35 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.