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