如何将wpf MessageBox.Owner设置为桌面窗口,因为SplashScreen关闭MessageBox

如何将wpf MessageBox.Owner设置为桌面窗口,因为SplashScreen关闭MessageBox,wpf,messagebox,Wpf,Messagebox,我正在使用WPF中的SplashScreen功能,将位图的构建操作设置为SplashScreen。在启动屏幕后面,正在检查许可信息,如果失败,我将显示一个消息框 根据这一点,这是因为MessageBox.Owner是启动屏幕,一旦另一个窗口打开,即使它是MessageBox,启动屏幕窗口也会关闭,然后关闭MessageBox,因此用户永远看不到MessageBox _formKludge.TopMost = true; MessageBox.Show(_formKludge

我正在使用WPF中的SplashScreen功能,将位图的构建操作设置为SplashScreen。在启动屏幕后面,正在检查许可信息,如果失败,我将显示一个消息框

根据这一点,这是因为MessageBox.Owner是启动屏幕,一旦另一个窗口打开,即使它是MessageBox,启动屏幕窗口也会关闭,然后关闭MessageBox,因此用户永远看不到MessageBox

     _formKludge.TopMost = true;

     MessageBox.Show(_formKludge, "Nice informative message.", "Super-duper Program",
                     MessageBoxButtons.OK, MessageBoxIcon.Error);

     _formKludge.TopMost = false;
因此,解决方法是将MessageBox.Owner设置为另一个窗口,但这意味着我必须实例化另一个甚至不需要的窗口


是否可以将MessageBox.Owner设置为桌面窗口?还有,因为我想到的另一个函数是GetDesktopWindow()api函数,但它返回一个窗口句柄和MessageBox。所有者是一个WPF窗口。

你能发布一些代码吗?我刚刚尝试在新的WPF应用程序中将其添加到App.xaml.cs文件中:

protected override void OnStartup(StartupEventArgs e)
{
    if (MessageBox.Show("Start app?", "Confirm Start", 
        MessageBoxButton.YesNo) == MessageBoxResult.No)
    {
        this.Shutdown();
        return;
    }

    this.StartupUri = new Uri("Window1.xaml", UriKind.Relative);
    base.OnStartup(e);
}

。。。它可以按预期工作(“确认启动”提示保持打开状态,直到我做出响应,如果我单击“否”,应用程序将关闭)。

我发现了问题。我还使用了内置启动屏幕,这导致了以下问题:

桌面窗口从来都不是正确的父窗口,请阅读以下内容了解原因:

现在,这篇文章中描述的问题不会发生太多,因为MS解决了这个问题,在这篇文章中,您可以看到:


这对我帮助很大。。。。。 给了我新的想法 但是我在这里看到的示例代码需要进行一些修改

下面是wpf中的一个简单示例,经过修改 现在它正在工作

点击按钮

粘贴此代码

如果(System.Windows.Forms.MessageBox.Show(“确定”、“删除”、System.Windows.Forms.MessageBoxButtons.YesNo、System.Windows.Forms.MessageBoxIcon.Question)==System.Windows.Forms.DialogResult.Yes) { 这个。关闭(); } 其他的 { MessageBox.Show(“为什么不删除”);
}

由于使用桌面窗口作为模式对话框的父窗口不是一个好主意,正如@Nir在他的回答中指出的,这里有三个其他解决方法:

1) 使用隐藏窗口。创建一个小的非模式窗口,作为MessageBox或其他模式对话框的父窗口。这里描述了这种方法:

2) 创建非模态消息窗口。将启动模式更改为显式关闭,并使用非模式窗口显示消息。该问题的答案中描述了该方法:

3) 给MessageBox打两次电话。显然,该问题只影响显示的第一个模态对话框。因此,如果您不介意第一个对话框打开和关闭时的闪烁,您可以简单地调用您的模态对话框两次

就我个人而言,我不喜欢这些变通办法。唯一的其他选择是避免内置的SplashScreen功能,并从头开始使用自己的功能。如果您想进一步调查该路线,这里有一个链接:

最后,如果你和我一样对这个问题感到恼火,你可以在这里投票支持微软修复这个错误:


我自己提出了这个解决方案,所以可能有问题,但它似乎工作得很好:

Window temp = new Window() { Visibility=Visibility.Hidden };
temp.Show();
MessageBox.Show(temp, "An error occurred before the application could start.\n\nTechnical Details: " + ex.Message, "Fatal Error", MessageBoxButton.OK, MessageBoxImage.Stop);
App.Current.Shutdown(1);

这与OP的情况没有直接关系,但对于在某些特殊情况下,MessageBox隐藏在其他窗口后面有问题的其他人来说,这可能很有用

正如@dthrasher提到的,一种解决方案是使用隐藏的虚拟窗口。但有时即使这样也不够。我遇到的情况是,解决方案不仅是使用一个隐藏的虚拟窗口,而且每当我将它与MessageBox一起使用时,都要打开它的最顶层属性

     _formKludge.TopMost = true;

     MessageBox.Show(_formKludge, "Nice informative message.", "Super-duper Program",
                     MessageBoxButtons.OK, MessageBoxIcon.Error);

     _formKludge.TopMost = false;

马特,我也像你一样测试了它,并意识到它确实有效,因为我使用的是闪屏,它会关闭MessageBox,没有闪屏它不会关闭,所以我想现在你需要决定是否关闭这个问题,因为“不再相关”或者(正如@adriaanp在他的评论中建议的那样)将其作为一个不同的问题进行修改。现在的问题是如何将MessageBox的所有者设置为deskop窗口?这是一个很好且简单的解决方法。但是,实际上并不需要
Visibility=Visibility.Hidden
,因为您还是要显示窗口。相反,为了避免背景窗口的飞溅显示,我使用了:
新窗口{WindowState=WindowState.Minimized,ShowInTaskbar=false}
新窗口{allowsttransparency=true,ShowInTaskbar=false,WindowStyle=WindowStyle.None,background=bruss.Transparent}
可以使窗口完全隐藏,而设置可见性或窗口状态将导致在调用
Show()
时窗口显示几毫秒。