TopMost并非总是最顶层 - WPF

8

我有一个时钟应用程序。我已经设置了窗口的TopMost属性。但是,随机地,一些其他窗口或Visual Studio会出现在时钟上面。

是否有其他方法使我的窗口(时钟应用程序)始终显示在所有其他应用程序的顶部。

4个回答

23

我知道这个问题很旧了,但我不太明白为什么被接受的答案会得到赞成票...或者为什么它被接受了...它并没有真正回答问题,也没有提供解决方案,而且现在发布的答案如果这么短几乎总是会被社区 down 票或删除。唉,不管怎样,我想这是发表在不同的时代。

不管怎样,虽然它很老了,但是我有一个可能的解决方案,适用于未来遇到这个帖子的任何人。您可以简单地处理Window.Deactivated事件和/或Application.Deactivated事件Window.Deactivated事件 在窗口变为后台窗口时发生Application.Deactivated事件 在应用程序停止成为前景应用程序时发生

思路是每当您的应用程序或Window失去焦点时,将相关的TopMost属性设置为true

private void Window_Deactivated(object sender, EventArgs e)
{
    // The Window was deactivated 
    this.TopMost = true;
}

值得注意的是,其他开发人员也可以使用这种技术,因此这并不能保证您的 Window 将始终保持在最上面,但对我而言它起作用,并且使用它仍然可以显着改善情况。


5
这对我没用。要使其起作用,关键是先将Topmost设置为false,然后再将其设置为true。 - Riz

4
这在大多数情况下都能解决问题。
private void Window_Deactivated(object sender, EventArgs e)
{
    // The Window was deactivated 
    Topmost = false; // set topmost false first
    Topmost = true; // then set topmost true again.
}

我需要支持的遗留代码却相反:将其设置为true,然后立即将其设置为false。不知道为什么? - Sabuncu

3

当我在已有的窗口上设置Window.Topmost = true时,有时会遇到这个问题,有时候可以工作,有时候不行。以下是我的解决方法,如果WS_EX_TOPMOST样式在运行时丢失,你可能可以将其与其他人提到的Window_Deactivated方法结合使用。

App.Current.MainWindow.Topmost = true;

// Get this window's handle
IntPtr hwnd = new WindowInteropHelper(App.Current.MainWindow).Handle;

// Intentionally do not await the result
App.Current.Dispatcher.BeginInvoke(new Action(async () => await RetrySetTopMost(hwnd)));

额外的代码:

private const int RetrySetTopMostDelay = 200;
private const int RetrySetTopMostMax = 20;

// The code below will retry several times before giving up. This always worked with one retry in my tests.
private static async Task RetrySetTopMost(IntPtr hwnd)
{
    for (int i = 0; i < RetrySetTopMostMax; i++)
    { 
        await Task.Delay(RetrySetTopMostDelay);
        int winStyle = GetWindowLong(hwnd, GWL_EXSTYLE);

        if ((winStyle & WS_EX_TOPMOST) != 0)
        {
            break;
        }

        App.Current.MainWindow.Topmost = false;
        App.Current.MainWindow.Topmost = true;
    }
}

internal const int GWL_EXSTYLE = -20;
internal const int WS_EX_TOPMOST = 0x00000008;

[DllImport("user32.dll")]
internal static extern int GetWindowLong(IntPtr hwnd, int index);

有用的小代码片段,这是一个令人沮丧的错误。 - Joe
对我来说有效。问题是,当我现在点击我的窗口时,它现在在全屏程序的顶部。全屏程序被最小化了。我认为整个问题是一个鸡生蛋或蛋生鸡的问题。全屏程序想要在前景中,但我们试图强制将一些窗口置于其上方。 - Welcor

-2
你确定它是一个随机窗口吗?如果另一个窗口也是最顶层的窗口,它有可能覆盖在你的窗口上方。

是的。我想要的是,无论其他窗口状态如何,我的时钟应用程序都应该在最顶层显示。就像“SlinkRun”应用程序一样。 - Prince Ashitaka
11
没有“超级顶级选项”。显然它会被每个人都使用,这就违背了拥有它的原因。 - Hans Passant
2
@Hans 谢谢。但是,可能有一些应用程序(如SlickRun和其他桌面时钟)是如何显示在所有可能窗口的最顶部的?除了“Window”之外,还有什么可以提供我这种效果吗? - Prince Ashitaka

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接