Why does TopMost=True not always work?

4.2k views Asked by At

I have a simple app which is small and is supposed to float on top of all my other windows. After a few hours, I'll notice it is no longer on top of all my other windows and I was wondering if anyone knew why this happens.

During this time I have opened new applications (mostly MS 2010 products), locked/unlocked my PC a few times, hit the Desktop shortcut, and moved the app around on the screen (sometimes between screens since I have two monitors).

I have not been able to duplicate the behavior on demand, however it happens at least once a day. When it stops staying on top, it hides itself when I hit the desktop shortcut, so I think somehow the TopMost property is getting set to false.

<Window AllowsTransparency="True" 
        WindowStyle="None"
        Topmost="True"
        SizeToContent="WidthAndHeight"
        MouseDown="Window_MouseDown"
        ShowInTaskbar="False"
        Background="Transparent" 
        SnapsToDevicePixels="True">

The app is really simple... it just works like a virtual chess clock and lets me track time spent handling help desk calls vs actual development. The MouseDown event simply triggers the drag/drop behavior of the application since WindowStyle is set to None.

I am running WindowsXP and the app was built in .Net 4.0.

3

There are 3 answers

3
Tom On

Perhaps you could capture the Deactivated event, and force the Window back ontop again?

Just a guess really, but it'd be worth investigating if setting Topmost = False then Topmost = True at the right time fixes it.

0
jansen208 On

Alternative solution

in your WPF MainWindow

namespace YourNameSpace
{  
     public partial class MainWindow : Window
     {
    public MainWindow()
    {
        InitializeComponent();
    }

    private delegate void MessageBoxDelegate(DelegatePara para);

    public void ShowAwMessageBox(DelegatePara para)
    {            
        this.Dispatcher.BeginInvoke(new MessageBoxDelegate(ShowMessageBox), para);
    }

    private void ShowMessageBox(DelegatePara para)
    {
        this.Topmost = true;
        int typ = para.count;
        string msg = para.Msg;
        switch (typ)
        {
            case 0:
                MessageBox.Show(this, msg, "Auswertung", MessageBoxButton.OK, MessageBoxImage.Information);
                break;
            case 1:
                MessageBox.Show(this, msg, "Auswertung", MessageBoxButton.OK, MessageBoxImage.Error);
                break;
            case 2:
                MessageBox.Show(this, msg, "Auswertung", MessageBoxButton.OK, MessageBoxImage.Question);
                break;
            default:
                MessageBox.Show(this, msg, "Auswertung", MessageBoxButton.OK, MessageBoxImage.Information);
                break;
        }
    }
}

 public class DelegatePara
 {
    public int count {get;set; }
    public string Msg {get;set; }
 }
}

Then you call it with MainWind handle from anywhere you want, even in a thread

this.MyWind.ShowRlvAwMessageBox(new DelegatePara() { count = 0, Msg = "Hallo World!" });
3
BVernon On

This question is pretty old but I haven't found any real solutions yet so here's my idea for anyone else that runs across the issue:

Try Tom's advice, but instead of just checking to see if TopMost becomes use ShowWindowAsync to force it to show again.

Only thing that might be an issue about that that is that it can move the focus away from the active application, but I know there's a way to make it a "focus-less" form if that's an option for you.

About to try this for myself, so I will update this answer if it works with details.