Win32:按真实激活顺序枚举真实窗口

use*_*019 5 winapi hwnd z-order

我现在已经厌倦了研究这个话题。系统中有上百万个 API 来实现部分功能,即枚举所有窗口,但没有涉及如何获取它们的真实 z 顺序。怎么做?让我解释。

首先,当然,要枚举窗口,可以使用EnumWindows或 当它表现不佳并决定不显示 UWP 应用程序时,因为操作系统中存在一些愚蠢的限制,可以直接使用NtUserBuildHwndList无论如何在后端调用的EnumWindows.

这样一来,您就可以在回调中过滤子窗口、隐藏窗口和奇怪的窗口。根据您所做的事情,您会得到不同的结果。为了让您免于阅读,最常见的方法是 Raymond Chen 那种过时的解决方案,或者尝试一些更新的方法,可以更好地过滤 Windows 10+ 中的隐藏窗口,并DwmGetWindowAttribute(hwnd, DWMWA_CLOAKED, &bIsCloaked, sizeof(BOOL));BOOL bIsCloaked = TRUE;您最终会得到真正的窗口对桌面感兴趣。

唯一的问题是,它们是按 z 顺序排序的。该列表是通过按 z 顺序对每个窗口带中的所有窗口进行排序而形成的,然后将结果连接到最终列表中。现在,什么是窗带?这是一项未记录的微软发明,他们让一些窗口位于更上面的位置HWND_TOPMOST(从安全角度来看是有道理的,但从根本不记录它的意义上来说,这是没有意义的)。您可以在这里阅读相关内容。基本上,桌面上有多个带区,每个带区是一组共享 z 顺序的窗口。然后,将条带堆叠在一起,生成条带的 z 顺序。选中“始终在顶部”的任务管理器在ZBID_SYSTEM_TOOLS上方的带区中运行ZBID_DESKTOP,这就是为什么它始终位于常规应用程序可以创建的任何窗口的顶部。

这是完全有道理的,但用户并不关心窗口带。它会看到桌面上的窗口,当按下 Alt-Tabing 时,它会看到一个按降序排列的列表,从最近使用的窗口到最后使用的窗口。按照这个顺序,尽管有乐队。例如,我的工作流程是 Firefox-Task Manager-cmd,我希望在 Alt-Tab 中看到 cmd-Task Manager-Firefox,尽管任务管理器始终位于顶部。

现在很明显,我们需要以某种方式对这个列表进行排序。出现的问题是,如何不考虑窗口带而按 z 顺序对窗口列表进行排序?我一生都无法在任何地方找到任何有用的东西,无论是在谷歌上,还是在乏善可陈的文档中。GetTopWindow并且GetNextWindow,传统功能比方说,始终将来自其他带的窗口放在第一个位置ZBID_DESKTOP,然后对其余窗口进行正确排序ZBID_DESKTOP。所有旧版 API 的行为就像其他频段中的窗口一样HWND_TOPMOST,这是有道理的。但我不希望这样:仅当我们一起考虑所有频带或所有窗口都在同一频带上时,z 顺序 = 激活顺序。我希望窗口按激活顺序排列,这与 z 顺序接近,但不相同,正如我在此处尝试解释的那样。

显然,Windows 以某种方式做到了这一点,因为我描述的行为发生在Alt-Tab、等中。显然有一个 API(不需要管理员,因为资源管理器以普通用户身份运行)允许您按这样的顺序对窗口进行排序,或者直接获取排序列表。不,我认为资源管理器不会在内部跟踪顺序,就像当您重新启动它并立即点击Win-TabSnap AssistAlt-Tab或类似的操作时,窗口会以正确的顺序显示,或者在我看来是这样。窗口已经创建,因此它必须从某个地方获取信息。

我还查看了twinui.pcshell.dll其中基本上是桌面 Windows shell,但到目前为止尚未找到任何相关内容。它们的名称中有一些方法zorder,但是当然会发生一百万个动态调度调用,当动态遍历调用堆栈时,您很容易迷失方向,并且在我的生活中,我无法找到它们在排序时使用的比较器(例如,AppViewSwitchItemZOrderSort::AppViewSwitchItemZOrderSort点击 时会被调用Win+Tab)。

有没有人在这个方向上有任何指示,我将不胜感激。我更喜欢 C,但此时任何东西都是可用的,我只想知道 API/COM 调用/做什么。

PS 如今 Windows 中的一切都是从头开始的逆向工程。微软专门制作了一套完全不同的 API 供他们使用,并给其他人留下了生锈的旧 API,以便他们的内置功能能够更好地执行。他们Alt+TabWin+Tab之前有现场窗口。您可能认为他们使用DWM 缩略图 API,但是,当然不是,他们使用了一些内部 API,允许他们操纵纹理或获取圆角纹理,因此它在 Windows 11 上看起来很合适,当然,他们也没有无需更新 DWM 缩略图 API 即可让应用程序能够请求带有圆角的纹理。因为何苦呢。他们甚至不再关心自己的软件。只需编译一些代码即可在 10 秒内打开一个窗口并关闭它。在这 10 秒内,打开Alt-TabWindows 11,然后坐在那里。当窗口关闭时,资源管理器崩溃,因为没有人期望窗口会自行关闭......就像,来吧微软......

谢谢。