WPF Always On Top
Asked Answered
F

7

66

Is it possible to make a window stay always on top even when other application is running on Fullscreen? I'm using right now TopMost = true but when other application is running on fullscreen mine becomes invisible. It's WindowStyle = None window by the way.

Edit: And do not let other window minimalize ofcourse

Filibeg answered 18/11, 2013 at 14:39 Comment(6)
Which application is running fullscreen? There's a big difference between a maximized window (eg a web browser), and an application that really take over the display (like most videogames by default)Photoengrave
It depends how they implemented full screen feature (did they open a DC for display of they just put their own window on the top, maximized and without borders?). Of course you can always handle changes in your own window style to react in the proper way (for example restoring visible state).Anelace
You may find this and this interesting, they are for C++ but the comments are relevant.Quianaquibble
I mean about games. When I run let's say NBA2k13 which I tested before, my application is hidden underneath videogame.Filibeg
Don't worry. It's made to be almost invisible when playing. It's hidden on the edge of the screen and you can access the program by going with cursor on this edge. And you can lock it so it won't open, only 21x21px box for unlock. It's a music player btw.Filibeg
Topmost="True" is also very useful in debugging with visual studio.Topi
C
65

This won't work 100% of the time, but it will improve the situation somewhat. You can set Topmost = true in the handler for the Window.Deactivated event:

private void Window_Deactivated(object sender, EventArgs e)
{
    Window window = (Window)sender;
    window.Topmost = true;
}

The Deactivated event will be called whenever your application loses focus (often when another application requests to be Topmost) and so this will reset your application on top after this.

Colpotomy answered 18/11, 2013 at 15:3 Comment(6)
@Steve, the last focused of the two applications will win (be on top).Colpotomy
@Colpotomy based on what you said, the event will be called whenever it loses focus. So this is a potential infinite loop if more than one application tries to do this?Aorist
No, I see what you mean, but I've never experienced any issues like that.Colpotomy
@Aorist I know this is a few years too late, but here is an interesting article in regard to your question: blogs.msdn.microsoft.com/oldnewthing/20050607-00/?p=35413Zombie
I know I'm commenting on an old question/answer, but wanted to add "me too" in addition to others that this doesn't work for - but only on certain systems. Wondering if there is a system policy that can be set to nullify this as an explanation why my code works on some systems and not others.Dentate
This can also be set in XAML: <Window ... Topmost="True">Varix
S
17

Try this solution from MSDN, it should work for you. In the Window Activated Event add the following code:

this.Width   = System.Windows.SystemParameters.PrimaryScreenWidth;
this.Height  = System.Windows.SystemParameters.PrimaryScreenHeight;
this.Topmost = true;
this.Top  = 0;
this.Left = 0;

in DeActivated Event add the following code

this.Topmost = true;
this.Activate();

Original post from MSDN

Strapped answered 24/2, 2014 at 9:36 Comment(0)
B
16

None of the solutions above for me worked, so here is what I ended up doing. It worked perfectly for me.

Basically, to keep it on top you just set the lose focus event to make it go back to top.

XAML:

PreviewLostKeyboardFocus="Window_PreviewLostKeyboardFocus"
    

Code Behind:

private void Window_PreviewLostKeyboardFocus(object sender, KeyboardFocusChangedEventArgs e)
{
      var window = (Window)sender;
      window.Topmost = true;
}
Butcher answered 11/4, 2018 at 14:46 Comment(2)
Exactly what I was looking for. Simple solution, thanks!Gildus
doesnt work for full screen game in my case.Rarity
O
4

If you want your application to stay on top of EVERYTHING (including the start interface in Windows 8, previously known as "Metro"), then you can specify UiAccess="True" in your manifest file. This is typically used by accessibility applications such as onscreen keyboards.

From memory you need to do 3 things;

  1. Request UiAccess="True"
  2. Sign your application's exe file with a recognised certificate. I obtained a free code signing certificate from Certum as my project is Open Source.
  3. Install your application to a "Trusted Location", which in my case was the program files directory. There is no official definition of "Trusted Location" that I could find.
Ofilia answered 4/3, 2015 at 16:8 Comment(3)
Note the manifest file doesn't exist by default; you have to create it (as described here: https://mcmap.net/q/183289/-wpf-application-manifest-file )Enormous
More specific "Trusted Locations" and some more official documentation: learn.microsoft.com/en-us/windows/security/threat-protection/…Ruggles
Certum is not free anymore. You can use a self-signed certificate instead if it meets your needs, I explained the whole thing in this answer: https://mcmap.net/q/183290/-how-to-make-my-wpf-app-to-be-on-top-of-everything-even-the-windows-taskbar-like-windows-clock-appAutobiographical
P
3

So I ran into the same requirement recently. It seems the top rated answer as well as the second didn't properly work for me. I've found a solution that seems to work flawlessly and somewhat adheres to best practice using MVVM.

Using the below forces the window to the top and never lapses on change like the other solutions.

Step 1: I created a simple state manager class for my main client window. I used INotifyPropertyChanged to keep property in sync when using a direct binding to my window. (very important)

public class ClientStateManager : INotifyPropertyChanged
{
    #region Private Variables
    private bool isForceToTop;
    private bool isClientEnabled;
    #endregion

    #region Public Properties
    public bool IsForceToTop
    {
        get { return isForceToTop; }
        set
        {
            isForceToTop = value;
            NotifyPropertyChanged();
        }
    }
    public bool IsClientEnabled
    {
        get { return isClientEnabled; }
        set
        {
            isClientEnabled = value;
            NotifyPropertyChanged();
        }
    }       
    #endregion

    #region Private Methods
    private void NotifyPropertyChanged([CallerMemberName] String propertyName = "")
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
    #endregion

    #region Public Methods
    public void Lock() => this.IsClientEnabled = false;
    public void UnLock() => this.IsClientEnabled = true;
    public void SetTop() => this.IsForceToTop = true;
    public void UnSetTop() => this.IsForceToTop = false;
    #endregion

    #region Public Events
    public event PropertyChangedEventHandler PropertyChanged; 
    #endregion
}

Step 2.1: Added my state manager class to my ViewModel. (MVVM)

  internal class MainWindowViewModel : INotifyPropertyChanged
  {
    #region Constructor
    public MainWindowViewModel() 
    {
        ClientStateManager = new ClientStateManager();
    }
    #endregion

    #region Public Properties  
    public ClientStateManager ClientStateManager { get; private set; }
    #endregion
  }

Step 2.2: Then set your window data context to your view model.

  private MainWindowViewModel model;
  private MainWindow()
  {
        InitializeComponent();
        this.model = new MainWindowViewModel();
        this.DataContext = model;
  }   

Step 3: Add your data binding to your window.

  <Window x:Class="Intouch_Work.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:ojects="clr-namespace:Framework.Object;assembly=Framework"
    xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"     
    mc:Ignorable="d"
    Title="Intouch" Height="800" Width="1100"
    x:Name="mainWindow"
    Topmost="{Binding Path=ClientStateManager.IsForceToTop, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}">

So now you can manage your window state using the state manager object initialized within the View Model. You can call SetTop() from you state manager to push it forward, or UnSetTop() to stop it. Hope this helps anyone looking to do the same.

Phytology answered 10/4, 2018 at 8:40 Comment(0)
A
2

I needed something similar for an industrial quality control application, where non-admin operators should not be able to minimize or use anything else on the dedicated computer while the application is running, not even Windows+D to bring up the desktop. And I found out that the cleanest and simplest way to achieve that is through:

  1. Settings the correct Width, Height, WindowStyle, WindowState and Topmost properties.
  2. Handling some related events: StateChanged, Deactivated, LostFocuse, LostMouseCapture, LostKeyboardFocus and PreviewLostKeyboardFocus.
  3. Handling closing events with ALT+F4 or a custom button).

No need for P/Invoke, Here is the full code:

public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            Loaded += OnLoaded;
            Closing += OnClosing;
            StateChanged += OnStateChanged;
            Deactivated += (sender, args) => Activate();
            LostFocus += (sender, args) => Focus();
            LostMouseCapture += (sender, args) => Mouse.Capture(this);
            LostKeyboardFocus += (sender, args) => Keyboard.Focus(this);
            PreviewLostKeyboardFocus += (sender, args) => Keyboard.Focus(this);
        }

        private void OnLoaded(object sender, RoutedEventArgs e)
        {
            Width = SystemParameters.PrimaryScreenWidth;
            Height = SystemParameters.PrimaryScreenHeight;
            WindowStyle = WindowStyle.None;
            WindowState = WindowState.Maximized;
            Topmost = true;
            // Other stuff here
        }

        private void OnClosing(object sender, CancelEventArgs e)
        {
            // You might want to allow only some users to close the app
            if (MessageBox.Show("Are you an admin?", "Admin Check", MessageBoxButton.YesNo, MessageBoxImage.Warning) == MessageBoxResult.No)
               e.Cancel = true;
        }

        private void OnStateChanged(object sender, EventArgs e)
        {
            if (WindowState == WindowState.Minimized)
                WindowState = WindowState.Maximized;
        }
    }

You can also put some of this in XAML:

<Window x:Class="FullScreen.MainWindow"
        ...
        Title="MainWindow"
        WindowState="Maximized"
        WindowStyle="None" 
        Topmost="True">
    <Grid>
        
    </Grid>
</Window>

Accursed answered 15/2, 2021 at 9:40 Comment(0)
W
0

I had a main window that I wanted to keep on top of everything (if the user checked "always on top".
This worked for me. Hope this helps someone.

// If we want main to stay on top, we set the rest of the menus to Not be top 
if (mnuViewMainWindowAlwaysOnTopo.IsChecked)
{
    this.Topmost = true;
    
    foreach (var window in Application.Current.Windows)
        // Don't change for main window
        if (window.GetType().Name != this.GetType().Name)
            window.Topmost = false;
}
else this.Topmost = false;
Wastrel answered 16/9, 2014 at 16:38 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.