在Windows中,是否可以设置窗口A,使其始终位于窗口B的顶部,但允许其他窗口正常工作,并在活动时显示在两者之上。
换句话说,我想在两个窗口之间建立父子关系。这可以在不使窗口A成为窗口B,MDI风格的子窗口的情况下完成吗?窗口B不是我的(Internet Explorer),并且当我尝试使用SetParent
实现此操作时,将我的对话框A的图形搞定。
我以为我是用MSDN forum post的这个想法来解决它的,但是唉,窗户A仍然总是在一切之上,而不仅仅是窗口B.
// Place window A on top
SetWindowPos(hWndWindow, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE);
// Place window B underneath it
SetWindowPos(hWndParent, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOSIZE|SWP_NOMOVE);
有可能吗?
答案 0 :(得分:13)
不会创建所有权关系吗?
SetWindowLong(hwndChild, GWL_HWNDPARENT, hwndOwner)
窗口可以在不同的进程中,您可以从任何进程调用它。这将确保子窗口始终位于所有者窗口之上。这与实际创建父/子关系的SetParent不同。 Read through this article(从1993年开始,但仍然大部分是正确的)看到所有权和养育子女之间的区别。
答案 1 :(得分:4)
当您的窗口的Z顺序(或大小或位置)发生变化时,它应该会收到WM_WINDOWPOSCHANGING消息。如果您处理该消息,您有机会修改窗口移动到的最终Z顺序(或大小或位置)。
为了说明,在hWndA的窗口过程中:
case WM_WINDOWPOSCHANGING:
DefWindowProc(hWnd, msg, wParam, lParam);
WINDOWPOS *p = (WINDOWPOS*)lParam;
p->hwndInsertAfter = hWndB;
p->flags &= ~SWP_NOZORDER;
return 0;
每当hWndA的位置改变时,应该在h-order之后插入hWndA。
答案 2 :(得分:2)
在Vista之前,一种方法是使用SetWindowsHookEx
,并挂钩WH_CBT
或WH_CALLWNDPROC
挂钩,然后在检测到Z顺序更改时采取适当的操作。然而,这不适用于Vista(据我可以通过谷歌搜索来判断)。
我能想到的唯一其他解决方案是设置计时器每隔几秒钟启动一次,然后当你收到WM_TIMER
时,使用GetNextWindow
查询系统以找出哪个窗口落后于你。如果它不是IE,那么调用SetWindowPos
将你的窗口放在IE上面(我假设你有一个HWND
用于你关心的IE窗口 - 记住可以有多个IE窗口。)
如果人们试图将您的窗口置于前面,这将导致问题 - 它将回到IE正上方。在这种情况下,在您的代码中,您可以处理WM_ACTIVATE
并尝试更改IE窗口的Z顺序,使其位于窗口下方(调用SetWindowPos
移动IE的窗口,使其位于当前窗口的上方在你的窗口下面)。出于安全原因,Windows可能会试图阻止您弄乱另一个进程的窗口,因此这个解决方案可能会遇到问题。另一方面,SetWindowPos
的MSDN文档没有明确提及您无法操纵另一个进程的窗口。但是可能存在模糊的限制。
即使使用此计时器黑客攻击,您也会在应用程序中有效地进行忙碌等待循环(使用频繁的WM_TIMER消息),这通常是糟糕要做的事情,特别是对于笔记本电脑等的电池寿命(因为你可以防止CPU进入睡眠状态,等等)。
我会说没有好办法做到这一点,任何你可能会工作的东西都会变脆并导致问题。 我强烈建议您不要尝试这样做。是否可以将您的程序转换为IE的某种插件或工具栏?
NB 要特别注意SetWindowsHookEx
如果沿着这条路走下去,会在系统范围内造成性能损失。
答案 3 :(得分:1)
莫里斯的答案是最好的,但却缺少重要的一步。当您在窗口上调用show作为叠加层时,需要调用具有该参数的show方法。您需要定义一个实现IWin32Window接口的类,并创建一个新的实例。接口唯一关心的是Handle,所以只需将其设置为IE窗口的句柄,它应该可以正常工作
答案 4 :(得分:1)
如果亲子关系是由您自己使用SetWindowPos()函数创建的,那么您的愿望就可以实现。
答案 5 :(得分:0)
您可以访问Windows的Z顺序吗?
我无法回想起Windows的默认z顺序,但我认为它是1.您可以将IE设置为-1,将应用程序设置为0.
答案 6 :(得分:0)
试试这个:
// Place window A on top of window B
SetWindowPos(hWndA, hWndB, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE);
第二个窗口句柄参数指定Z顺序中的下一个窗口。
请注意,这实际上并不会改变窗口的父子关系 - 但您可以模拟它。