C++从线程 ID 列表中查找 GUI 线程

C++ finding the GUI thread from a list of thread IDs

本文关键字:线程 查找 GUI ID C++ 列表      更新时间:2023-10-16

我正在C++构建一个应用程序,该程序使用Windows钩子来控制第三方程序。我正在制作的程序是一个教程程序,用于展示如何使用这些第三方程序。我可以找到要挂钩的第三方程序的进程 ID,然后可以查询此进程 ID 以查找要用作 Windows API 函数 SetWindowsHookEx 参数的线程 ID 列表。但是,我担心从正在运行的进程的线程 ID 列表中,我将挂接到可能随时完成的线程。理想情况下,我想挂在运行主 gui 的线程中,该线程很可能是最长寿命的线程之一(即使它不是最长寿命的线程,教程程序也旨在与 GUI 配合使用,因此它仍然是理想的)。如果第三方应用程序有多个 GUI,那么我想找到主 GUI 的线程 ID。

所以我的问题是从我从查询进程 ID 中获得的线程 ID 列表中,有没有办法找到主 GUI ID 或其他合适的线程,该线程将在程序退出之前处于活动状态?显然,我选择的线程 ID 需要有一个事件队列,以便我可以挂接到它。

如何找到应用程序的主窗口,然后使用 GetWindowThreadProcessId 获取该窗口的线程 ID?

如果您还不知道主窗口,可以尝试使用 FindWindow() 查找它(如果您知道窗口名称和类名),或者 EnumWindows() 枚举桌面上的所有顶级窗口,并检查它们是否属于目标进程(再次使用 GetWindowThreadProcessId,并与您的进程 ID 进行比较)。

主窗口通常是设置了WS_CAPTION样式位的窗口。还应检查窗口是否可见(IsWindowVisible),以避免隐藏的工作窗口(通常属于工作线程)。还可以检查WS_POPUP和WS_EX_TOOLWINDOW样式以过滤掉顶级浮动和对话框窗口 - 尽管它们通常由主 GUI 线程拥有。

应用程序可以有任意数量的"主窗口"和GUI线程;通常只有一个 - 但没有什么可以阻止开发人员创建多个线程,每个线程都有自己的主顶级窗口和消息循环。如果需要处理这种情况,最好的办法可能是挂接所有似乎拥有交互式 UI 的线程。

确定线程是否为 GUI 线程的最简单、最可靠的方法是调用 GetGUIThreadInfo:

如果指定的线程没有 [...] 具有输入队列,则该函数将失败。

其中,具有输入队列可将 GUI 线程与常规线程区分开来。