我有一个用
EnumWindows
枚举窗口的进程。 EnumWindowsProc 创建一个长时间处理窗口句柄的线程。
主线程定期调用
EnumWindows
来检查是否有新的窗口需要枚举。我需要能够识别已经枚举的窗口,以便不会为那些已经枚举的窗口重新创建更多线程。
我刚刚更改了窗口的标题栏以识别之前枚举的窗口,但是一些后台窗口(例如 GDI+ 帮助程序窗口、用户会话帮助程序窗口)无法重命名,因此为它们创建线程会浪费内存每次
EnumWindows
通话。我可以对程序进行硬编码来识别这些名称,但这似乎并不理想。
有人可以告诉我是否有更好的方法来做到这一点?我不需要处理那些不可见的窗口,只需处理那些可见的窗口(例如任务栏上的窗口)。感谢您的阅读!
您可以通过检查其
WS_VISIBLE
样式来过滤掉不可见的窗口:
if(GetWindowLong(hwnd, GWL_STYLE) & WS_VISIBLE)
; // the window is visible
要确定是否已有线程处理该窗口,您可以保留已知窗口的哈希表:
std::unordered_set<HWND> S;
// when new window is found:
S.insert(hwnd);
// when done processing the window:
S.erase(hwnd);
// to check if the window is known:
if(S.find(hwnd) == S.end())
; // the window is not in the set
窗口句柄是系统全局的,在窗口的生命周期内不会改变。然而,如果窗口被创建和销毁,它们最终可能会被重用——但据我所知,没有办法解决这个问题。
主线程定期调用EnumWindows来检查是否有新的窗口需要枚举。
我建议使用
SetWindowsHookEx()
来检测何时创建新窗口。
我刚刚更改了窗口的标题栏以识别之前已枚举的窗口。
一种侵入性较小的方法可能是使用
SetProp()
在每个窗口内存储自定义标记,然后您可以稍后查找该标记。在销毁每个窗口之前,您必须在每个窗口上调用 RemoveProp()
,但您也可以使用钩子来实现这一点。
或者,您可以简单地将每个
HWND
存储在您自己的列表中,然后在添加任何新的 HWND
之前检查该列表。您仍然需要使用钩子来检测每个 HWND
何时被销毁,以便您可以将其从列表中删除。