控制台应用程序中所有窗口前面的消息框?
我试图在所有窗口前弹出一个消息框,以便用户看到它。 我有以下代码,但它似乎把消息框放在后面。
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"); }
以上代码是在一个线程中运行这是我的问题,我将如何解决这个问题?
谢谢
在这种情况下,最好的选择可能是使用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*/);
是的,这是你的问题。 你创建的表单将作为一个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; } }