C#winform:在任何消息框显示之前,新表单不能是TopMost

时间:2015-04-13 14:34:50

标签: c# winforms exception-handling

最近我写了一些代码来显示winforms app的未处理异常。

我希望那些例外显示窗口是TopMost。

所以我向Application.ThreadException添加了一个事件处理程序。处理程序创建一个新线程,打开一个TopMost属性设置为true的新表单。

然后我意识到,即使他们的TopMost属性为true,新窗口也无法成为TopMost。 更重要的是,如果显示任何MessageBox,后续的新窗口将重新获得成为TopMost的能力!

已经有一篇文章讨论了这个问题:TopMost form in a thread?但是这些答案仍然不能让我的Windows TopMost。 此外,我想知道显示TopMostMessageBox有效的原因。

这是我的最小问题演示:

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);
        }
    }
}

输出:具有计数的窗口:1/2/3 不是最顶部,具有计数的窗口:4/5/6 最顶层。

1 个答案:

答案 0 :(得分:0)

我只是回答这个问题而不是试图告诉你这个错误。您需要创建一个新表单并粘贴此代码:

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

现在即使从另一个线程显示它也将是最顶层的。