混合WPF和winforms项目DPI意识

时间:2016-01-20 13:01:26

标签: c# wpf winforms .net-4.6 highdpi

我有一个使用winforms和WPF的C#程序,我很难让它在高DPI环境中工作。 目前,如果我从解决方案中删除所有WPF项目并运行它,它将会很好地扩展,但是只要我重新添加任何wpf(功能必需),扩展就会失败并且UI变得无法使用。

这似乎与以前的SO问题完全相同:DPI Scaling in .Net 3.5 in Mixed WinForms and WPF ApplicationProblems getting WinForms to scale correctly with DPI

我遵循了有关这些问题的建议,并尝试添加清单文件和提供的dpi识别代码。

我还将项目升级到.net framework 4.6.1(从4.0开始)并包含了app.config设置:<add key="EnableWindowsFormsHighDpiAutoResizing" value="true" />

这确实影响了程序的主shell(所以不要在一个小窗口中加载所有控件压缩,主程序窗口打开最大化并显示正常)但是,当我输入任何winforms子窗体或插件时主窗口,缩放失败。

当我输入任何WPF子表单或插件,或返回主屏幕时,这些正确呈现。只有winforms功能无法正确扩展。

有没有人对如何让混合winforms / WPF项目在高DPI中正确扩展有任何想法?

提前致谢

4 个答案:

答案 0 :(得分:7)

当WPF加载到项目中时,它会将进程升级为System DPI Aware。为了解决这个问题,首先: 1)在条目程序集中的名称空间声明上方设置[assembly:DisableDpiAwareness]属性 2)您可以在项目中添加app.manifest文件并添加以下内容:

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

这应该使您的WinForms和WPF内容都在正确的目标DPI上。 (但如果您使用不同的DPI进行多显示器设置,则无法进行缩放)。

答案 1 :(得分:1)

我的同事终于解决了这个问题。由于配置设置等都不适用于此项目,我们尝试删除winforms shell并将其替换为WPF shell。一旦在WPF中重写了主shell项目,所有'插件'都出现在正确的DPI缩放中。

这不是我所知道的最好的解决方案,因为它涉及重写现有代码,但这是唯一为我们解决问题的方法。

答案 2 :(得分:0)

非常感谢您的回答@ rohit21agrawal!

我有一个非常类似的复杂Win Forms解决方案,每当我在WeifenLuo的DockPanelSuite中打开停靠的Form时,Form就会调整大小并弄乱整个GUI。

现在,经过几年尝试不同的方法(没有一种方法有效),您救了我的命!

除了您对所有其他开发人员的回答之外,想知道如何完成您的解决方案:

  1. a)(我的项目面向.NET Framework 4.7.2)
  2. b)(我所有的表单都设置为AutoScaleMode = Font)
  3. 在WinForms项目中,添加对WindowsBase的引用(应该是程序集列表中的倒数第三项)
  4. 在您的 AssemblyInfo.cs
  5. 中添加“ [assembly: System.Windows.Media.DisableDpiAwareness]
  6. 添加“
<application xmlns="urn:schemas-microsoft-com:asm.v3">
  <windowsSettings xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">
    <dpiAware>true/PM</dpiAware>
  </windowsSettings>
</application>

”放入 app.manifest 文件的父级“ <assembly>…</assembly>”部分

就我而言,这就像一种魅力:-) 最终,我能够在不同的显示器之间移动窗体(一个4K的比例为175%,另一个全高清的比例为125%),它可以立即重新绘制/重新渲染所有控件!

再次感谢您! 柯特

答案 3 :(得分:0)

如果您没有清单文件,因为您是 WinForms 应用程序而不是 WPF 应用程序,则必须通过 AssemblyInfo.cs 进行更改。因为它是相反的方向,您必须禁用 DPI 感知才能使世界同步,而不是像上述 WPF 方法那样启用它。

在 AssemblyInfo.cs 中,添加以下行。

[assembly: System.Windows.Media.DisableDpiAwareness]

我的问题被标记为重复,但不是真正的重复,因为我有一个使用 WPF 组件的 WinForms 应用程序,而不是相反。我正在为像我这样因错误原因被引导到这里的人添加这个答案。