Mixed WPF and winforms project DPI awareness
Asked Answered
H

4

12

I have a C# program that uses both winforms and WPF and I'm struggling to get it to work in high DPI environments. Currently, if I remove all WPF projects from the solution and run it, it will scale fine, however as soon as I add any wpf back in (necessary for the functionality) the scaling fails and the UI becomes unusable.

This seems like the exact same issue as previous SO questions: DPI Scaling in .Net 3.5 in Mixed WinForms and WPF Application and Problems getting WinForms to scale correctly with DPI

I followed the advice on these questions and tried adding a manifest file and the dpi aware code provided.

I also upgraded the project to .net framework 4.6.1 (from 4.0) and included the app.config setting: <add key="EnableWindowsFormsHighDpiAutoResizing" value="true" />

This did affect the main shell of the program (so instead of loading up in a small window with all the controls squished, the main program window opens maximised and appears normal) However, when I enter any winforms subform or plugin from the main window, the scaling fails.

When I enter any WPF subform or plugin, or return to the main screen, these render correctly. It is only the winforms features that are failing to scale properly.

Has anyone got any ideas on how to get mixed winforms/WPF projects to scale correctly in high DPI?

Thanks in advance

Hun answered 20/1, 2016 at 13:1 Comment(1)
If you think that would be a better approach, ok. I posted a new question as I presumed I have a different problem given that their fix did not work for me.Hun
M
10

When WPF is loaded into a project, it promotes the process to be System DPI Aware. In order to get around this, first : 1) set [assembly: DisableDpiAwareness] attribute above the namespace declaration in your entry assembly 2) you can add an app.manifest file in your project and add the following :

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

This should render your WinForms and WPF content both at the right target DPI. (This will however fail to scale if you have a multi monitor setup with different DPIs).

Mamoun answered 31/3, 2016 at 21:45 Comment(9)
This is an answer from the quoted question "#19552799" which I have stated did not work for me.Hun
@AnyaHope notice the difference. I have said you need to set <dpiAware> as true/PM not true. true/PM means Per Monitor Aware, while true means System DPI aware.Mamoun
Sorry, you're right. I hadn't noticed. Unfortunately at the time I was trying the <dpiAware> config setting I did try to use all of the different possible values and sadly none worked.Hun
@AnyaHope I am surprised it doesn't work. Another way to achieve this would be to set [assembly: DisableDpiAwareness] attribute in your entry assembly.Mamoun
Thank you very much for trying for me. I'll have a go with this one. I think the reason I'm having so much trouble getting it to work is because of the nature of the application I'm working on. It's a very complicated solution with dozens of 'plugin' projects. I'm sure I must be missing something.Hun
Nope, not at all. This project has been shelved for a while as other things have become more important. I think due to the complexity of the solution I'm working with, there's not going to be a single line fix. I will probably have to do this manually.Hun
I finally got around to looking at this again. I owe you an apology for being a complete idiot. I'd been putting the '[assemby: DisableDpiAwareness] attribute in the wrong place. When I placed it above the namespace in my entry class, it has fixed the problem completely. I wish I could afford a bounty retrospectively.Hun
I have not had the same success as @AnyaHope. I have a Windows Forms app, targeting .NET 4.6.1. Regardless of where I put [assemby: DisableDpiAwareness], even in AssemblyInfo.cs, it's not having any sort of visual effect on my app. I used the same settings in the manifest, and even added the EnableWindowsFormsHighDpiAutoResizing settings to app.config. An actual working demo somewhere on GitHub would be great.Encrata
That's an excellent idea. I'm sorry you haven't had any success with this yet. Would you like to create an example project on GitHub similar to your project? There are enough people on here that hopefully one of us will be able to get it up and running for you :)Hun
T
4

If you do not have a manifest file because you are a WinForms app and not a WPF app, you have to go through AssemblyInfo.cs to make the change. Because it's in the opposite direction, you have to DISABLE DPI awareness to get the worlds in sync, rather than ENABLE it like the above WPF approach.

In AssemblyInfo.cs, add the following line.

[assembly: System.Windows.Media.DisableDpiAwareness]

My question was marked as a duplicate of this, but is not a true duplicate because I have a WinForms app using a WPF component, not the other way around. I am adding this answer for people like me who get directed here for the wrong reason.

Text answered 16/6, 2021 at 17:21 Comment(2)
My project was exactly this when I started. Winforms base, WPF components, so I'm really glad this is here for others in the same situation. Thanks for postingHun
thank you so much! spent 3 hours with all the app.manifest and config settings and nothing was working. just removed all of that and simply added this and now magically the app scales correctly. thanks so much for posting. just to be clear, my app was a win form app with some WPF controls in it.Montgomery
H
2

My colleague finally worked this one out. As none of the config settings etc would work for this project, we attempted to remove the winforms shell and replace it with a WPF shell. Once the main shell project was re-written in WPF, all the 'plugins' appeared in the correct DPI scaling.

Not the best fix I know considering it involves a re-write of existing code, however this was the only thing that sorted the problem for us.

Hun answered 30/6, 2016 at 10:9 Comment(0)
V
0

Thank you so much for your answer @rohit21agrawal!

I had a quite similar complex Win Forms solution that whenever I opened a docked Form within WeifenLuo's DockPanelSuite, the Form resized and messed-up the whole GUI.

Now, after a couple of years trying different approaches (and none of them working) you saved my life!

In Addition to your answer for every other developer out there wondering how to accomplish your solution:

  1. a) (My projects target .NET Framework 4.7.2)
  2. b) (all my forms are set to AutoScaleMode = Font)
  3. In your WinForms Project, add a Reference to WindowsBase (should be the third last entry in the list of Assemblies)
  4. Add "[assembly: System.Windows.Media.DisableDpiAwareness]" to your AssemblyInfo.cs
  5. Add "
<application xmlns="urn:schemas-microsoft-com:asm.v3">
  <windowsSettings xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">
    <dpiAware>true/PM</dpiAware>
  </windowsSettings>
</application>

" into the parental "<assembly>…</assembly>" section of your app.manifest file

In my case, that worked like a charm :-) Eventually I am able to move the Form between different Displays (one 4K with 175% and another Full HD with 125% Font Scale) and it immediately redraws/re-renders all controls!

Again, thank you very much! Cordt

Visigoth answered 3/11, 2019 at 10:41 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.