SuRGeoNix/Flyleaf

FlyLeaf libraries and DPI challenges

Closed this issue · 7 comments

*Added: Regarding the issue below, when I add Application.SetHighDpiMode(HighDpiMode.SystemAware); into the main program it's all fine. The reason I hadn't done that was because it affects the layout of many of my other controls. It seems I'll have to bite the bullet and sort all that out. :(

I have incorporated the Flyleaf libraries into my app (wonderful!), but on publishing my app and running it on a screen that has greater than 100% scaling, I get some really weird issues:

  • Some buttons don't get triggered (they highlight as being hovered over, but click does not trigger the button event)
  • My startup splash screen starts in the correct DPI resolution (for the monitor), but when the form with the Flyleaf libraries loads, that splash screen displays in the smaller 100% form
  • I can also get the message 'failed to set win32 parent of the control' on opening a main form from the startup procedure

The issue only occurs after engine startup:
Engine.Start(new EngineConfig() { UIRefresh = true, FFmpegPath = ":FFmpeg", });
That is, without loading the libraries everything is good, but as soon as I uncomment the above section the issues occur.

I have moved this engine intialisation from the form constructor to OpenForm(), but that just delays the issue and causes the hosting form to switch resolutions and show at 100% rather than the 125% at which I have my display set.

Unfortunately this is a big deal for me as the app often needs to run on Surface Pro tablets running at 150%/200% scaling.
Have you seen this issue and is it resolvable?
My environment is C#, .Net8, Winforms
Thanks

@davsun55 Does the issue happens also locally before publishing during debugging if you set Zoom/DPI at your pc's display?
Sounds like each Window has different DPI awareness in your case (not even sure if that possible) that's why Application.SetHighDpiMode will fix this as it will make sure that all of them use the same logic.

Is it possible that you mix WinForms/WPF? Maybe it's Flyleaf's fault that this happens..

<UseWindowsForms>true</UseWindowsForms>
<UseWPF>true</UseWPF>

But again, I'm not sure and not easy to understand how .NET handles those related with the DPI awareness.

Yes - the issue does occur when debugging direct from VS. I already have true and adding UseWPF made no difference - I'm not sure if you're suggesting to add or make sure I don't have UseWPF?
After more research I have added EnableWindowFormsHighDpiAutoResizing=True to app.config. Now if I start the app with 100% scaling then switch to 200% it reformats perfectly. However when starting the app in 200%, many of the controls/fonts are not sized correctly and toggling 100%/200% doesn't help.
If you've got any guidance (although it's not your issue), I'd be very grateful. My issue is that my app is often run on a tablet, so there isn't a main or secondary screen that's running at 100%.
Would it be possible to have FlyLeaf not require the Application.SetHighDpiMode(HighDpiMode.SystemAware) statement?

Can you create a mini reproducible demo to have a better look? This might be related with windows settings (for the tablet).

@davsun55 I will close this but feel free to send more info to investigate more

FlyleafDemo.zip
I am resolved to having my app handle DPI changes better, but this zip demonstrates the issue. It's your demo but with the initialisation moved from constructor/form open to the button. If I don't have any version of this statement in program.cs Application.SetHighDpiMode(HighDpiMode.DpiUnaware); // SystemAware);, then when starting on a monitor at other than 100% scaling, the form looks fine, but after initialisation it is reduced to much smaller.
If I do have one of those statements included, then the form stays the same size.
As it stands, I need to go through all my forms and tweak the controls that don't handle DPI changes. It seems ListViews are one of the worst culprits.
I guess it would be nice if FlyLeaf initialisation didn't cause this effect, but I'm guessing that it needs to for other reasons???
:)

@davsun55 Found the issue, during the plugin's load event, even if it does not load anything at all (except embedded/default), just by iterating to the current assembly's types will cause dpi-aware enable (possible MS bug).

Line causes the issue

Same issue by another user

FYI the best solution I've found is:

  • Add <ForceDesignerDpiUnaware>true</ForceDesignerDpiUnaware> to the apps' .csproj file in the first <PropertyGroup> section - this allows the development environment to render forms correctly whatever the DPI
  • Add Application.SetHighDpiMode(HighDpiMode.DpiUnaware); to the startup object (NOT app.config as some suggest) - this causes the executing app to render forms correctly whatever the DPI

Notes:

  • HighDpiMode.SystemAware option: On app startup, control sizes are determined by primary screen, so stretching can occur when moved to a different DPI and/or resolution
  • HighDpiMode.PerMonitorV2 option: causes serious and compounding control layout issues when form is dragged between screens with different DPIs
  • HighDpiMode.DpiUnaware option: seems to work best - at least for me! The fonts are not as perfectly clear as 'SystemAware' but definitely good enough and better than the stretching that occurs otherwise.

Thanks for your work,
D