【问题标题】:how to set wpf MessageBox.Owner to desktop window because SplashScreen closes MessageBox由于 SplashScreen 关闭 MessageBox,如何将 wpf MessageBox.Owner 设置为桌面窗口
【发布时间】:2009-02-23 04:14:38
【问题描述】:

我通过将位图的 Build Action 设置为 Splashscreen 来使用 WPF 中的 SplashScreen 功能。在初始屏幕后面,正在检查许可信息,如果失败,我会显示一个 MessageBox

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

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

是否可以将 MessageBox.Owner 设置为桌面窗口?以及如何,因为唯一想到的其他函数是 GetDesktopWindow() api 函数,但它返回一个窗口句柄并且 MessageBox.Owner 是一个 WPF 窗口。

【问题讨论】:

    标签: wpf messagebox


    【解决方案1】:

    正如@Nir 在他的回答中指出的那样,由于使用桌面窗口作为模态对话框的父级不是一个好主意,因此还有其他三种解决方法:

    1) 使用隐藏窗口。创建一个微小的非模态窗口作为 MessageBox 或其他模态对话框的父级。此处描述了此方法:

    http://social.msdn.microsoft.com/Forums/en-US/wpf/thread/116bcd83-93bf-42f3-9bfe-da9e7de37546/

    2) 创建非模态消息窗口。将您的启动模式更改为显式关闭并使用非模式窗口来显示您的消息。这种方法在这个 StackOverflow 问题的答案中有所描述:

    MessageBox with exception details immediately disappears if use splash screen in WPF 4.0

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

    https://connect.microsoft.com/VisualStudio/feedback/details/600197/wpf-splash-screen-dismisses-dialog-box

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

    http://social.msdn.microsoft.com/Forums/en-US/wpf/thread/8dd49fd0-9cc9-43c6-b285-6f119ab8a32e/

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

    http://connect.microsoft.com/VisualStudio/feedback/details/600197/wpf-splash-screen-dismisses-dialog-box

    【讨论】:

      【解决方案2】:

      我自己想出了这个解决方案,所以也许它有问题,但它似乎完美地工作:

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

      【讨论】:

      • 不错的简单解决方法。但是,Visibility=Visibility.Hidden 并不是真正需要的,因为无论如何您都将显示窗口。相反,为了避免后台窗口的闪屏显示,我使用了:new Window { WindowState = WindowState.Minimized, ShowInTaskbar = false }
      • new Window { AllowsTransparency = true,ShowInTaskbar=false,WindowStyle=WindowStyle.None, Background=Brushes.Transparent} 可以在设置可见性时使窗口完全隐藏,否则在调用Show() 时窗口状态会导致窗口显示几毫秒。
      【解决方案3】:

      我发现了问题。我也在使用导致此问题的内置闪屏:WPF SplashScreen closes MessageBox

      【讨论】:

      • 现在的问题是如何将 MessageBox 的所有者设置为桌面窗口?
      【解决方案4】:

      你能发布一些代码吗?我刚刚尝试将其添加到新 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);
      }
      

      ...它按预期工作(“确认开始”提示保持打开状态,直到我做出回应,如果我点击“否”,应用程序将关闭)。

      【讨论】:

      • 马特,我也像你一样测试了它并意识到它确实有效,因为我使用的是闪屏,它关闭了 MessageBox,没有闪屏它没有关闭
      • 所以我想你现在需要决定是否将问题关闭为“不再相关”或(正如@adriaanp 在他的评论中建议的那样)将其重新作为一个不同的问题。
      【解决方案5】:

      桌面窗口永远不是正确的父窗口,请阅读此内容了解原因:

      http://blogs.msdn.com/oldnewthing/archive/2004/02/24/79212.aspx

      现在这篇文章中描述的问题并没有发生太多,因为 MS 解决了它,在这篇文章中你可以看到:

      http://blogs.msdn.com/oldnewthing/archive/2006/11/02/931674.aspx

      【讨论】:

        【解决方案6】:

        这个问题还是个问题,我最近遇到了。对我来说,解决方案是在出现任何问题时立即关闭启动屏幕:

                SplashScreen splash = new(Assembly.GetAssembly(typeof(GuiApp))!, "Resources/img_my.png");
                splash.Show(false);
        
                using ServiceProvider? services = initializeApp();
        
                if (services == null)
                {
                    splash.Close(TimeSpan.Zero);
                    return -3;
                }
        

        之后MessageBox正常显示。

        【讨论】:

          【解决方案7】:

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

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

          点击按钮

          粘贴此代码

          if (System.Windows.Forms.MessageBox.Show("你确定", "删除", System.Windows.Forms.MessageBoxButtons.YesNo, System.Windows.Forms.MessageBoxIcon.Question) == System.Windows .Forms.DialogResult.Yes) { this.Close(); } 别的 { MessageBox.Show("为什么不删除"); }

          【讨论】:

            【解决方案8】:

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

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

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

            【讨论】:

              猜你喜欢
              • 2011-11-29
              • 1970-01-01
              • 2011-11-04
              • 2012-10-08
              • 1970-01-01
              • 2017-12-02
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多