-1

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.

Community
  • 1
  • 1
  • looks to be some threading issue just looking at first glance.. I would definitely recommend putting some break points in your code then stepping thru the code using the debugger.. I suspect that your issue is between this line `Thread t = new Thread(new ThreadStart(() => {` also you are trying to execut 3 more method calls after you `if(MessageBox.Show` why are you not wrapping that code inside of a code block..? – MethodMan Apr 13 '15 at 14:38
  • @MethodMan `if(MessageBox.Show` just shows a messagebox, the if-block is empty with only a `;`... I have no idea where is the issue of creating thread?.. – user2726215 Apr 13 '15 at 15:00
  • You should not be creating any windows in any other thread than the main UI thread. But that said, I am unable to reproduce the problem you describe using the code you show. When running the code standalone (i.e. not from the debugger, which steals focus when the exception is thrown), after clicking the button, I see three top-most windows and the message box. The top-most windows even remain above the message box, as well as other windows on my desktop. – Peter Duniho Apr 14 '15 at 19:54

1 Answers1

0

I'll just answer the question instead of trying to talk you out of this mistake. You need to create a new form and paste this code:

    protected override CreateParams CreateParams {
        get {
            var cp = base.CreateParams;
            cp.ExStyle |= 8;  // Turn on WS_EX_TOPMOST
            return cp;
        }
    }

Now it will be top-most even if displayed from another thread.

Hans Passant
  • 922,412
  • 146
  • 1,693
  • 2,536
  • Did you try his example code, _outside of the debugger_? When I run the OP's code, it works just as desired: all displayed windows are "top-most" (well, obviously only one of the top-most windows can really be the top-most window...but they are all on top of everything else, including windows from other processes). – Peter Duniho Apr 14 '15 at 19:52
  • Yes, I tested this code before I posted it. The OP tested it as well and found it solved his problem. I expected it to. – Hans Passant Apr 14 '15 at 20:23
  • No, I don't mean your code. I mean the OP's code. "_his_ example code". I cannot reproduce the problem he describes. Can you? (Regardless, it is my opinion you should have at least tried to talk him out of his poor design...but I'm more curious whether you were able to even verify his complaint in the first place). – Peter Duniho Apr 14 '15 at 22:31
  • In the good olde days SO users shared their knowledge and the questioner was as much involved as the answerer. Those days are over, the OP is just not interested in sharing what he knows that we don't know that would make this code useful. The fantastic number of upvotes on this very unobvious technical answer buys me an opportunity to not have to defend it, nor ingrain myself in the OP's core problem, not sure why you expect me to. If you want to know more about it then just click the Ask Question button. I'm sure it is going to be a better question than this one. – Hans Passant Apr 14 '15 at 23:12
  • _"not sure why you expect me to"_ -- I wouldn't say "expect" is the right word. Personally, I almost never bother answering a question if I myself cannot reproduce the described issue; it's too easy to accidentally provide a useless answer (i.e. one that either solved a non-existent-problem, or failed to solve the original problem). But I don't **expect** you or anyone else to necessarily subscribe to that philosophy. I was just _curious_ as to whether you were able to reproduce the issue. No expectations one way or the other. – Peter Duniho Apr 14 '15 at 23:28