为什么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);
}

为什么MessageBox不是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 阻塞窗口,直到消息被驳回,通常它将是'应用程序模态'模式。

参考链接

  1. MSDN论坛-如何将消息框显示为最上面的窗口
  2. 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示例