【问题标题】:Stop being topmost window不再是最顶层的窗口
【发布时间】:2015-07-11 18:57:37
【问题描述】:

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

当目标窗口被激活时,我用HWND_TOPMOST 调用SetWindowPos 将我的窗口放在它上面,而目标仍然可以是活动窗口。

当目标窗口不再是前景窗口时,我希望我的窗口仍然在目标窗口的顶部,但不再是最上面的,所以其他窗口不会被它覆盖。

我有两个想法:

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

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

是否可以让一个窗口停止在最顶层并将其置于当前前景窗口下方?

【问题讨论】:

  • Topmost 表示在所有其他未标记为 Topmost 的窗口之上。因此,如果没有其他窗口被标记为最顶层,则您的窗口将位于最顶层。为什么不创建模态对话框?它将仅适用于您的应用程序。
  • @GaneshR。如前所述,我无法控制目标窗口。当我的窗口位于顶部时,目标窗口也应该处于活动状态。

标签: windows winapi window topmost


【解决方案1】:

无论目标窗口是否位于最顶层,使一个窗口永久位于另一个窗口之上的唯一自动方法是所有者/拥有关系。您可以尝试使用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, ...);
}

【讨论】:

  • 谢谢,这真的很好用。还涵盖了两个窗口突然转到 z 顺序顶部的情况。在我的方法中,我的窗口将介于这两者之间。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-04-09
  • 2013-02-05
  • 2011-07-13
  • 2010-12-04
相关资源
最近更新 更多