windows EnumWindows 返回句柄的顺序是否有意义?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/295996/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Is the order in which handles are returned by EnumWindows meaningful?
提问by Oliver Giesen
From a couple of preliminary tests it seems that EnumWindows
always returns windows in reverse instantiation order, i.e. most recently instantiated window first. Is that a valid observation? If so, is it true across all versions of Windows? And is this a reliable assumption, i.e. is that behaviour documented somewhere?
从几个初步测试似乎EnumWindows
总是以相反的实例化顺序返回窗口,即最近实例化的窗口首先。这是一个有效的观察吗?如果是这样,是否适用于所有版本的 Windows?这是一个可靠的假设,即该行为是否记录在某处?
Context: I'm dealing with a situation where I am triggering a third-party application to open several non-modal windows and I need to send some window messages to those windows once they're open, yet I have no sure-fire way of identifying them as neither their window classes nor their captions will differ and I also do not know their expected coordinates. However, if I could rely on the above behaviour of EnumWindows
I could simply use the first handle returned by EnumWindows
whose class and caption match my expectation. That still leaves some hypothetical loop holes but I think it will be good enough. Alternative suggestions welcome nevertheless.
上下文:我正在处理一种情况,我正在触发第三方应用程序打开几个非模态窗口,一旦它们打开,我需要向这些窗口发送一些窗口消息,但我没有万无一失的方法将它们识别为它们的窗口类和标题都不会不同,而且我也不知道它们的预期坐标。但是,如果我可以依赖上述行为,EnumWindows
我可以简单地使用EnumWindows
其类和标题符合我期望的返回的第一个句柄。这仍然会留下一些假设的漏洞,但我认为这已经足够了。尽管如此,欢迎提供其他建议。
回答by P Daddy
It returns them in Z order. First the top-most window with WS_EX_TOPMOST
set, until the bottom-most window with WS_EX_TOPMOST set
, then the top-most window without WS_EX_TOPMOST
, though to the bottom-most window without WS_EX_TOPMOST
. Note that visibility is not a determining factor, so an invisible window that's higher in the Z-order than a visible window will still appear before it.
它以 Z 顺序返回它们。首先是最上面的窗口WS_EX_TOPMOST
设置,直到最下面的窗口有WS_EX_TOPMOST set
,然后最上面的窗口没有WS_EX_TOPMOST
,尽管到最底部的窗口没有WS_EX_TOPMOST
。请注意,可见性不是决定因素,因此在 Z 顺序中比可见窗口高的不可见窗口仍会出现在它之前。
EDIT:
编辑:
It's highly unlikely that you could use this as you want, just taking the first return from EnumWindows
. Not only is your new window unlikely to be the first return, but you'd have a race condition where other windows could be opened in the meantime. You could, however, keep a list of all known windows for the application, and when you need to find a newly opened window, call EnumWindows
and compare the window handles to those in your list. When you find one that has the correct class and caption (you might even check that it belongs to the right process with GetWindowThreadProcessID
) that is notin your list, then you've found the new window.
您不太可能随心所欲地使用它,只需从EnumWindows
. 不仅您的新窗口不太可能是第一次返回,而且您会遇到竞争条件,在此期间可以打开其他窗口。但是,您可以保留应用程序的所有已知窗口的列表,并且当您需要查找新打开的窗口时,调用EnumWindows
窗口句柄并将其与列表中的窗口句柄进行比较。当您找到一个具有正确类和标题(您甚至可以使用 来检查它是否属于正确的进程GetWindowThreadProcessID
)但不在您的列表中时,您就找到了新窗口。
For your purposes, though, you may be even better served by installing a CBT hook and watching for the HCBT_CREATEWND notification. See MSDN help on SetWindowsHookEx()
and the CBTProc
callbackfor more information.
但是,出于您的目的,您可能会通过安装 CBT 钩子并观察 HCBT_CREATEWND 通知得到更好的服务。请参阅MSDN上的帮助SetWindowsHookEx()
,并在CBTProc
回调以获取更多信息。
Level of certainty about enumeration order:
关于枚举顺序的确定性级别:
A number of comments and other answers to this question have mentioned a lack of precise documentation in MSDN about the order in which EnumWindows
returns window handles. And indeed, the pages on EnumWindows
and the EnumWindowsProc
callbackare both quite silent on the issue. I offer as evidence the following:
这个问题的许多评论和其他答案都提到 MSDN 中缺乏关于EnumWindows
返回窗口句柄顺序的精确文档。事实上,在页面上EnumWindows
,并在EnumWindowsProc
回调都对这个问题相当沉默。我提供以下证据作为证据:
A C++ Q&A article in MSDN magazinedoes state specifically:
EnumWindows enumerates the windows in top-down Z-order
The page on
EnumChildWindows
alludes to the order in the remarks section:A child window that is moved or repositioned in the Z order during the enumeration process will be properly enumerated.
This implies that the order is Z-order dependent. And since, in the description of the hWndParentparameter, it says this:
If this parameter is NULL, this function is equivalent to EnumWindows.
one can assume that the same logic and ordering applies to
EnumWindows
.- This is the observable behavior of this function, which makes it a breaking change to alter it. In general, Microsoft has been very good about not making breaking changes to observable behavior. That's not a guarantee, but it's a pretty safe bet. You're more likely to find that in the next version the function you're using has been deprecated—and replaced with yet another "Ex" version—than to find that its observable behavior has changed.
甲C ++ Q&在MSDN杂志的一篇文章确实状态具体为:
EnumWindows 以自上而下的 Z 顺序枚举窗口
页面上
EnumChildWindows
提到了备注部分的顺序:在枚举过程中按 Z 顺序移动或重新定位的子窗口将被正确枚举。
这意味着顺序是 Z 顺序相关的。因为,在hWndParent参数的描述中,它是这样说的:
如果此参数为 NULL,则此函数等效于 EnumWindows。
人们可以假设相同的逻辑和顺序适用于
EnumWindows
.- 这是这个函数的可观察行为,这使得改变它成为一个突破性的变化。总的来说,Microsoft 在不对可观察行为进行重大更改方面做得非常好。这不是一个保证,但这是一个非常安全的赌注。您更有可能发现在下一个版本中您使用的函数已被弃用——并替换为另一个“Ex”版本——而不是发现它的可观察行为发生了变化。
Of course, this is all very academic at this point, since EnumWindows
is probably not the best solution for the OP's problem—at the very least EnumThreadWindows
would probably be a better fit—but I thought it was worth mentioning for other people who might come across this post.
当然,这在这一点上非常学术,因为EnumWindows
可能不是 OP 问题的最佳解决方案——至少EnumThreadWindows
可能更合适——但我认为值得一提的是其他可能遇到这个问题的人邮政。
回答by kero
Previous answers need considerable refinement. Enum-order = Z-order only if GetSystemMetrics(SM_IMMENABLED)=0, i.e. Input Method Manager/Input Method Editor features are disabled. Because all windows class "IME" (the title "Default IME") and "MSCTFIME UI" are enumerated after the window "Progman" ("Program Manager"), - i.e. not in Z-order.
以前的答案需要大量改进。Enum-order = Z-order 仅当 GetSystemMetrics(SM_IMMENABLED)=0 时,即输入法管理器/输入法编辑器功能被禁用。因为所有窗口类“IME”(标题“默认 IME”)和“MSCTFIME UI”都在窗口“Progman”(“程序管理器”)之后枚举,即不按 Z 顺序。
回答by Skizz
The order is not specified in the API (MSDN link) so it's not guaranteed to be anything in particular - if there was a guarantee it would be explicitly specified in the API. What happens, for example, if a window is created halfway through the enumeration - does it get included in the enumeration? This allows the window manager the freedom to change its implementation should it become more efficient to do so.
API(MSDN 链接)中未指定该顺序,因此不能保证它是任何特定的东西 - 如果有保证,它将在 API 中明确指定。例如,如果在枚举的中途创建了一个窗口 - 它是否包含在枚举中?这允许窗口管理器在它变得更有效率时自由地改变它的实现。
However, there is a unique value that can be used to differentiate between windows - the window handle itself. In your EnumWindowProc
method, save the window handle for each matching window - you need it anyway to send messages to the window.
但是,有一个唯一值可用于区分窗口 - 窗口句柄本身。在您的EnumWindowProc
方法中,保存每个匹配窗口的窗口句柄 - 无论如何您都需要它来向窗口发送消息。
回答by Jo?o Augusto
If you control both processes you can send from the first one a SendMessage with "HWND_BROADCAST" as first parameter.
如果您控制这两个进程,则可以从第一个进程发送带有“HWND_BROADCAST”作为第一个参数的 SendMessage。
Then the other program when receive the msg, can do a SendMessage to his child windows.
然后其他程序在收到 msg 时,可以向他的子窗口发送一个 SendMessage。
回答by liggett78
If the documentation does not say anything about the order of enumeration, I would STRONGLY suggest you stay away from any assumptions. A couple of posts on Raymond Chen's blog (blogs.msdn.com/oldnewthing) would reveal you how many apps are there that rely on all this undocumented stuff/observation, and something goes terribly wrong when a new version of Windows comes out (unless MS developers introduce yet another shim for yet another app that behaves badly).
如果文档没有说明枚举顺序,我强烈建议您远离任何假设。Raymond Chen 的博客 (blogs.msdn.com/oldnewthing) 上的几篇文章会告诉您有多少应用程序依赖于所有这些未记录的内容/观察,并且当新版本的 Windows 出现时会出现严重的错误(除非MS 开发人员为另一个表现不佳的应用程序引入了另一个垫片)。
As for your purpose, there are several functions, like GetWindowThreadProcessID, GetParent, EnumThreadWindows and EnumWindows that could help you achieve the task.
至于您的目的,有几个函数可以帮助您完成任务,例如 GetWindowThreadProcessID、GetParent、EnumThreadWindows 和 EnumWindows。