TopMost is not TopMost always - WPF
Asked Answered
A

4

8

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.

Attendance answered 16/9, 2010 at 17:57 Comment(0)
I
-2

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.

Illustrational answered 16/9, 2010 at 18:2 Comment(3)
Yeah. What I'm seeking is, what ever the other window state may be, my clock app should be in the TopMost. Like the "SlinkRun" application.Attendance
There is no SuperDuperTopMost option. It would obviously be used by everybody, defeating the reason for having it.Toothpaste
@Hans thanks. But, possibly how some apps like SlickRun and other desktop clocks are displaying themselves in topmost of all possible windows? Is there anything other then "Window" could provide me that effect?Attendance
N
23

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.

Nonpayment answered 13/1, 2014 at 11:19 Comment(1)
This doesn't work for me. To make it work, the key is to set Topmost = false first and then again set Tompost = trueFlagrant
F
4

This should do the trick in most cases

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.
}
Flagrant answered 4/10, 2019 at 12:59 Comment(1)
The legacy code I have to support does the opposite: sets it to true, then immediately sets it to false. Wonder why?Jock
G
3

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);
Grilse answered 22/2, 2017 at 1:36 Comment(2)
Useful little snippet of code, it's a frustrating bug.Phenacaine
worked for me. problem is, when i now click on my window that is now on top of the full screen program. the fullscreen program is minimized. i think the whole thing is a hen-egg-problem. the full screen program wants to be in the foreground but we try to force some window on top of it.Carrew
I
-2

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.

Illustrational answered 16/9, 2010 at 18:2 Comment(3)
Yeah. What I'm seeking is, what ever the other window state may be, my clock app should be in the TopMost. Like the "SlinkRun" application.Attendance
There is no SuperDuperTopMost option. It would obviously be used by everybody, defeating the reason for having it.Toothpaste
@Hans thanks. But, possibly how some apps like SlickRun and other desktop clocks are displaying themselves in topmost of all possible windows? Is there anything other then "Window" could provide me that effect?Attendance

© 2022 - 2024 — McMap. All rights reserved.