none
WPF Splash Screen?

Answers

  • If the app is going to run locally then you probably don't need to bother with multi-threading. In cold-start scenarios, a rather large amount of time (several seconds) can be spent just loading the WinFX binaries. If you load and display the splash-screen using GDI calls, you can largely side-step this cost.

    Basically, your app structure is going to look something like:

    class MyApp
    {
        public static void Main()
        {
            OpenSplashScreen();
            StartApplication();
        }

        // No inlining, to ensure that we don't load WinFX dlls until we absolutely have to.
        [MethodImpl(MethodImplOptions.NoInlining)]
        private static void StartApplication()
        {
            Application app = new Application();
            app.Run();
        }

        private static void OpenSplashScreen()
        {
            // Do GDI stuff in here.
        }

        private static void CloseSplashScreen()
        {
            // destroy window and clean-up here.
            // Called inside, say, the OnWindowLoaded() callback.
        }
    }

    I'll see if I can provide an actually example of this in action.

    Monday, December 11, 2006 11:12 PM
  • Hi all,
        Anthony Hodson's (top) answer is the most correct here... let's not forget the primary purpose of having a splash screen is to give better perceived perf.  This means that showing a WPF-derived splash screen is not a good idea, since starting up .NET and loading WPF assemblies is the lion's share of startup time.

    If you want to use the WPF splash screen control (3.5 SP1): Simply include images in any WIC-supported format as Resource type "SplashScreen".    You can choose instead to show/fade it yourself... but really it's not useful to have a WPF-based splash screen.  (This version just does the GDI version internally).  This supports transparency for PNG and some other image formats, but no animations or other fun stuff (use below approach to do that)

    If you want to roll your own splash screen (.NET 3.0 RTM or later):

    See this blog post:
    http://blogs.msdn.com/jgoldb/archive/2007/12/10/splash-screen-to-improve-wpf-application-perceived-cold-startup-performance.aspx 

    ... it provides a detailed walkthrough of how to generate the most performant possible splash screen.  This approach will allow you more customization than the WPF SplashScreen control.

    Hope this helps,
    Matt
    SDET : Deployment/Hosting
    Thursday, September 25, 2008 5:06 PM

All replies

  • I guess my main question is not how to make the splash screen itself, but the correct way to do the startup and threading stuff that's done before the main application is shown...
    Friday, December 08, 2006 2:49 PM
  • If the app is going to run locally then you probably don't need to bother with multi-threading. In cold-start scenarios, a rather large amount of time (several seconds) can be spent just loading the WinFX binaries. If you load and display the splash-screen using GDI calls, you can largely side-step this cost.

    Basically, your app structure is going to look something like:

    class MyApp
    {
        public static void Main()
        {
            OpenSplashScreen();
            StartApplication();
        }

        // No inlining, to ensure that we don't load WinFX dlls until we absolutely have to.
        [MethodImpl(MethodImplOptions.NoInlining)]
        private static void StartApplication()
        {
            Application app = new Application();
            app.Run();
        }

        private static void OpenSplashScreen()
        {
            // Do GDI stuff in here.
        }

        private static void CloseSplashScreen()
        {
            // destroy window and clean-up here.
            // Called inside, say, the OnWindowLoaded() callback.
        }
    }

    I'll see if I can provide an actually example of this in action.

    Monday, December 11, 2006 11:12 PM
  • An example would be great!
    Wednesday, January 03, 2007 4:50 PM
  • There is an intro about spash on MSDN, you can find it here http://msdn2.microsoft.com/en-us/library/aa350491.aspx

     

    QUOTE:

    Sometimes, the first instantiated Window is not actually the main application window e.g. a splash screen. In this case, you can specify the main application window using markup, like the following:

    Code Block
    <Application
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        StartupUri="StartupWindow.xaml"
        >
      <Application.MainWindow>
        <NavigationWindow Source="MainPage.xaml" Visibility="Visible"></NavigationWindow>
      </Application.MainWindow>
    </Application>

     

     


    hope to help

    Sunday, January 20, 2008 2:15 AM
  • One way is to change the app.xaml like this (notice the StartupUri):

     

    Code Block

    <Application

    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

    xmlns:Microsoft_Windows_Themes="clr-namespace:Microsoft.Windows.Themes;assembly=PresentationFramework.Luna"

    x:Class="Simple123.App"

    StartupUri="Dialogs\SplashScreen.xaml">

     

     

     

    then your splash code looks like this:

     

    Code Block

    public partial class SplashScreen

    {

    public SplashScreen()

    {

    InitializeComponent();

    this.Loaded += new RoutedEventHandler(Splash_Loaded);

    }

    void Splash_Loaded(object sender, RoutedEventArgs e)

    {

    IAsyncResult result = null;

    // This is an anonymous delegate that will be called when the initialization has COMPLETED

    AsyncCallback initCompleted = delegate(IAsyncResult ar)

    {

    App.Current.ApplicationInitialize.EndInvoke(result);

    // Ensure we call close on the UI Thread.

    Dispatcher.BeginInvoke(System.Windows.Threading.DispatcherPriority.Normal, (Invoker)delegate { Close(); });

    };

    // This starts the initialization process on the Application

    result = App.Current.ApplicationInitialize.BeginInvoke(this, initCompleted, null);

    }

    public void SetProgress(double progress)

    {

    // Ensure we update on the UI Thread.

    Dispatcher.BeginInvoke(DispatcherPriority.Normal, (Invoker)delegate { });

    }

    void cancelButton(object sender, RoutedEventArgs e)

    {

    this.DialogResult = false;

    }

    }

     

     

    and your app code looks like this:

     

    Code Block

    internal delegate void Invoker();

    public partial class App : Application

    {

    //public static Window1 MainWindow;

    public App()

    {

    ApplicationInitialize = _applicationInitialize;

    }

    public static new App Current

    {

    get { return Application.Current as App; }

    }

    internal delegate void ApplicationInitializeDelegate(SplashScreen splashWindow);

    internal ApplicationInitializeDelegate ApplicationInitialize;

    private void _applicationInitialize(SplashScreen splashWindow)

    {

    Thread.Sleep(1000);

    // Create the main window, but on the UI thread.

    Dispatcher.BeginInvoke(DispatcherPriority.Normal, (Invoker)delegate

    {

    Window1 MainWindow = new Window1();

    Helper.setWin(MainWindow);

    MainWindow.Show();

    });

    }

    }

     

     

    Tom

     

    Sunday, January 20, 2008 7:41 PM
  •  Shiny Zhu wrote:

    There is an intro about spash on MSDN, you can find it here http://msdn2.microsoft.com/en-us/library/aa350491.aspx

     

    QUOTE:

    Sometimes, the first instantiated Window is not actually the main application window e.g. a splash screen. In this case, you can specify the main application window using markup, like the following:

    Code Block
    <Application
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        StartupUri="StartupWindow.xaml"
        >
      <Application.MainWindow>
        <NavigationWindow Source="MainPage.xaml" Visibility="Visible"></NavigationWindow>
      </Application.MainWindow>
    </Application>

     

     


    hope to help

     

    ---------------------------------------------------

     

    This method looks clean but it only works if it is a "Page".  I tried to put in --> Source="MainWindow.xaml" and I get the following exception "root element is not valid for navigation" What would be the syntax to put in a Window instead of a Page?

    Monday, March 31, 2008 6:18 PM
  • Yes, if you use a NavigationWindow you will get the error you specified.  You would need to do the following.  Where WPFSandbox is the name of the assembly and where you MainWindow.xaml is your main window.

    Code Snippet

    <Application
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x=http://schemas.microsoft.com/winfx/2006/xaml

        xmlns:local="clr-namespace:WPFSandbox"
        StartupUri="StartupWindow.xaml"
        >
      <Application.MainWindow>   

    <local:MainWindow Visibility="Visible"/>

      </Application.MainWindow>
    </Application>

     

     

    Friday, April 11, 2008 2:26 PM
  •  Patrick Kragthorpe-Shirley wrote:
    Yes, if you use a NavigationWindow you will get the error you specified.  You would need to do the following.  Where WPFSandbox is the name of the assembly and where you MainWindow.xaml is your main window.

    Code Snippet

    <Application
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x=http://schemas.microsoft.com/winfx/2006/xaml

        xmlns:local="clr-namespace:WPFSandbox"
        StartupUri="StartupWindow.xaml"
        >
      <Application.MainWindow>   

    <local:MainWindow Visibility="Visible"/>

      </Application.MainWindow>
    </Application>

     

     

     

    Good, this solution would works with some minor ajustment.  If you use the code as is, you will see BOTH of your windows at startup.  

     

    If you want to see only the StartupWindow first and them the MainWindow after, you should start the MainWindow visibility as "Hidden".   Then then put the MainWindow visibility to "Visible" when the StartupWindow closes.

    Friday, April 11, 2008 6:02 PM
  •  TomGiam :  what references and using statements are you using for your code? Your code deosn't work as it misses some references. I fugured some, but some others are still missing. Please help...

     

    thanks

     

    vitya

    Tuesday, May 20, 2008 11:57 AM
  • Tom do you have a demo app for this?
    Your method seems better because I could probably update the splash screen with status info (loading, updating, etc.)
    Thursday, September 25, 2008 4:53 PM
  • Hi all,
        Anthony Hodson's (top) answer is the most correct here... let's not forget the primary purpose of having a splash screen is to give better perceived perf.  This means that showing a WPF-derived splash screen is not a good idea, since starting up .NET and loading WPF assemblies is the lion's share of startup time.

    If you want to use the WPF splash screen control (3.5 SP1): Simply include images in any WIC-supported format as Resource type "SplashScreen".    You can choose instead to show/fade it yourself... but really it's not useful to have a WPF-based splash screen.  (This version just does the GDI version internally).  This supports transparency for PNG and some other image formats, but no animations or other fun stuff (use below approach to do that)

    If you want to roll your own splash screen (.NET 3.0 RTM or later):

    See this blog post:
    http://blogs.msdn.com/jgoldb/archive/2007/12/10/splash-screen-to-improve-wpf-application-perceived-cold-startup-performance.aspx 

    ... it provides a detailed walkthrough of how to generate the most performant possible splash screen.  This approach will allow you more customization than the WPF SplashScreen control.

    Hope this helps,
    Matt
    SDET : Deployment/Hosting
    Thursday, September 25, 2008 5:06 PM
  • Even rolling your own splash screen in managed code (or using the SplashScreen class) incurs the cost of starting the CLR. For this reason, I implemented a alpha-blended splash screen (for my WPF application) in a native C++ Win32 application; I've blogged all the code required to do it at http://code.logos.com/blog/2008/09/displaying_a_splash_screen_with_c_introduction.html.

    Bradley

    • Proposed as answer by SSG31415926 Thursday, June 04, 2009 2:45 PM
    Wednesday, October 01, 2008 8:52 PM
  • Matt Galbraith - MSFT said:

    If you want to use the WPF splash screen control (3.5 SP1): Simply include images in any WIC-supported format as Resource type "SplashScreen".    You can choose instead to show/fade it yourself... but really it's not useful to have a WPF-based splash screen.  (This version just does the GDI version internally).  This supports transparency for PNG and some other image formats, but no animations or other fun stuff (use below approach to do that)



    I'm using SplashScreen build option on a png image. But when the main window apprears, it overlaps the splash image, then when the image fade out, it again covers part of the window.

    Is there anyway to keep the splash image always on top?
    Sunday, February 08, 2009 1:08 PM
  • Unfortunately not in 3.5 Sp1.  The deficiency was noted and an overload to the Show() method was added for v4.0, which should be available in public beta in the not too distant future.  Until then, you may have luck explicitly calling Close() on the splash screen before your app's window shows up.  The SplashScreen still won't be topmost but should reduce the visual effect you describe.

    -Matt
    SDET : Deployment/Hosting
    • Proposed as answer by Replika Friday, February 13, 2009 5:19 PM
    Monday, February 09, 2009 8:50 PM
  • Maybe yuo can explain the main thing about this : Helper.setWin(MainWindow);

    Monday, November 16, 2009 9:20 AM