C# 为什么不是';t消息框最上面?

C# 为什么不是';t消息框最上面?,c#,messagebox,topmost,C#,Messagebox,Topmost,我最近发现,默认情况下,messagebox在默认显示时并不是最顶层的表单,我想知道是否有人知道在什么情况下,您不希望messagebox显示在其他窗口的顶部 当我在加载应用程序时开始显示启动屏幕时,我发现了这个问题,看起来我的程序仍在运行,但启动屏幕后面有一个等待输入的MessageBox。。启动屏幕显示在与调用messagebox的线程不同的线程上,所以我想这就是为什么它没有出现在启动上面的原因;但这仍然不能解释为什么MessageBox在默认情况下没有MB_最上面的标志 编辑 为了更好地澄

我最近发现,默认情况下,messagebox在默认显示时并不是最顶层的表单,我想知道是否有人知道在什么情况下,您不希望messagebox显示在其他窗口的顶部

当我在加载应用程序时开始显示启动屏幕时,我发现了这个问题,看起来我的程序仍在运行,但启动屏幕后面有一个等待输入的
MessageBox
。。启动屏幕显示在与调用messagebox的线程不同的线程上,所以我想这就是为什么它没有出现在启动上面的原因;但这仍然不能解释为什么MessageBox在默认情况下没有
MB_最上面的
标志

编辑

为了更好地澄清: 最后,我不得不做一些类似的事情来制作一个messagebox,代码并不像从内存中写的那样完全正确)


显示
MessageBox
时,请将其所有者作为第一个参数。例如,从
表单
实例调用调用时:

MessageBox.Show(this, "Message");
作为第一个参数提供对拥有它的窗口的引用


消息框(以及通常的模式表单)不会出现在应用程序的所有窗口的顶部。它们只出现在其所有者的顶部。如果希望消息框(或其他模式表单)位于初始屏幕的顶部,请将其所有者设置为初始表单实例。

要在应用程序的最顶部显示消息框,请执行以下操作

代码

//Should be MessageBox.Show() below
MessageBox.Show(this, "My top most message");
默认情况下不在
MB_最上面的原因

如果MB_TOPMOST为默认值,则
消息框
将以“系统模式”模式显示,并且它将恰好位于该窗体的顶部,副作用是“系统模式”模式将导致
消息框
阻塞窗口,直到消息被解除,通常情况下,它将为“应用模式”

参考链接


  • 如果您可以获得对话框应该显示在其顶部的窗口的句柄或引用,则建议的解决方案将起作用。然而,这并不总是可能或容易实现:

    • 该窗口是一个启动屏幕,不应与您的业务逻辑紧密结合
    • 窗口是由当前类或库以外的其他类或库创建的
    • 该窗口不受您的控制,即来自第三方(本机)库
    在这种情况下,您可以从
    User32.dll
    使用Win32
    MessageBox
    API,但也可以使用更简单的托管解决方案:

    MessageBox.Show(new Form { TopMost = true }, "Hello, I'm on top!");
    
    代码
    新表单{TopMost=true}
    将使用
    MB_TopMost
    属性创建一个隐藏表单,该属性由messagebox对话框窗口继承。因此,它将显示在所有其他窗口的顶部。使用
    new Form()
    inline没有副作用,没有视觉效果,它将通过垃圾收集器正常销毁


    注意:如果您尚未在表单中,请不要忘记名称空间,这是
    System.Windows.Forms.MessageBox
    ,而不是
    System.Windows.MessageBox
    !(谢谢,)。

    上面给出的答案显然是正确的,只需在对象新窗体上调用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
    }
    
    更多信息:


    我尝试粘贴一个更完整的代码块,它肯定能工作

        [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);
            }
        }
    

    我不明白你的答案。。这将如何确保messagebox始终高于所有其他窗口?或者这能实现什么?不会的。它将始终仅位于其所有者的顶部。如果你想让它出现在闪屏上,把它的所有者设置为闪屏实例。这个答案看起来很棒!但我认为MessageBox还是阻止了windows?从中我发现有类似于
    系统模式
    应用程序模式
    。也许我稍后会查看更多细节。只有模式消息框会阻塞它们的表单,“常规”消息框即使在您退出生成它的程序后仍然可以保持。我相信msdn页面是我最终解决方案的灵感来源,我想关于系统模式和应用程序模式的观点正是我想要的。谢谢:D(很快就会接受)作为补充说明,想象一下,如果默认的MessageBox是最上面的:您在应用程序A中工作,应用程序B在后台运行一些操作。当您在工作时,应用程序B抛出一个MessageBox,它位于应用程序a的顶部,显示在应用程序a的顶部。没有任何上下文,充其量您可能会感到困惑,最坏的情况下,您可能会在应用程序a的上下文中解释消息并单击错误的选项,从而导致应用程序B中出现一些意外操作。有趣的方法,之所以选择这样的答案,是因为应用程序模式和系统模式之间存在差异。我认为您的方法仍将保持messagebox应用程序模式,并且在您概述的环境中会很有用+1为了向其他人澄清,这是
    System.Windows.Forms.MessageBox
    而不是
    System.Windows.MessageBox
    这是解决我问题的唯一解决方案。谢谢亚伯!感谢这是最好的解决方案,对于那些使用“this”获得“交叉线程异常”的人来说,也应该使用“new Form{TopMost=true}”。我在制作Excel加载项时发现了这一点,对于那些处于类似情况下的人来说,
    MessageBox
    不会出现在前面,添加
    Application.DoEvents()MessageBox.Show()之前,code>为我解决了这个问题。这个答案同样有效,但在多监视器设置中,它会在第一个监视器上创建消息框,而不是Excel窗口所在的监视器。
    
        [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);
            }
        }