我正在尝试在所有窗口前弹出一个消息框,以便用户看到它。我有以下代码,但它似乎把消息框放在后面。
DialogResult dlgResult = MessageBox.Show(new Form() { TopMost = true }, "Do you want to continue?", "Continue?",
MessageBoxButtons.YesNo, MessageBoxIcon.Question);
if (dlgResult == DialogResult.Yes)
{
Console.WriteLine("YES");
}
else if (dlgResult == DialogResult.No)
{
Console.WriteLine("NO");
}
上面的代码是在一个线程中运行的,这是我的问题,我将如何解决这个问题?
由于
答案 0 :(得分:3)
是的,这是你的问题。你创建的表单将作为一个doornail死,你的线程不会消息循环。即使你可以使它工作,你仍然有一个重大问题。在用户的脸上按消息框无法可靠地工作。用户将敲打一个Word文档并按下空格键,就像弹出消息框一样。立即消失。用户注意到的只是一个轻微的闪光和文档中神秘遗漏的空间。
你真的应该使用NotifyIcon来弹出这样的通知。它的ShowBalloonTip方法是提供背景信息的标准方法。
您可以创建自己的Form类来显示自定义内容。重要的是它不会窃取焦点以避免上面提到的闪光问题。您需要创建专用线程以避免消息循环问题。像这样:
public static void ShowNotification(string msg) {
var t = new Thread(() => {
var frm = new frmNotify(msg);
frm.TopMost = true;
var rc = Screen.PrimaryScreen.WorkingArea;
frm.StartPosition = FormStartPosition.Manual;
frm.CreateControl();
frm.Location = new Point(rc.Right - frm.Width, rc.Bottom - frm.Height);
Application.Run(frm);
});
t.SetApartmentState(ApartmentState.STA);
t.IsBackground = true;
t.Start();
}
frmNotify是通知表单,如下所示:
public partial class frmNotify : Form {
public frmNotify(string msg) {
InitializeComponent();
frm.TopMost = true;
label1.Text = msg;
this.ShowWithoutActivation = true;
}
}
答案 1 :(得分:3)
在这种情况下,最好的选择可能是使用P / Invoke直接调用MessageBox函数。然后,您可以包含MB_TOPMOST
标志,这将强制它成为最顶层的消息框。 (这不会在托管API中公开。)
这将被声明为(来自pinvoke.net):
[DllImport("coredll.dll", SetLastError=true)]
public static extern int MessageBoxW(int hWnd, String text, String caption, uint type);
然后称为:
MessageBoxW(0, "Topmost Window", "Hello world", 0x00000040L /*MB_ICONINFORMATION*/ | 0x00040000L /*MB_TOPMOST*/);