System.Windows.MessageBox doesn't wait for user input before going poof!

坚强是说给别人听的谎言 提交于 2019-12-01 02:29:10
Alexey Ivanov

Try to use an overload that accepts System.Windows.Window parameter and pass Null value to make your MessageBox a top-level window of your application, which is independent of all other windows that may exist. I guess your MessageBox gets owned by splashscreen form. When splashscreen is closed, the framework closes the MessageBox. So making your MessageBox ownerless should do the trick.

Based on Alexey Ivanov's suggestion, I successfully used a new window as the parent

System.Windows.Forms.MessageBox.Show(new System.Windows.Forms.NativeWindow(), errorMessage, "Application Startup", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);

The message box vanishes immediately because it has no owner. If you specify the option MessageBoxOptions.DefaultDesktopOnly, the desktop will be assigned as the owner, and the message box will work correctly on an application with no main window.

MessageBox.Show(
    "Message", 
    "Title",
    MessageBoxButton.YesNoCancel, 
    MessageBoxImage.Question, 
    MessageBoxResult.Cancel,
    MessageBoxOptions.DefaultDesktopOnly);

Create transparent hidden window and use it as an owner of the MessageBox:

private Window CreateHiddenWindow()
        {
            var window = new Window
            {
                AllowsTransparency = true,
                Background = System.Windows.Media.Brushes.Transparent,
                WindowStyle = WindowStyle.None,
                Top = 0,
                Left = 0,
                Width = 1,
                Height = 1,
                ShowInTaskbar = false
            };

            window.Show();

            return window;
        }

You can keep your splash screen and use a standard WPF MessageBox if you implement the splash screen in code instead of as an image build action.

App.xaml.cs:

var splashScreen = new SplashScreen("path/to/splash_image.bmp");
splashScreen.Show(false); //make sure to use 'false' here to prevent auto-closing

string errorMessage;

if(CheckStartUpConditions(out errorMessage))
{
    (new MainWindow()).Show();
}
else
{
    //standard WPF MessageBox may now be used here
    MessageBox.Show(errorMessage, "Application Startup", 
        MessageBoxButton.OK, MessageBoxImage.Error);

    Shutdown();
}

//explicitly close the splash screen now
splashScreen.Close(TimeSpan.FromSeconds(1));

Alexey is right, the splash screen closes the message box.

A simple way to avoid this is to use the native MessageBox function:

[DllImport("user32.dll", CharSet = CharSet.Unicode)]
public static extern int MessageBox(IntPtr hWnd, String text, String caption, uint type);

public static void Main()
{
   ...
   MessageBox(new IntPtr(0), "Hello World!", "MyApp", 0);

You need to tell WPF not to shutdown when the first window does. Look at this: http://msdn.microsoft.com/en-us/library/system.windows.application.shutdownmode.aspx. You want to set your application to shutdown explicitly (instead of after the first window closes):

<Application
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    StartupUri="MainWindow.xaml"
    ShutdownMode="OnExplicitShutdown">
</Application>

Your other choose is to set your MainWindow as the StartupUri (instead of your splash screen) and then load your splash screen in the MainWindow's loaded event. Then you would do whatever loading or time intensive stuff you need to do, hide your splash screen, and re-show your main Window.

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!