Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/337.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 每个监视器的WPF ClickOnce DPI感知v2_C#_Wpf_Clickonce_Dpi - Fatal编程技术网

C# 每个监视器的WPF ClickOnce DPI感知v2

C# 每个监视器的WPF ClickOnce DPI感知v2,c#,wpf,clickonce,dpi,C#,Wpf,Clickonce,Dpi,我将设置这个问题并自己回答,这样其他人就可以轻松地搜索并找到正确的答案。我不得不用谷歌搜索数小时,并从多个来源编译最终结果 因此,问题是-如何在ClickOnce场景(特别是WPF、c)中启用每监视器v2 DPI感知? Win 10 Creators更新(1703)中添加了每监视器v2。众所周知,ClickOnce不支持app.manifest文件中声明的DPI感知功能。首先,任何想大声叫喊的人-默认情况下,每个监视器的目标.NET 4.6.2 DPI感知功能都是启用的-这根本不是真的。 在.N

我将设置这个问题并自己回答,这样其他人就可以轻松地搜索并找到正确的答案。我不得不用谷歌搜索数小时,并从多个来源编译最终结果

因此,问题是-如何在ClickOnce场景(特别是WPF、c)中启用每监视器v2 DPI感知?


Win 10 Creators更新(1703)中添加了每监视器v2。众所周知,ClickOnce不支持app.manifest文件中声明的DPI感知功能。

首先,任何想大声叫喊的人-默认情况下,每个监视器的目标.NET 4.6.2 DPI感知功能都是启用的-这根本不是真的。
在.NET 4.62中默认启用的是后台的样板代码——在Windows声明代码中非常讨厌的C++钩子,以支持对每个监视器DPI的认识。 您仍然必须通过app.manifest声明支持每监视器dpi感知,但ClickOnce不支持此功能。
(请注意,早期版本的.NET将不支持每监视器dpi感知,即使使用应用程序清单,除非您)

现在回答:

  • 确保您的项目目标是.NET 4.6.2。(最容易使用Visual Studio 2017进行此操作)
  • 在程序集属性中禁用DPI感知。相信我,稍后我们将在代码中重新启用它。为此,请打开项目属性节点下的AssemblyInfo.cs(展开SolutionExplorer内的扳手图标,通常位于右侧)。将以下代码添加到最后一行:
    [assembly:DisableDpiAwareness]
    。(这将需要一个
    using System.Windows.Media;
    语句,只需单击鼠标悬停在红色曲线上时出现的灯泡,然后添加建议的using语句)
  • 添加一个app.manifest文件,并声明支持Win 10和其他操作系统版本。右键单击SolutionExplorer->add->new item->Application manifest文件中的项目。打开创建的清单文件,在中间有一个带有OS版本的部分,取消对它们的注释: 不要取消对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,然后选择查看代码。然后添加以下代码:

    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
    事件和
    visualtreeheloper.GetDpi()
    方法


  • 享受:)

    在应用程序中声明的DPI感知。显示.NET 4.7.2功能之一

    @Marko-回答得好!但这里有一个小细节:如果您将WinForms与WPF混合,则必须添加WinForms配置。请更新你的答案,我没有足够的理由留下评论

    <System.Windows.Forms.ApplicationConfigurationSection>
         <add key="DpiAwareness" value="PerMonitorV2" />
    </System.Windows.Forms.ApplicationConfigurationSection>
    
    
    

    我试过了,除了应用程序内的滚动条(scrollviewer)无法缩放外,其他一切似乎都正常。你知道为什么吗?如果我通过清单声明V2支持,滚动条看起来很好,但当然部署中断。我已经验证了使用V2调用SetProcessDpiAwarenessContext是否成功。(windows 10,最新更新,目标为4.6.2)此解决方案是否适用于windows 7?它适用于windows 10 perfectlyWin 10 v1803,目标.NET 4.7.2确实适用于以下清单:
    PerMonitorV2,PerMonitor,System
    遗憾的是,这不适用于安装了.NET 4.7.2的服务器2008r2(也可能是Win 7),因为无法分析清单。