win32con常量解析及全屏窗口样式判断技术求助
Windows窗口样式数值生成逻辑与全屏窗口区分解析
问题背景
需要区分普通全屏(窗口最大化)和独占全屏窗口,编写Python代码获取窗口样式时,发现win32con.WS_MAXIMIZE常量值和输出的窗口样式数值不匹配,想搞清楚Windows窗口样式数值的生成逻辑。已知《漫威蜘蛛侠:重制版》是独占全屏,PotPlayer播放视频时为普通全屏。
窗口样式数值的核心逻辑
Windows窗口样式是**位掩码(Bitmask)**结构:
- 每个
WS_/WS_EX_常量对应二进制中的某一位(仅该位为1,其余为0),比如WS_MAXIMIZE = 16777216,对应二进制是10000000000000000000000(第25位,从0开始计数)。 - 窗口的最终样式数值,是多个样式常量的**按位或(OR)**结果(因每个位不重叠,也可理解为数值相加)。也就是说,样式数值的每一位代表是否启用了对应的样式属性。
- 判断某个样式是否启用,必须用**按位与(AND)**操作:若
(窗口样式数值 & 目标常量) != 0,说明该样式已启用;直接对比数值是否相等是错误的,因为窗口样式是多个属性的组合。
结合输出与代码分析
1. WS_MAXIMIZE的判断逻辑
代码中用GetWindowLong(window.hwnd, win32con.GWL_STYLE) & win32con.WS_MAXIMIZE过滤窗口,输出的MAXIMIZED列表里没有《漫威蜘蛛侠:重制版》,这正是独占全屏的核心特征:
- 独占全屏不是通过普通窗口最大化实现的,而是直接接管显示设备,因此它的窗口样式中不会设置
WS_MAXIMIZE位。 - PotPlayer的普通全屏本质是窗口最大化,其样式中包含
WS_MAXIMIZE位,未出现在列表可能是代码执行时窗口状态变化或get_apps_by_z_order的过滤逻辑导致,但核心判断逻辑是成立的。
2. 各窗口样式数值拆解
GWL_STYLE(基础样式)
- 漫威蜘蛛侠:
369098752=WS_VISIBLE(268435456) + WS_CLIPSIBLINGS(67108864) + WS_CLIPCHILDREN(33554432),无WS_MAXIMIZE位,符合独占全屏的样式特征。 - PotPlayer:
-1764818944转32位无符号整数为2530148352,包含WS_MAXIMIZE(16777216)、WS_VISIBLE(268435456)及WS_OVERLAPPEDWINDOW相关位,是普通最大化窗口的典型样式。
GWL_EXSTYLE(扩展样式)
- 漫威蜘蛛侠:
8=WS_EX_TOPMOST,符合独占全屏窗口置顶、独占显示的特征。 - PotPlayer:
262416=WS_EX_APPWINDOW(262144) + WS_EX_WINDOWEDGE(256),是普通窗口最大化后的典型扩展样式。
区分两种全屏的关键方法
独占全屏:
- 基础样式(GWL_STYLE)中不包含
WS_MAXIMIZE位(& win32con.WS_MAXIMIZE == 0) - 通常包含
WS_POPUP、WS_VISIBLE位 - 扩展样式(GWL_EXSTYLE)可能包含
WS_EX_TOPMOST - 辅助判断:窗口覆盖整个屏幕且无标题栏、边框(通过
WS_BORDER、WS_CAPTION位判断)
- 基础样式(GWL_STYLE)中不包含
普通全屏(窗口最大化):
- 基础样式中包含
WS_MAXIMIZE位(& win32con.WS_MAXIMIZE != 0) - 通常包含
WS_OVERLAPPEDWINDOW相关位(WS_CAPTION、WS_BORDER等) - 扩展样式可能包含
WS_EX_APPWINDOW
- 基础样式中包含
附:代码与输出内容
Python代码
from win32gui import GetWindowLong, GetWindowText from pyvda import AppView, get_apps_by_z_order # noqa from datetime import datetime import win32con import inspect # Spider-Man: Exclusive Fullscreen tinmestamp = datetime.now().timestamp() while datetime.now().timestamp() - tinmestamp < 10: continue with open('GWL.txt', 'w') as file: for key, value in [member for member in inspect.getmembers(win32con) if 'GWL' in member[0]]: file.write(f'{key + ": int":35} = {value}\n') with open('256.txt', 'w') as file: for key, value in [member for member in inspect.getmembers(win32con) if member[1] == 256]: file.write(f'{key + ": int":35} = {value}\n') with open('WS.txt', 'w') as file: for key, value in [member for member in inspect.getmembers(win32con) if member[0].startswith('WS_')]: file.write(f'{key + ": int":35} = {value}\n') with open('win32con.txt', 'w') as file: for key, value in [member for member in inspect.getmembers(win32con) if member[0].isupper()]: file.write(f'{key + ": int":35} = {value}\n') print(f'{"MAXIMIZED":>12}') windows = [window for window in get_apps_by_z_order(current_desktop = False) if (GetWindowLong(window.hwnd, win32con.GWL_STYLE) & win32con.WS_MAXIMIZE)] for window in windows: print(f'{GetWindowText(window.hwnd)}') print() print(f'{"GWL_STYLE":>12}') for window in get_apps_by_z_order(current_desktop = False): print(f'{GetWindowLong(window.hwnd, win32con.GWL_STYLE):<15} {GetWindowText(window.hwnd)}') print() print(f'{"GWL_EXSTYLE":>14}') for window in get_apps_by_z_order(current_desktop = False): print(f'{GetWindowLong(window.hwnd, win32con.GWL_EXSTYLE):<15} {GetWindowText(window.hwnd)}')
代码输出
MAXIMIZED MonitorPowerUtility – topmost.py Alienware Command Center GWL_STYLE 369098752 Marvel's Spider-Man Remastered v2.616.0.0 399441920 MonitorPowerUtility – topmost.py -1781596160 Alienware Command Center 382664704 Can anyone explain to me how these constants in win32con are picked apart? - Stack Overflow — Mozilla Firefox -1764818944 FBI - S02E14 - Studio Gangster.mkv - PotPlayer GWL_EXSTYLE 8 Marvel's Spider-Man Remastered v2.616.0.0 256 MonitorPowerUtility – topmost.py 2097408 Alienware Command Center 256 Can anyone explain to me how these constants in win32con are picked apart? - Stack Overflow — Mozilla Firefox 262416 FBI - S02E14 - Studio Gangster.mkv - PotPlayer
生成的WS.txt内容
WS_ACTIVECAPTION: int = 1 WS_BORDER: int = 8388608 WS_CAPTION: int = 12582912 WS_CHILD: int = 1073741824 WS_CHILDWINDOW: int = 1073741824 WS_CLIPCHILDREN: int = 33554432 WS_CLIPSIBLINGS: int = 67108864 WS_DISABLED: int = 134217728 WS_DLGFRAME: int = 4194304 WS_EX_ACCEPTFILES: int = 16 WS_EX_APPWINDOW: int = 262144 WS_EX_CLIENTEDGE: int = 512 WS_EX_COMPOSITED: int = 33554432 WS_EX_CONTEXTHELP: int = 1024 WS_EX_CONTROLPARENT: int = 65536 WS_EX_DLGMODALFRAME: int = 1 WS_EX_LAYERED: int = 524288 WS_EX_LAYOUTRTL: int = 4194304 WS_EX_LEFT: int = 0 WS_EX_LEFTSCROLLBAR: int = 16384 WS_EX_LTRREADING: int = 0 WS_EX_MDICHILD: int = 64 WS_EX_NOACTIVATE: int = 134217728 WS_EX_NOINHERITLAYOUT: int = 1048576 WS_EX_NOPARENTNOTIFY: int = 4 WS_EX_OVERLAPPEDWINDOW: int = 768 WS_EX_PALETTEWINDOW: int = 392 WS_EX_RIGHT: int = 4096 WS_EX_RIGHTSCROLLBAR: int = 0 WS_EX_RTLREADING: int = 8192 WS_EX_STATICEDGE: int = 131072 WS_EX_TOOLWINDOW: int = 128 WS_EX_TOPMOST: int = 8 WS_EX_TRANSPARENT: int = 32 WS_EX_WINDOWEDGE: int = 256 WS_GROUP: int = 131072 WS_HSCROLL: int = 1048576 WS_ICONIC: int = 536870912 WS_MAXIMIZE: int = 16777216 WS_MAXIMIZEBOX: int = 65536 WS_MINIMIZE: int = 536870912 WS_MINIMIZEBOX: int = 131072 WS_OVERLAPPED: int = 0 WS_OVERLAPPEDWINDOW: int = 13565952 WS_POPUP: int = -2147483648 WS_POPUPWINDOW: int = -2138570752 WS_SIZEBOX: int = 262144 WS_SYSMENU: int = 524288 WS_TABSTOP: int = 65536 WS_THICKFRAME: int = 262144 WS_TILED: int = 0 WS_TILEDWINDOW: int = 13565952 WS_VISIBLE: int = 268435456 WS_VSCROLL: int = 2097152
内容的提问来源于stack exchange,提问作者phpjunkie
相关产品推荐
相关产品推荐

