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.
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 not in your list, then you've found the new window.
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
callback for more information.
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
callback are both quite silent on the issue. I offer as evidence the following:
A C++ Q&A article in MSDN magazine does 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 hWndParent parameter, 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.
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.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…