使用Python获取窗口位置和大小

43

如何使用Python获取和设置窗口(任何Windows程序)的位置和大小?


当前进程拥有的窗口,或者桌面上显示的任何顶级窗口? - André Caron
1
我想知道是否有任何方法可以在不安装第三方软件或非本地库的情况下完成此操作。从逻辑上讲,这似乎是可能的。如果不行,那么为什么呢? - Musixauce3000
8个回答

47
假设您使用的是Windows系统,可以尝试使用pywin32win32gui模块及其EnumWindowsGetWindowRect函数。
如果您使用的是Mac OS X系统,则可以尝试使用appscript
对于Linux系统,您可以尝试使用众多与X11接口相关的界面。 编辑:Windows示例(未经测试):
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()

你能给我一个Windows的例子吗? - Bruno 'Shady'
2
有关如何在Linux下(最好是Gnome)执行此操作的建议? - seler
2
@seler:正如我的回答所说,您可以尝试使用X11的接口之一。个人建议使用xpyb。遍历窗口,找到您想要的窗口,然后获取它们的几何信息。几何信息包含窗口的位置和大小。 - icktoofay
1
对于 Linux 解决方案,请参见 https://dev59.com/n3M_5IYBdhLWcg3wcCnc。 - DiCaprio
1
对我来说不起作用:打开Windows计算器,在全高清显示器上将其设置为全屏,并获得奇怪的值:窗口计算器: 位置:(-7,-7) 大小:(1550,838)。它具有1.25比例的严格不成比例和稳定的偏移量,对于左上角点的-7,-7看起来非常奇怪。 - user2602807
显示剩余2条评论

15
你可以使用 GetWindowRect 函数获取窗口坐标。为此,您需要窗口的句柄,可以使用 FindWindow 获取,假设您已经知道有关该窗口的一些信息(例如窗口标题)。
要从Python调用Win32 API函数,请使用pywin32

3
建议使用FindWindow而不是枚举。 - MadRabbit

9

如Greg Hewgill所说,如果您知道窗口的名称,可以直接使用win32gui的FindWindow和GetWindowRect。这可能比以前的方法更加清晰和高效。

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)

供将来参考:PyWin32GUI现已迁移到Github


当窗口全屏时(例如Diablo / Overwatch),我得到(-32000,-32000,-31840,-31972) - David

6

这可以从窗口标题返回窗口矩形

代码

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

环境

使用conda-forge打包的Python 3.8.2版本,(默认版本为Apr 24 2020, 07:34:03),在Windows 10 Pro 1909(64位)操作系统上运行。


如果您使用的是Windows系统,则默认加载ctypes.windll.user32ctypes.wintypes - ShortArrow

4
对于Linux,你可以使用我在这里制作的工具。这个工具原本是为了其他用途而设计的,但是你可以直接使用API满足你的需求。
安装工具。
sudo apt-get install xdotool xprop xwininfo
git clone https://github.com/Pithikos/winlaunch.git && cd winlaunch

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

widpid分别代表窗口ID和进程ID。


非常感谢这个工具! - hayj

3

这段代码适用于Windows系统。它返回当前活动窗口的位置和大小。

from win32gui import GetWindowText, GetForegroundWindow
print(GetWindowRect(GetForegroundWindow()))

2
在其他回答中提及的事情都没有提到的是,在更新的 Windows(Vista 及以上版本)中,“窗口矩形现在包括投影区域。”,这正是win32gui.GetWindowRectctypes.windll.user32.GetWindowRect所接口的内容。
如果你想获取位置和大小不包括阴影,你可以:
1. 手动删除它们。在我的情况下,左侧、底部和右侧各有 10 个像素必须被修剪。 2. 使用 dwmapi 提取文章中提到的 DWMWA_EXTENDED_FRAME_BOUNDS 关于使用 dwmapi.DwmGetWindowAttribute(参见 这里):
这个函数有四个参数:hwnd,我们感兴趣的属性标识符,用于写入属性的数据结构指针以及此数据结构的大小。我们通过检查 此枚举 来获取标识符。在我们的例子中,属性 DWMWA_EXTENDED_FRAME_BOUNDS 在第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)

最后提醒:请注意,与窗口矩形不同,DWM扩展框架边界没有根据DPI进行调整。

0

对于我在Mac/OSX上,这些解决方案都没有起作用。目前,pygetwindow 的大多数功能在OSX上尚未实现(请参见pygetwindow/_pygetwindow_macos.py on Github)。

使用已实现的少数功能,以下代码将按名称列出所有窗口,然后获取每个窗口的几何形状,格式为(左上角X坐标,左上角Y坐标,宽度,高度):

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')

示例输出:

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

以下是目前已实现的pygetwindow函数列表,供参考:

pygetwindow

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

这对我来说在这个环境下是有效的。
Python 3.11.6
PyGetWindow 0.0.9
OSX Ventura 13.5

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接