I have a clock application. I have set the Window's TopMost property. But, randomly, some other window or visual studio comes above clock.
Is there any other way to make my window (clock app) to display always on top of all other applications.
I have a clock application. I have set the Window's TopMost property. But, randomly, some other window or visual studio comes above clock.
Is there any other way to make my window (clock app) to display always on top of all other applications.
Are you sure it's a random window? If another window is also a topmost window, it is possible for it to come above your window.
I know that this question is old, but I don't quite understand why the accepted answer has received up votes... or why it was accepted... it doesn't really answer the question, or provide a solution and answers posted these days that are that short are almost always down voted and/or deleted by the community. Ah well, I guess it was posted in different times.
Either way, as old as it is, I have a possible solution for anyone who may come across this post in the future. You can simply handle the Window.Deactivated
Event and/or the Application.Deactivated
Event. The Window.Deactivated
Event occurs when a window becomes a background window and the Application.Deactivated
Event occurs when an application stops being the foreground application.
The idea is to set the relevant TopMost
property to true
each time your application or Window
loses focus:
private void Window_Deactivated(object sender, EventArgs e)
{
// The Window was deactivated
this.TopMost = true;
}
It's worth noting that other developers can also use this technique, so this doesn't guarantee that your Window
will always remain on top, but it works for me and the situation is still certainly improved by using it.
I also had this problem when setting Window.Topmost = true on already existing window sometimes worked, sometimes not. Below is my workaround, you can probably combine it with Window_Deactivated approach mentioned by other people, if WS_EX_TOPMOST style is lost at runtime.
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)));
Extra code:
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);