Skip to content

Commit

Permalink
Initial work on the new fast splash screen (#186)
Browse files Browse the repository at this point in the history
* new fast and simple splash screen
  • Loading branch information
dotMorten authored Nov 19, 2024
1 parent 28bee68 commit 746753a
Show file tree
Hide file tree
Showing 8 changed files with 535 additions and 38 deletions.
126 changes: 96 additions & 30 deletions docs/concepts/Splashscreen.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,73 @@
## Splash Screen

WinUIEx provides two kinds of splash screens:
- `SimpleSplashScreen`: A simple splash screen that shows just an image and can be launched before any UI loads.
- `SplashScreen`: A more advanced splash screen that can show any XAML including a progress bar and status text.


### SimpleSplashScreen

`SimpleSplashScreen` will show an image while the app is loading. To use it, create a new `SimpleSplashScreen` in App.xaml.cs:

```cs
private SimpleSplashScreen vss { get; set; }

public App()
{
fss = SimpleSplashScreen.ShowDefaultSplashScreen(); // Shows the splash screen you already defined in your app manifest. For unpackaged apps use .ShowSplashScreenImage(imagepath):
// fss = SimpleSplashScreen.ShowSplashScreenImage(full_path_to_image_); // Shows a custom splash screen image. Must be a full-path (no relative paths)
this.InitializeComponent();
}
```

Once your window is activated, you can remove the splash screen by either calling `.Dispose()` or `Hide()`.

```cs
protected override void OnLaunched(Microsoft.UI.Xaml.LaunchActivatedEventArgs args)
{
m_window = new MainWindow();
m_window.Activate();
Window_Activated += Window_Activated;

}

private void Window_Activated(object sender, WindowActivatedEventArgs args)
{
((Window)sender).Activated -= Window_Activated;
fss?.Hide();
fss = null;
}
```

For even faster splash screen, disable the XAML generated main method by defining the `DISABLE_XAML_GENERATED_MAIN` preprocessor directive
and instead defining your own start method. You'll then be able to display the splash screen as the very first thing before the application is created. For example:

```cs
#if DISABLE_XAML_GENERATED_MAIN
public static class Program
{
[System.STAThreadAttribute]
static void Main(string[] args)
{
// If you're using the WebAuthenticator, make sure you call this method first before the splashscreen shows
if (WebAuthenticator.CheckOAuthRedirectionActivation(true))
return;
var fss = SimpleSplashScreen.ShowDefaultSplashScreen();
WinRT.ComWrappersSupport.InitializeComWrappers();
Microsoft.UI.Xaml.Application.Start((p) => {
var context = new Microsoft.UI.Dispatching.DispatcherQueueSynchronizationContext(Microsoft.UI.Dispatching.DispatcherQueue.GetForCurrentThread());
System.Threading.SynchronizationContext.SetSynchronizationContext(context);
new App(fss); // Pass the splash screen to your app so it can close it on activation
});
}
}
#endif
```

### SplashScreen

To create a new splash screen, first create a new WinUI Window.
Next change the baseclass from "Window" to SplashScreen:
Next change the baseclass from `Window` to `SplashScreen`:

Before:
```xml
Expand All @@ -21,52 +87,52 @@ Before:
```cs
public sealed partial class SplashScreen : Window
{
public SplashScreen()
{
this.InitializeComponent();
}
public SplashScreen()
{
this.InitializeComponent();
}
}
```
After:
```cs
public sealed partial class SplashScreen : WinUIEx.SplashScreen
{
public SplashScreen(Type window) : base(window)
{
this.InitializeComponent();
}
public SplashScreen(Type window) : base(window)
{
this.InitializeComponent();
}
}
```

Next in App.xaml.cs, change OnLaunched from:
```cs
protected override void OnLaunched(Microsoft.UI.Xaml.LaunchActivatedEventArgs args)
{
m_window = new MainWindow();
m_window.Activate();
}
protected override void OnLaunched(Microsoft.UI.Xaml.LaunchActivatedEventArgs args)
{
m_window = new MainWindow();
m_window.Activate();
}
```
To:
```cs
protected override void OnLaunched(Microsoft.UI.Xaml.LaunchActivatedEventArgs args)
{
var splash = new SplashScreen(typeof(MainWindow));
splash.Completed += (s, e) => m_window = e;
}
protected override void OnLaunched(Microsoft.UI.Xaml.LaunchActivatedEventArgs args)
{
var splash = new SplashScreen(typeof(MainWindow));
splash.Completed += (s, e) => m_window = e;
}
```

Lastly, override OnLoading, to create some long-running setup work - once this method completes, the splash screen will close and the window in the type parameter will launch.

Example:
```
protected override async Task OnLoading()
{
//TODO: Do some actual work
for (int i = 0; i < 100; i+=5)
{
statusText.Text = $"Loading {i}%...";
progressBar.Value = i;
await Task.Delay(50);
}
}
```cs
protected override async Task OnLoading()
{
//TODO: Do some actual work
for (int i = 0; i < 100; i+=5)
{
statusText.Text = $"Loading {i}%...";
progressBar.Value = i;
await Task.Delay(50);
}
}
```
2 changes: 1 addition & 1 deletion src/Directory.Build.targets
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
<Authors>Morten Nielsen - https://xaml.dev</Authors>
<Company>Morten Nielsen - https://xaml.dev</Company>
<PackageIcon>logo.png</PackageIcon>
<Version>2.4.2</Version>
<Version>2.5.0</Version>
<!--<PackageValidationBaselineVersion>2.3.4</PackageValidationBaselineVersion>-->
</PropertyGroup>

Expand Down
13 changes: 12 additions & 1 deletion src/WinUIEx/NativeMethods.txt
Original file line number Diff line number Diff line change
Expand Up @@ -54,4 +54,15 @@ DwmExtendFrameIntoClientArea
CreateRectRgn
CreateSolidBrush
FillRect
GetDC
GetDC
ReleaseDC
GdiplusStartup
GdiplusShutdown
GetObject
GdipCreateBitmapFromFile
GdipCreateHBITMAPFromBitmap
WNDCLASSEXW
RegisterClassEx
CreateCompatibleDC
SelectObject
MonitorFromPoint
Loading

0 comments on commit 746753a

Please sign in to comment.