如何编写Python脚本准确计算桌面被可见窗口遮挡的百分比?
解决桌面遮挡百分比计算的问题
原代码的核心问题
- 窗口筛选错误:使用
EnumChildWindows获取桌面子窗口,包含大量非顶层窗口(如按钮、控件、托盘小窗口等),而非真正的顶层应用窗口。 - 未排除无效窗口:没有过滤最小化窗口、不可见窗口,以及完全不在桌面区域内的窗口。
- 重叠区域重复计算:直接累加所有窗口面积,重叠部分被多次扣除,导致结果远大于实际遮挡比例。
修改后的代码
import win32api import win32gui import win32con def merge_rectangles(rects): """合并重叠或相邻的矩形,返回合并后的矩形列表""" if not rects: return [] # 按左边界排序 sorted_rects = sorted(rects, key=lambda r: r[0]) merged = [sorted_rects[0]] for current in sorted_rects[1:]: last = merged[-1] # 当前矩形与最后一个合并矩形重叠或相邻 if current[0] <= last[2] and current[1] <= last[3]: # 计算新的合并矩形 new_left = min(last[0], current[0]) new_top = min(last[1], current[1]) new_right = max(last[2], current[2]) new_bottom = max(last[3], current[3]) merged[-1] = (new_left, new_top, new_right, new_bottom) else: merged.append(current) return merged def calculate_covered_area(rects): """计算矩形列表的总面积(去重重叠部分)""" merged_rects = merge_rectangles(rects) total = 0 for rect in merged_rects: left, top, right, bottom = rect width = right - left height = bottom - top if width > 0 and height > 0: total += width * height return total def get_desktop_covered_percentage(): # 获取虚拟桌面的尺寸(支持多显示器) desktop_left = win32api.GetSystemMetrics(win32con.SM_XVIRTUALSCREEN) desktop_top = win32api.GetSystemMetrics(win32con.SM_YVIRTUALSCREEN) desktop_width = win32api.GetSystemMetrics(win32con.SM_CXVIRTUALSCREEN) desktop_height = win32api.GetSystemMetrics(win32con.SM_CYVIRTUALSCREEN) desktop_rect = (desktop_left, desktop_top, desktop_left + desktop_width, desktop_top + desktop_height) desktop_area = desktop_width * desktop_height if desktop_area == 0: return 0.0 valid_window_rects = [] def enum_window_callback(hwnd, extra): # 筛选条件: # 1. 窗口可见 if not win32gui.IsWindowVisible(hwnd): return True # 2. 窗口未最小化 if win32gui.IsIconic(hwnd): return True # 3. 获取窗口矩形 rect = win32gui.GetWindowRect(hwnd) left, top, right, bottom = rect # 4. 窗口有实际大小 if right <= left or bottom <= top: return True # 5. 窗口与桌面区域有交集 if right < desktop_rect[0] or left > desktop_rect[2] or bottom < desktop_rect[1] or top > desktop_rect[3]: return True # 6. 若不需要统计任务栏,可取消以下注释: # if win32gui.GetClassName(hwnd) == "Shell_TrayWnd": # return True # 裁剪窗口到桌面范围内(避免窗口超出桌面的部分被计算) clipped_left = max(left, desktop_rect[0]) clipped_top = max(top, desktop_rect[1]) clipped_right = min(right, desktop_rect[2]) clipped_bottom = min(bottom, desktop_rect[3]) valid_window_rects.append((clipped_left, clipped_top, clipped_right, clipped_bottom)) return True # 枚举所有顶层窗口 win32gui.EnumWindows(enum_window_callback, None) # 计算所有有效窗口的并集面积 covered_area = calculate_covered_area(valid_window_rects) # 计算遮挡百分比 percentage = (covered_area / desktop_area) * 100 # 确保结果在0-100之间 return max(0.0, min(100.0, percentage)) if __name__ == "__main__": percentage = get_desktop_covered_percentage() print(f"桌面被窗口遮挡的百分比: {percentage:.2f}%")
关键修改说明
- 窗口筛选逻辑:使用
EnumWindows枚举顶层窗口,通过多条件过滤有效窗口,确保只统计可见、非最小化且与桌面有交集的顶层窗口。 - 重叠区域处理:实现矩形合并函数,将重叠或相邻的窗口矩形合并,避免重叠部分重复计算,保证面积统计准确。
- 多显示器适配:使用虚拟屏幕尺寸获取完整桌面范围,同时将窗口矩形裁剪到桌面边界内,避免超出桌面的区域被错误统计。
- 结果校准:将最终百分比限制在0-100区间,避免计算误差导致的异常值。
内容的提问来源于stack exchange,提问作者Neo-S
相关产品推荐
相关产品推荐

