我打算设置这个问题并自己回答,以便其他人可以更轻松地搜索并找到正确答案。我不得不谷歌数小时并从多个来源编译最终结果...
所以问题是 - 如何在 ClickOnce 场景(WPF,特别是 c#)中启用 Per-Monitor v2 DPI 感知?
在 Win 10 Creators Update (1703) 中添加了 Per-Monitor v2。众所周知,ClickOnce 不支持 app.manifest 文件中声明的 DPI 感知,like this .
最佳答案
首先,任何想要大声疾呼的人 - 只需以 .NET 4.6.2 为目标,每个显示器默认启用 DPI 感知 - 这根本不是真的。
.NET 4.6.2 中默认启用的是幕后样板代码 - 窗口声明代码中相当讨厌的 c++ Hook ,以启用对每个显示器 dpi 感知的支持。
您仍然必须声明您通过 app.manifest 支持每个监视器的 dpi 感知,但 ClickOnce 不支持它。
(请注意,早期版本的 .NET 不支持每个显示器的 dpi 感知,即使有应用程序 list ,除非你 manually add the boilerplate code )
现在回答:
- 确保您的项目面向 .NET 4.6.2。 (为此最容易使用 Visual Studio 2017)
- 在程序集属性中禁用 DPI 感知。相信我,我们稍后会在代码中重新启用它。为此,打开项目 Properties 节点下的 AssemblyInfo.cs(展开 SolutionExplorer 中的 Spanner 图标,通常位于右侧)。将以下代码添加到最后一行:
[assembly: DisableDpiAwareness]
。 (这将需要using System.Windows.Media;
语句,只需单击将鼠标悬停在红色波浪线上时出现的灯泡并添加建议的 using 语句) - 添加一个 app.manifest 文件并声明对 Win 10 和其他操作系统版本的支持。在 SolutionExplorer 中右键单击您的项目 -> 添加 -> 新项目 -> 应用程序 list 文件。打开创建的 list 文件,中间有一个包含操作系统版本的部分,取消注释: 不要取消对有关 DPI 感知的部分的注释(往下一点)!如果您这样做,ClickOnce 将抛出错误。
您现在需要在项目中的某处使用以下 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()
方法。
享受 :)
关于c# - WPF ClickOnce DPI 感知 Per-Monitor v2,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43537990/