C# winform:在显示任何消息框之前,新表单不能成为 TopMost
C# winform: new form can't be TopMost before any messagebox shows
最近我正在编写一些代码来显示 winforms 应用程序的未处理异常。
我希望那些异常显示-windows 成为 TopMost。
所以我向 Application.ThreadException
添加了一个事件处理程序。处理程序创建一个新线程,打开一个 TopMost
属性设置为 true
.
的新表单
然后我意识到,新的 windows 不能成为 TopMost,即使它们的 TopMost
属性是 true
。 更重要的是,如果有MessageBox
出现,后续新的windows重新获得TopMost的能力!
已经有一个 post 讨论这个问题:TopMost form in a thread? 但是那个答案仍然不能使我的 windows 置顶。 此外,我想知道为什么TopMost
在显示MessageBox
后有效。
这是我的最小问题演示:
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);
}
}
}
输出:window 计数:1/2/3 不是 最顶层,window 计数:4/5/6 是最上面的。
我只会回答问题,而不是试图说服您改正这个错误。您需要创建一个新表单并粘贴此代码:
protected override CreateParams CreateParams {
get {
var cp = base.CreateParams;
cp.ExStyle |= 8; // Turn on WS_EX_TOPMOST
return cp;
}
}
现在即使从另一个线程显示它也会在最上面。
最近我正在编写一些代码来显示 winforms 应用程序的未处理异常。
我希望那些异常显示-windows 成为 TopMost。
所以我向 Application.ThreadException
添加了一个事件处理程序。处理程序创建一个新线程,打开一个 TopMost
属性设置为 true
.
然后我意识到,新的 windows 不能成为 TopMost,即使它们的 TopMost
属性是 true
。 更重要的是,如果有MessageBox
出现,后续新的windows重新获得TopMost的能力!
已经有一个 post 讨论这个问题:TopMost form in a thread? 但是那个答案仍然不能使我的 windows 置顶。 此外,我想知道为什么TopMost
在显示MessageBox
后有效。
这是我的最小问题演示:
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);
}
}
}
输出:window 计数:1/2/3 不是 最顶层,window 计数:4/5/6 是最上面的。
我只会回答问题,而不是试图说服您改正这个错误。您需要创建一个新表单并粘贴此代码:
protected override CreateParams CreateParams {
get {
var cp = base.CreateParams;
cp.ExStyle |= 8; // Turn on WS_EX_TOPMOST
return cp;
}
}
现在即使从另一个线程显示它也会在最上面。