停止成为最顶层的窗口

时间:2015-07-11 18:57:38

标签: windows winapi window topmost

我的窗口应位于我无法控制的特定“目标”窗口之上。

当目标窗口激活后,我使用SetWindowPos调用HWND_TOPMOST将我的窗口置于其顶部,而目标仍然可以是活动窗口。

当目标窗口不再是前景窗口时,我希望我的窗口仍然位于目标窗口的顶部,但不再是最顶层的,因此其他窗口不会被它覆盖。

我有两个想法:

  • SetWindowPoshWndInsertAfter一起调用为刚刚激活的窗口。当刚刚激活的窗口位于最顶层时,这会失败,因为我的窗口不会失去最顶层的状态。另一个问题是:如果刚刚激活的窗口是桌面,则我的窗口位于目标窗口下方。

  • 使用SetWindowPos致电HWND_NOTOPMOST以失去最高级别的状态。但是,这会将我的窗口置于所有非最顶层窗口的顶部,因此它覆盖刚刚激活的窗口。要解决此问题,我必须将刚刚激活的窗口再次置于另一个SetWindowPosHWND_TOP的顶部。感觉这是错误的做法,可能会导致闪烁。

是否可以让窗口停在最顶端并将其放在当前前景窗口下面?

1 个答案:

答案 0 :(得分:3)

无论目标窗口是否为最顶层,唯一的自动方法是使窗口永久地位于另一个窗口之上是所有者/拥有关系。您可以尝试使用SetParent创建此关系,但请注意Raymond Chen does say it's not recommended

假设您正在以某种方式跟踪窗口激活,我认为您的SetWindowPos想法(第一个)就是这样做的方式,并进行了以下修改:

  • 当目标窗口处于活动状态时,将窗口设置为HWND_TOPMOST
  • 当目标失去激活时,请在z序中将目标窗口的前一个窗口后面的窗口插入(即有效地仍在目标窗口的顶部,但不是最顶层)

像这样的伪代码:

if (foregroundwindow == targetwindow)
   SetWindowPos(my_window, HWND_TOPMOST, ...);
else
{
    HWND hwndPred = GetWindow(targetwindow, GW_HWNDPREV);
    if (!hwndPred)
    {
        // no predecessor so my_window will still be on top, just not top-most any more
        if (GetWindowLong(targetwindow, GWL_EXSTYLE) & WS_EX_TOPMOST)
            hwndPred = HWND_NOTOPMOST;
    }
    SetWindowPos(my_window, hwndPred, ...);
}