我将设置此问题并自行回答,以便其他人可以更轻松地搜索并找到正确的答案。我不得不google几个小时,并从多个来源编译最终结果......
所以问题是 - 如何在ClickOnce场景中启用Per-Monitor v2 DPI感知(WPF,特别是c#)?
在Win 10 Creators Update(1703)中添加了Per-Monitor v2。众所周知,ClickOnce不支持在 app.manifest 文件like this中声明的DPI感知。
答案 0 :(得分:4)
首先,任何想要喊出来的人 - 只需要针对.NET 4.6.2,默认情况下启用每台显示器DPI感知 - 这根本不是真的。
.NET 4.6.2中默认启用的是幕后的样板代码 - 窗口声明代码中非常讨厌的c ++钩子,以支持每个监视器的dpi感知。
您仍然必须通过app.manifest声明您支持每个显示器dpi感知,但ClickOnce不支持它。
(请注意,早期版本的.NET不支持每个监视器dpi感知,即使使用应用程序清单,除非您manually add the boilerplate code)
现在回答:
[assembly: DisableDpiAwareness]
。 (这需要using System.Windows.Media;
声明,只需点击悬停在红色波浪线上方时出现的灯泡并添加建议的使用声明)您现在需要在项目的某个地方使用以下c#代码,我建议为此创建一个新的静态类:
internal static class NativeMethods
{
[DllImport("user32.dll", SetLastError = true)]
internal static extern bool SetProcessDpiAwarenessContext(int dpiFlag);
[DllImport("SHCore.dll", SetLastError = true)]
internal static extern bool SetProcessDpiAwareness(PROCESS_DPI_AWARENESS awareness);
[DllImport("user32.dll")]
internal static extern bool SetProcessDPIAware();
internal enum PROCESS_DPI_AWARENESS
{
Process_DPI_Unaware = 0,
Process_System_DPI_Aware = 1,
Process_Per_Monitor_DPI_Aware = 2
}
internal enum DPI_AWARENESS_CONTEXT
{
DPI_AWARENESS_CONTEXT_UNAWARE = 16,
DPI_AWARENESS_CONTEXT_SYSTEM_AWARE = 17,
DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE = 18,
DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2 = 34
}
}
最后一部分是调用上面的p / invoke方法并声明dpi感知支持。我们需要在任何其他代码运行之前执行此操作。为此,右键单击 SolutionExplorer 中的 app.xaml ,然后选择View Code
。然后添加以下代码:
protected override void OnStartup(StartupEventArgs e)
{
if (Environment.OSVersion.Version >= new Version(6, 3, 0)) // win 8.1 added support for per monitor dpi
{
if (Environment.OSVersion.Version >= new Version(10, 0, 15063)) // win 10 creators update added support for per monitor v2
{
NativeMethods.SetProcessDpiAwarenessContext((int)NativeMethods.DPI_AWARENESS_CONTEXT.DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2);
}
else NativeMethods.SetProcessDpiAwareness(NativeMethods.PROCESS_DPI_AWARENESS.Process_Per_Monitor_DPI_Aware);
}
else NativeMethods.SetProcessDPIAware();
base.OnStartup(e);
}
确保其余代码正确处理DPI。从.NET 4.6.2开始,您可以使用OnDpiChanged
事件和VisualTreeHelper.GetDpi()
方法。
享受:)
答案 1 :(得分:1)
@Marko-很好的答案!但这是一个小细节:如果将WinForms与WPF混合使用,则必须添加WinForms配置。请更新您的答案,我没有足够的意思发表评论...
<System.Windows.Forms.ApplicationConfigurationSection>
<add key="DpiAwareness" value="PerMonitorV2" />
</System.Windows.Forms.ApplicationConfigurationSection>
引荐:https://docs.microsoft.com/en-us/dotnet/framework/winforms/high-dpi-support-in-windows-forms
答案 2 :(得分:0)
在app.manifest is claimed to be .NET 4.7.2功能之一中声明的DPI感知。