我有一个时钟应用程序。我已经设置了窗口的TopMost属性。但是,随机地,一些其他窗口或Visual Studio会出现在时钟上面。
是否有其他方法使我的窗口(时钟应用程序)始终显示在所有其他应用程序的顶部。
我知道这个问题很旧了,但我不太明白为什么被接受的答案会得到赞成票...或者为什么它被接受了...它并没有真正回答问题,也没有提供解决方案,而且现在发布的答案如果这么短几乎总是会被社区 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 将始终保持在最上面,但对我而言它起作用,并且使用它仍然可以显着改善情况。
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.
}
当我在已有的窗口上设置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);
Topmost
设置为false,然后再将其设置为true。 - Riz