通过几个初步测试,似乎 EnumWindows 始终以反向实例化顺序返回窗口,即最近实例化的窗口。这是一个有效的观察吗?如果是这样,在所有版本的Windows中都是如此吗?这是一个可靠的假设,即某种行为记录在某个地方吗?


上下文:我正在处理我触发第三方应用程序打开几个非模态窗口的情况,我需要在打开后向这些窗口发送一些窗口消息,但是我没有确定的方法来识别它们,因为它们的窗口类和它们的标题都不会有所不同,我也不知道它们的预期坐标。但是,如果我可以依赖<=>的上述行为,我可以简单地使用<=>返回的第一个句柄,其类和标题符合我的期望。这仍然留下一些假设的循环漏洞,但我认为这将是足够好的。不过欢迎其他建议。

有帮助吗?

解决方案

以Z顺序返回它们。首先是WS_EX_TOPMOST设置的最顶层窗口,直到带有WS_EX_TOPMOST set的最底层窗口,然后是没有EnumWindows的最顶层窗口,但是没有GetWindowThreadProcessID的最底层窗口。请注意,可见性不是一个决定因素,因此Z序中比可见窗口更高的不可见窗口仍然会出现在它之前。

修改

你不太可能按照自己的意愿使用它,只需从SetWindowsHookEx()获得第一次回报。您的新窗口不仅不是第一次返回,而且您还有一个竞争条件,在此期间可以打开其他窗口。但是,您可以为应用程序保留所有已知窗口的列表,当您需要查找新打开的窗口时,请调用CBTProc并将窗口句柄与列表中的窗口句柄进行比较。当你找到一个具有正确的类和标题(你甚至可以检查它属于EnumWindowsProc的正确进程)的列表中的不是时,你找到了新的窗口

但是,出于您的目的,您可以通过安装CBT挂钩并观察HCBT_CREATEWND通知来获得更好的服务。有关 EnumChildWindows EnumThreadWindows回调以获取更多信息。

关于枚举顺序的确定程度

此问题的一些注释和其他答案提到MSDN中缺少关于<=>返回窗口句柄的顺序的精确文档。事实上, <=> 上的页面和 <=>回调都非常沉默问题。我提供以下证据:

  1. C ++ Q <!> amp; MSDN杂志上的一篇文章具体说明:

      

    EnumWindows以自上而下的Z顺序列举窗口

  2. <=> 在备注部分提及订单:

      

    将在枚举过程中以Z顺序移动或重新定位的子窗口将被正确枚举。

    这意味着订单依赖于Z顺序。因为,在 hWndParent 参数的描述中,它说:

      

    如果此参数为NULL,则此函数等效于EnumWindows。

    可以假设相同的逻辑和顺序适用于<=>。

  3. 这是此函数的可观察行为,这使得它可以改变它。总的来说,微软一直非常善于不对可观察行为进行重大改变。这不是保证,但这是一个非常安全的赌注。您更有可能发现在下一个版本中,您正在使用的函数已被弃用<!>#8212;并被另一个<!>引用; Ex <!>版本<!>#8212;而不是发现它的可观察行为已经改变。
  4. 当然,这一点都是非常学术性的,因为<=>可能不是OP问题的最佳解决方案<!>#8212;至少<=>可能更适合<! >#8212;但我认为值得一提的是其他可能会遇到此帖的人。

其他提示

以前的答案需要大量改进。 仅当GetSystemMetrics(SM_IMMENABLED)= 0时,Enum-order = Z-order,即禁用输入法管理器/输入法编辑器功能。 因为所有windows类<!>“IME <!>”; (标题<!>“;默认IME <!>”;)和<!>“; MSCTFIME UI <!>”;在窗口<!>之后枚举“Progman <!>”; (<!>“程序管理器<!>”;), - 即不是Z顺序。

API中未指定订单( MSDN链接 )所以它不能保证特别是 - 如果有保证它将在API中明确指定。例如,如果在枚举的中途创建了一个窗口会发生什么 - 它是否包含在枚举中?这使得窗口管理器可以自由地更改其实现,如果它变得更有效的话。

但是,有一个独特的值可用于区分窗口 - 窗口句柄本身。在EnumWindowProc方法中,保存每个匹配窗口的窗口句柄 - 无论如何都需要它来向窗口发送消息。

如果您控制这两个进程,您可以从第一个进程发送带有<!>“HWND_BROADCAST <!>”的SendMessage;作为第一个参数。

然后另一个程序在收到msg时,可以对他的子窗口执行SendMessage。

如果文档没有说明有关枚举的顺序,我强烈建议您远离任何假设。 Raymond Chen的博客(blogs.msdn.com/oldnewthing)上的几篇文章将向您展示有多少应用程序依赖于所有这些未记录的内容/观察,并且当新版本的Windows出现时出现了严重错误(除非MS开发人员为另一个表现不佳的应用推出了另一个垫片。

至于你的目的,有几个函数,比如GetWindowThreadProcessID,GetParent,EnumThreadWindows和EnumWindows可以帮助你完成任务。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top