How can I get around the asymmetry of GetParent / EnumChildWindows?

I recently tested the GUI with Microsoft Spy ++ and noticed a strange structure; it looked like this (warning, ASCII art to come):

  |
  + 002004D6 "MyRootWindow1" FooClassName
  |  |
  |  + 001F052C "MyChildWindow" ClassOfChildWindow
  |
  \ 001D0A8C "MyRootWindow2" SomeOtherClassName

There are two root windows: 002004D6 and 001D0A8c , the first of which has one child window, 001F052C .

Now everything would be fine and to find it if it weren’t one: calling GetParent (or watching “Parent window” or “Owner window” in Spy ++) in the child window ( 001F052C ) gives 001D0A8c .

Read: "MyChildWindow" is a child of "MyRootWindow1", but "MyRootWindow1" is not a parent of "MyChildWindow". Instead, the parent of "MyChildWindow" is "MyRootWindow2", but to make it complete, enumerating children from "MyRootWindow2" does not give "MyChildWindow".

This is a completely static graphics application, so there are no race conditions.

Does anyone know how this can happen? Does anyone know how I can get around this? Until now, I used GetParent and EnumChildWindows to get the parent (or children) for this HWND, and I assumed that this relationship is symmetrical. Perhaps something else I should use?

EDIT: Here is the code for a small C ++ program that demonstrates the problem:

 const HINSTANCE thisModule = ::GetModuleHandle( NULL ); HWND oldParent = ::CreateWindow( TEXT("STATIC"), TEXT("Old parent"), WS_VISIBLE | WS_BORDER, 0, 0, 850, 500, NULL, NULL, thisModule, NULL ); HWND child = ::CreateWindow( TEXT("STATIC"), TEXT("This is a sample dialog"), WS_OVERLAPPED | WS_POPUP | WS_VISIBLE | WS_BORDER, 100, 100, 300, 300, oldParent, NULL, thisModule, NULL ); HWND newParent = ::CreateWindow( TEXT("STATIC"), TEXT("Fake main window"), WS_VISIBLE | WS_BORDER, 0, 0, 850, 500, NULL, NULL, thisModule, NULL ); ::SetParent( child, newParent ); 

Note that the child object has WS_POPUP and WS_OVERLAPPED , but not WS_CHILD .

+4
source share
2 answers

The documentation for GetParent explains: "Note that despite its name, this function can return the owner window instead of the parent window."

Since you are not creating a child window, I assume you are in this case.

You should be able to call GetAncestor by passing GA_PARENT as indicated in the documentation: "Retrieves the parent window. This does not include the owner, as with the GetParent function."

See Win32 Window. Owner and Parent Window.

+2
source

Well, that, of course, doesn't make much sense. It smells like a child window re-educating itself. This is a common technique in .NET Windows Forms, it has a “parking window” where child controls can find a temporary home when their container window needs to be recreated because the window style has changed. This is not a very noticeable effect, it is also temporary.

Another remote feature is SetParent (). This has appcompat behavior to support older Windows 3.x programs. This is explained pretty well in the SDK docs for it, in a nutshell the window can be the parent, but not set the WS_CHILD style flag. Adobe Acrobat Reader is a classic example of a program that does this. What effect that will have for EnumChildWindows is not clear to me.

And last but not least, don’t forget that Spy ++ provides a static view of windows. To track changes, it is important to press F5 to refresh the list of windows.

Not great explanations. Try to find out if it is really important which top-level window is active, I suspect that it is.

+3
source

Source: https://habr.com/ru/post/1301133/


All Articles