enumwindows是windows平台获取所有顶级活动窗口标题最直接可靠的方式,需配合iswindowvisible和getwindowtextw双重过滤,使用std::vector存储utf-16标题,避免编码丢失与截断;linux/macos无等价api,跨平台不可行。

Windows平台用EnumWindows遍历窗口最直接
在Windows上,EnumWindows是获取所有顶级活动窗口标题的底层可靠方式。它不依赖UI自动化或进程注入,绕过UAC限制,且能捕获被隐藏但未销毁的窗口(比如最小化或托盘程序)。关键点在于:必须配合IsWindowVisible和GetWindowText做双重过滤,否则会拿到大量无效句柄或空标题。
- 回调函数里先调
IsWindowVisible,排除不可见窗口(如后台服务窗口、临时弹窗) - 再用
GetWindowText读取标题,注意缓冲区长度至少256字节,否则截断 - 避免对
WS_EX_TOOLWINDOW类窗口盲目过滤——有些合法工具栏(如OneDrive状态栏)也带此样式但需保留 - 不要用
GetForegroundWindow替代,它只返回一个窗口,不是“所有”
std::vector<:wstring></:wstring>存标题比std::string更安全
Windows API默认使用UTF-16编码,GetWindowTextW返回宽字符。若强行用std::string接收,会丢失中文、emoji等非ASCII字符,且可能因编码转换引入空字节导致字符串提前截断。直接用std::wstring是最小改动、零风险的选择。
- 声明容器:
std::vector<:wstring> titles;</:wstring> - 调用
GetWindowTextW(hWnd, buffer, MAX_PATH),buffer类型为wchar_t[256] - 构造
std::wstring(buffer)插入vector,无需手动处理BOM或编码转换 - 如果后续要转UTF-8输出,用
std::wstring_convert<:codecvt_utf8>></:codecvt_utf8>(C++17前)或std::from_bytes(C++20起)
Linux/macOS没有等价API,得换思路
Linux下X11/Wayland、macOS下Cocoa都没有全局“活动窗口列表”概念。所谓“活动”依赖WM(窗口管理器)实现,不同桌面环境行为不一致。硬要实现,只能退到进程级粗粒度方案:查/proc/[pid]/cmdline + xdotool search --onlyvisible --name ""(X11)或cgwindow -l(macOS),但结果不稳定、权限要求高、且无法区分“活动”与“可见”。
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
- X11下
xdotool命令行工具最常用,但需用户手动安装,且Wayland默认禁用 - macOS用
CGWindowListCopyWindowInfo可获取窗口信息,但需启用辅助功能权限,且返回的是CFArrayRef需手动转CFString再转C++ string - 跨平台库如Qt的
QGuiApplication::topLevelWindows()只返回本进程创建的窗口,不满足“系统所有”需求 - 结论:除非明确限定Windows平台,否则这个问题本身在非Windows上无通用解
容易漏掉的细节:权限、线程与窗口生命周期
即使代码逻辑正确,仍可能拿不到预期窗口——问题常出在权限模型和调用时机。比如UWP应用窗口默认不可枚举;某些安全软件会拦截EnumWindows;还有窗口在回调执行中途被销毁,导致GetWindowText返回0。
- 以管理员权限运行程序仅解决部分权限问题,对UWP/沙盒应用无效
- 避免在DLL注入或低权限子进程中调用,
EnumWindows可能被拦截 - 回调中对
hWnd做IsWindow二次校验,防止句柄失效 - 不要在GUI线程长时间阻塞,枚举过程若超时可能被系统终止(尤其窗口数>1000时)
真正难的不是写几行EnumWindows,而是判断哪些窗口该算“活动”——焦点、Z-order、任务栏可见性、DWM缩略图状态……这些信号分散在不同API里,没一个字段能一锤定音。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!










