wpf icon indicating copy to clipboard operation
wpf copied to clipboard

WPF Splashscreen doesn't work correctly on monitors with different dpi's

Open james1301 opened this issue 4 years ago • 14 comments

  • .NET Core Version: 5.0
  • Windows version: Windows 10 21H1
  • Does the bug reproduce also in WPF for .NET Framework 4.8?: No
  • Is this bug related specifically to tooling in Visual Studio (e.g. XAML Designer, Code editing, etc...)? No

Problem description:

Default SplashScreen image appears initially at wrong dpi in the center of the screen. It it then corrects the DPI and then is no longer in the center of the screen. So on a DPI higher than 100%, it appears to shrink and move off center.

Actual behavior:

SplashScreen appears at wrong DPI and then corrects itself (shrinks) and is moved off center.

Expected behavior:

SplashScreen appears at correct DPI and remains in the center of the screen.

Minimal repro:

  1. Using a monitor that is set at a DPI higher than 100% (I was using 250%)
  2. Create a Net Framework 5.0 WPF Application
  3. Add an Image to the project
  4. Set the Properties of the Image to BuildAction = SplashScreen
  5. Run Application and you will see it initially in the center of the screen at a larger non-DPI aware size and then move of center when it is corrected to the DPI aware size

Attached Sample: SplashScreenProblem.zip

james1301 avatar Aug 13 '21 11:08 james1301

Maybe Duplicated : #3060 #2942 #947

Link: #2031

lindexi avatar Aug 14 '21 00:08 lindexi

Similar to those and I'm sure sorting those would probably sort this too. But this one is definitely a bug in .NET compared to it working consistently in .NET Framework. It's unusable as is, DPI aware or not DPI aware would be acceptable to me, just not trying to do a bit of both while it loads up, that is the best of no worlds.

james1301 avatar Aug 16 '21 07:08 james1301

Hi @james1301,

Were you able to test this on 4.8? Thanks.

ryalanms avatar Aug 17 '21 16:08 ryalanms

@ryalanms, yeah I tested it and it was fine on .NET Framework 4.8.

james1301 avatar Aug 18 '21 07:08 james1301

@ryalanms, @lindexi has anything happened with this?

james1301 avatar Aug 08 '23 08:08 james1301

@james1301 Now I use https://github.com/kkwpsv/SplashImage . See https://github.com/dotnet/wpf/issues/2031

lindexi avatar Aug 08 '23 08:08 lindexi

Thanks @lindexi, but there doesn't seem much activity on that GitHub, we use very few third party libraries and the ones we do use need a certain level of popularity and support for us to consider using them so we know they should be all good for the future and hopefully well tested.

james1301 avatar Aug 08 '23 08:08 james1301

After a detailed investigation, I believe I've identified the root cause of the issue, along with a potential solution. It appears that the splash screen window is being created and displayed, and then

https://github.com/dotnet/wpf/blob/15cc5c1aa93c51090aa7207e4c975de006227aa5/src/Microsoft.DotNet.Wpf/src/PresentationCore/ModuleInitializer.cs#L52 is invoked, which changes the application's DPI awareness and causes the splash screen window to rescale.

My possible fix is to have the process DPI aware right from the beginning by changing the application manifest (https://learn.microsoft.com/en-us/windows/win32/hidpi/setting-the-default-dpi-awareness-for-a-process).

If system-aware is enough, then adding this is enough:

<dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true</dpiAware>

Or a more modern approach (which is per monitor aware, only supported on Windows 10, version 1607 and later): <dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">PerMonitorV2</dpiAwareness>

This causes the splash screen window to be created after DPI awareness was enabled, and this fixed the issue for me.

Nimce avatar Apr 18 '25 07:04 Nimce

@Nimce This doesn't work for me unfortunately. I have an app.manifest anyway in order to make my WPF app PerMonitorV2 aware; though the splashscreen does not scale (I'm on .NET 9.0.4 and running at 175 %).

<?xml version="1.0" encoding="utf-8"?>
<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
  <assemblyIdentity version="1.0.0.0" name="MyApplication.app"/>
  <trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
    <security>
      <requestedPrivileges xmlns="urn:schemas-microsoft-com:asm.v3">
        <requestedExecutionLevel level="asInvoker" uiAccess="false" />
      </requestedPrivileges>
    </security>
  </trustInfo>

  <compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
    <application>
      <!-- Windows 10 -->
      <supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}" />
    </application>
  </compatibility>

  <application xmlns="urn:schemas-microsoft-com:asm.v3">
    <windowsSettings>
      <dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">PerMonitorV2</dpiAwareness>
      <dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true</dpiAware>
      <longPathAware xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">true</longPathAware>
    </windowsSettings>
  </application>
</assembly>

mnissl avatar Apr 23 '25 08:04 mnissl

@mnissl Can you provide more details? how you integrated the splash screen in your app? or even a video of the problem? I just tried it again with .NET 9.0.4 and 175 % DPI and works fine with the manifest you provided.

With the manifest (I used the one you provided), the splash screen works correctly, centered and then the program loads:

https://github.com/user-attachments/assets/4e0b9e8e-5d39-4f7e-8559-15982d566c86

Without the manifest (the splash screen changes it's position and it's not centered either):

https://github.com/user-attachments/assets/e835d93f-2b14-433c-9739-55fb41ac04ba

Nimce avatar Apr 24 '25 19:04 Nimce

@mnissl Can you provide more details? how you integrated the splash screen in your app? or even a video of the problem? I just tried it again with .NET 9.0.4 and 175 % DPI and works fine with the manifest you provided.

new SplashScreen("image.png").Show(false, false);

With the manifest (I used the one you provided), the splash screen works correctly, centered and then the program loads: splashscreen-with-manifest.mp4

Without the manifest (the splash screen changes it's position and it's not centered either): splashscreen-without-manifest.mp4

Well, don't you see that without the manifest (in your second video), the splash screen first appears bigger before it scales down and changes its position.

With the manifest (in your first video), the position is correct (it's centered), but it is as small as without the manifest.

When you open your splashscreen image with the Windows Photos app (I'm on Windows 11), you will see that it renders the image at 100 %. Select 175 % in the bottom bar to see how big the image should appear in the splashscreen!

Well, as I just see, this issue here is actually about the splashscreen being off-center, whereas issue 947 treats the fact that image isn't scaled correctly. So a proper manifest obviously fixes the position, but the not the scale.

mnissl avatar Apr 25 '25 07:04 mnissl

@mnissl I see, sounds like we were talking about slightly different issues. For me, this behavior with the manifest enabled is appropriate and expected. Also, keep in mind that the WPF's SplashScreen class just displays a simple raster graphic file (e.g., .png), and those don’t scale automatically with DPI.

For your use case, you might consider implementing a custom splash screen using a WPF window. That would give you full control and allow for proper scaling, you could use an SVG image or provide different splash images for different DPI settings and show the appropriate one at runtime.

Alternatively (though generally not recommended), you could disable DPI awareness in your app entirely. This would make Windows "zoom" the splash screen and the rest of your app according to the system's DPI settings. Just note that this can lead to blurry visuals due to bitmap upscaling.

You can disable DPI awareness in your app by doing the following:

  1. Comment all the DPI-awareness relevant settings in the app manifest to disable them and write this in the app manifest: <dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">false</dpiAware>
  2. Add the DisableDpiAwareness attribute to the app assembly: [assembly: System.Windows.Media.DisableDpiAwareness]

Nimce avatar Apr 25 '25 10:04 Nimce

@mnissl I see, sounds like we were talking about slightly different issues.

Exactly: you wrote in the thread for issue 947 that you found a fix and referred to this issue here. But issue 947 is about that "WPF splash screen images are not scaled according to the DPI." So your fix presented here does not fix issue 947.

For me, this behavior with the manifest enabled is appropriate and expected.

Yes, it obviously fixes this issue 5070.

Also, keep in mind that the WPF's SplashScreen class just displays a simple raster graphic file (e.g., .png), and those don’t scale automatically with DPI.

Windows performs the scaling for DPI unaware apps. As WPF apps are DPI aware, one might expect that WPF's SplashScreen class is DPI aware, too.

For your use case, you might consider implementing a custom splash screen using a WPF window.

The idea of using the WPF's SplashScreen class is not to reinvent the wheel and to present the user with a splash screen immediately, not after WPF has started up after multiple seconds.

That would give you full control and allow for proper scaling,

This is what one expects the framework would do out of the box.

mnissl avatar Apr 25 '25 12:04 mnissl

@mnissl I see, sounds like we were talking about slightly different issues.

Exactly: you wrote in the thread for issue 947 that you found a fix and referred to this issue here. But issue 947 is about that "WPF splash screen images are not scaled according to the DPI." So your fix presented here does not fix issue 947.

I got your feedback - agreed, this does fix #5070 but not #947. I had originally commented on 947 because I see both tickets as pointing to the same underlying issue, but I've deleted that comment there to avoid further confusion.

Nimce avatar Apr 25 '25 13:04 Nimce