Recently I'm writing some code to display unhandled exceptions of the winforms app.
I want those exception-display-windows to be TopMost.
So I add an event handler to Application.ThreadException. The handler creates a new thread, opens a new form with TopMost attribute set to true.
Then I realize, new windows can't be TopMost even if their TopMost attribute is true. What's more, if any MessageBox was shown, subsequent new windows regain the ability to be TopMost!
There already is a post discussing this problem: TopMost form in a thread? But that answers still can't make my windows TopMost. Besides, I want to know why TopMost is valid after a MessageBox is shown.
Here is my minimal issue demo:
using System;
using System.Threading;
using System.Windows.Forms;
namespace WindowsFormsApplication1
{
static class Program
{
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.ThreadException += (o, e) => handleException();
Application.Run(new Form1());
}
static void handleException()
{
// before messagebox
doDisplay(); //Count:1
doDisplay(); //Count:2
doDisplay(); //Count:3
// Delay a while for the display threads to run
Thread.Sleep(300);
// show messagebox
if (MessageBox.Show("It doesn't matter you choose YES or NO",
"Message", MessageBoxButtons.YesNo) == DialogResult.No)
; // empty statement, just show msgbox
// after messagebox
doDisplay(); //Count:4
doDisplay(); //Count:5
doDisplay(); //Count:6
}
static int count = 0;
static void doDisplay()
{
Thread t = new Thread(new ThreadStart(() =>
{
Form f = new Form();
f.TopMost = true;
f.Text = "Count: " + ++count;
f.ShowDialog();
}));
t.IsBackground = true;
t.Start();
}
}
public class Form1 : Form
{
public Form1()
{
Button b = new Button();
b.Text = "throw!";
b.Click += (o, e) => { throw new Exception(); };
this.Controls.Add(b);
}
}
}
Output: window with Count: 1/2/3 aren't topmost, window with Count: 4/5/6 are topmost.