Reputation: 6796
My WPF app shows a PNG image as a splash screen at startup using the standard MS recommended method. That is, I chose an existing image file and set its build action to "Splash Screen" I like this because it's simple. No code to write, just a property.
But it's got a problem: It "jumps".
When my app is starting and the splash screen first appears it is large and centered on the screen as I want. But then, almost immediately, it jumps up to the left and gets smaller. As if its window goes from being maximized to only taking up part of the screen.
This "jump" happens even before the constructor of my Application object is reached so certainly long before my MainWindow is in mix. And I'm certainly not resizing anything.
So what could be causing this? I can't even see that I can set a breakpoint anywhere to detect this. Is there some property I can set somewhere to prevent this from happening? Like maybe in my App.xaml?
I should say that this is a Prism 7.2 application using .NET core 3.1, if any of that matters
Upvotes: 2
Views: 1486
Reputation: 156
The cause is something to do with the System Display "Scale" which you can adjust in the Settings panel:
On my system, when scale is set to 100%, the problem disappears. Set the Scale to anything else, and the splash screen jumps.
It seems to also depend on which flavor of .NET you use: https://github.com/dotnet/wpf/issues/5070
Upvotes: 2
Reputation: 801
The problem is related to display scale and DPI Awareness.
You can read more about DPI Awareness here: https://learn.microsoft.com/en-us/windows/win32/hidpi/high-dpi-desktop-application-development-on-windows
To fix the problem just declare your application as using Per-Monitor (V2) DPI Awareness. You can read how to do that here: https://learn.microsoft.com/en-us/windows/win32/hidpi/setting-the-default-dpi-awareness-for-a-process
Use the method involving application manifest file.
<application xmlns="urn:schemas-microsoft-com:asm.v3">
<windowsSettings>
<dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true</dpiAware>
<dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">PerMonitorV2</dpiAwareness>
</windowsSettings>
</application>
<assemblyIdentity>
element)<ApplicationManifest>app.manifest</ApplicationManifest>
in your .csproj file.Root cause of the problem:
WPF forces the use of DPI Awareness mode programmatically when it starts, but SplashScreen shows off before WPF starts. So the SplashScreen's window is already created when WPF calls SetProcessDpiAwarenessContext, but changing DPI awareness programmatically after creating any windows is officially not supported.
SplashScreen works well when DPI awareness is set properly from the beginning.
Upvotes: 4
Reputation: 411
If you override the:
protected virtual void OnStartup (System.Windows.StartupEventArgs e);
what you probably already do. Then you can control the splash screen a little bit more in there by:
SplashScreen splashScreen = new SplashScreen(YourImageFileName);
splashScreen.Show(false, true); // Auto-close: NO, On top: YES
And then later when you main window is ready to be shown, then:
splashScreen.Close(FadeTimeout); // FadeTimeout is of type TimeSpan
I know you liked the way, where you do not have anything in your code on the splash screen, but this little extra code you can control the splash screen much more. And it is probably what you need
Upvotes: 3