为什么MessageBox不是TopMost ?
本文关键字:TopMost 不是 MessageBox 为什么 | 更新日期: 2023-09-27 18:09:57
我最近发现,默认情况下,消息框不是最顶部的形式默认显示时,我想知道是否有人知道任何情况下,当你不希望消息框被显示在其他窗口的顶部?
我发现这个问题,当我开始显示启动屏幕,而加载应用程序,它看起来像我的程序仍在运行,但有一个MessageBox
背后的启动屏幕,等待输入。启动画面显示在不同的线程上,而不是调用消息框的线程上,所以我想这就是为什么它没有出现在启动画面上方;但这仍然不能解释为什么默认情况下MessageBox没有MB_TOPMOST
标志?
编辑
为了更好地说明:最后,我不得不做一些类似的事情,最终使消息框,代码不完全正确,从内存中写入)
[DllImport("User32.dll")]
private int extern MessageBox(windowhandle, message, caption, flag);
public static void MessageBox(windowhandle, string message, string caption)
{
MessageBox(windowhandle, message,caption, MB_TOPMOST);
}
如果您可以获得对话框应该出现在其上的窗口的句柄或引用,则建议的解决方案可以工作。然而,这可能并不总是可能或容易实现:
- 窗口是一个闪屏,不应该与您的业务逻辑紧密耦合
- 窗口是由另一个类或库创建的,而不是当前的
- 窗口不受您的控制,即来自第三方(本地)库
在这种情况下,您可以使用来自User32.dll
的Win232 MessageBox
API,但也可以使用更简单的托管解决方案:
MessageBox.Show(new Form { TopMost = true }, "Hello, I'm on top!");
代码new Form { TopMost = true }
将创建一个具有MB_TOPMOST
属性的隐藏表单,该属性由消息框对话框窗口继承。因此,它将出现在所有其他窗口的顶部。使用new Form()
内联没有副作用,没有视觉外观,并且会通过垃圾收集器正常销毁。
注意:如果你还没有在一个表单中,不要忘记命名空间,这是System.Windows.Forms.MessageBox
,而不是System.Windows.MessageBox
!(谢谢,user1)。
在最上面显示MessageBox
//Should be MessageBox.Show() below
MessageBox.Show(this, "My top most message");
默认不为MB_TOPMOST
的原因
参考链接如果MB_TOPMOST将是默认的,那么
MessageBox
将显示在一个'系统模态'模式,它将恰好在该形式的顶部,副作用是'系统模态'模式将导致MessageBox
阻塞窗口,直到消息被驳回,通常它将是'应用程序模态'模式。
- MSDN论坛-如何将消息框显示为最上面的窗口
- SO - c# MessageBox To Front当应用程序最小化到托盘
显示MessageBox
时,提供其所有者作为第一个参数。例如,当从Form
实例调用调用时:
MessageBox.Show(this, "Message");
提供对拥有它的窗口的引用作为第一个参数。
消息框(和一般的模态表单)不出现在应用程序的所有窗口的顶部。它们只出现在所有者的顶部。如果你想让你的消息框(或其他模态表单)在闪屏的顶部,设置它们的所有者为闪屏表单实例。
我试着粘贴一个更完整的代码片段,它肯定是工作的
[CLSCompliant(false)]
[DllImport("user32.dll", EntryPoint = "MessageBox")]
public static extern int MessageBoxUser32(int hWnd, String text, String caption, uint type);
const uint MB_TOPMOST = 0x00040000;
const uint MB_OK = 0x00000000;
const uint MB_OKCANCEL = 0x00000001;
const uint MB_ABORTRETRYIGNORE = 0x00000002;
const uint MB_YESNOCANCEL = 0x00000003;
const uint MB_YESNO = 0x00000004;
const uint MB_RETRYCANCEL = 0x00000005;
public static void ShowMessageBox(string message, bool topMost = true
, string title = null, MessageBoxButtons buttons = MessageBoxButtons.OK)
{
if(topMost)
{
uint mbv = MB_TOPMOST;
if (buttons == MessageBoxButtons.OK)
mbv |= MB_OK;
if (buttons == MessageBoxButtons.OKCancel)
mbv |= MB_OKCANCEL;
if (buttons == MessageBoxButtons.AbortRetryIgnore)
mbv |= MB_ABORTRETRYIGNORE;
if (buttons == MessageBoxButtons.YesNoCancel)
mbv |= MB_YESNOCANCEL;
if (buttons == MessageBoxButtons.YesNo)
mbv |= MB_YESNO;
if (buttons == MessageBoxButtons.RetryCancel)
mbv |= MB_RETRYCANCEL;
MessageBoxUser32(0, message, title == null ? string.Empty : title, MB_TOPMOST);
}
else
{
MessageBox.Show(message, title == null ? string.Empty : title, buttons);
}
}
上面给出的答案显然是正确的,但是它需要在对象new Form上调用System.iDisposable.Dispose。
MessageBoxButtons buttons = MessageBoxButtons.YesNo;
MessageBoxIcon icon = MessageBoxIcon.Error;
string message = Resources.ResourceManager.GetString("MESSAGE");
string caption = Resources.ResourceManager.GetString("TITLE");
DialogResult result;
Form form;
using (form = new Form())
{
form.TopMost = true;
result = MessageBox.Show(form, caption, message, buttons, icon);
}
if (result == DialogResult.Yes)
{
// do something with the result
}
更多:Top-Most-MessageBox示例