我最近用微软的Spy ++检查了一个GUI,发现了一个奇怪的结构;它看起来像这样(警告,未来的ASCII艺术):
| + 002004D6 "MyRootWindow1" FooClassName | | | + 001F052C "MyChildWindow" ClassOfChildWindow | \ 001D0A8C "MyRootWindow2" SomeOtherClassName
有两个根窗口002004D6
和001D0A8c
,前一个窗口有一个子窗口001F052C
。
现在,这一切都很好,并且发现它是否不是一件事:在子窗口上调用GetParent(或在Spy ++中观察“父窗口”或“所有者窗口”字段)({ {1}})产生001F052C
。
阅读:“MyChildWindow”是“MyRootWindow1”的子节点,但“MyRootWindow1”不是“MyChildWindow”的父节点。相反,“MyChildWindow”的父级是“MyRootWindow2” - 但是,要完成此操作,枚举“MyRootWindow2”的子级不会产生“MyChildWindow”。
这是一个非常静态的GUI应用程序,因此这里没有任何竞争条件。
有人知道这会怎么样吗?有谁知道如何解决这个问题?直到 现在,我使用GetParent和EnumChildWindows来获取给定HWND的父(或子),我假设这种关系是对称的。可能还有其他我应该使用的东西吗?
编辑:以下是演示此问题的小型C ++程序的代码:
001D0A8C
请注意'child'对象如何设置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 );
和 WS_POPUP
,而不是WS_OVERLAPPED
。
答案 0 :(得分:3)
嗯,这当然没有多大意义。它闻起来像儿童窗口正在重新养育自己。这是.NET Windows Forms中的常用技术,它有一个“停放窗口”,当窗口样式发生变化时,子控件可以在需要重新创建容器窗口时找到临时主页。这不是一个非常明显的效果,它也是暂时的。
另一种远程可能性是SetParent()。它具有appcompat行为以支持旧的Windows 3.x程序。它的SDK文档很好地解释了它,简而言之,一个窗口可以是父级但不设置其WS_CHILD样式标志。 Adobe Acrobat Reader是执行此操作的程序的典型示例。对我来说,EnumChildWindows会产生什么影响。
最后但并非最不重要:不要忘记Spy ++提供了窗口的静态视图。按F5更新窗口列表对于跟踪更改非常重要。
不是很好的解释。试着找出哪个顶层窗口是活动的,我怀疑它是否有效。
答案 1 :(得分:3)
GetParent的文档说明: “请注意,尽管名称如此,但此函数可以返回所有者窗口而不是父窗口。”
由于你没有创建一个子窗口,我猜你遇到了这种情况。
你应该可以调用GetAncestor传递GA_PARENT,因为文档说: “检索父窗口。这不包括所有者,因为它与GetParent函数一样。”