Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Initial work on the new fast splash screen #186

Merged
merged 13 commits into from
Nov 19, 2024
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
Loading