You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.NET 8 WinForms中Application.SetHighDpiMode()始终返回false求助

WinForms高DPI模式程序化修改失败问题

我正在测试优化WinForms应用显示渲染的方案,之前通过应用设置布尔值,启动时决定是否调用SetProcessDPIAware()。目前发现仅能通过在csproj文件的<PropertyGroup>中添加<ApplicationHighDpiMode>xxxx</ApplicationHighDpiMode>(xxxx可选值:DpiUnaware、SystemAware、PerMonitor、PerMonitorV2、DpiUnawareGdiScaled)修改渲染方式。

我希望通过代码程序化更改DPI处理逻辑,于是在Program.cs中添加了以下代码:

public static string DpiVal = "";

ApplicationConfiguration.Initialize();
<ApplicationHighDpiMode>DpiUnawareGdiScaled</ApplicationHighDpiMode>
HighDpiMode dpi = (HighDpiMode)Properties.Settings.Default.DpiMode;
Application.EnableVisualStyles();
bool status = Application.SetHighDpiMode(dpi);
DpiVal = string.Format("SetHighDpiMode({0}) returned {1}. Current HighDpiMode: {2}.", dpi, status, Application.HighDpiMode.ToString());
Application.Run(new Form1());

测试时在主窗体打印DpiVal,发现SetHighDpiMode始终返回false,HighDpiMode属性从未改变,示例输出:

SetHighDpiMode(PerMonitorV2) returned false. Current HighDpiMode: SystemAware.

根据文档说明,仅在清单(显式指定或通过csproj)设置HighDpiMode时该方法才返回false,但即使无清单或用默认清单(且csproj未设置ApplicationHighDpiMode),结果仍为false。

请问我操作有误吗?附加问题:如何在清单文件中指定ApplicationHighDpiMode?是否有类似csproj中<PropertyGroup>的特殊组?


问题解答

一、操作错误点

  • 代码混入非C#语法内容:ApplicationConfiguration.Initialize();之后的<ApplicationHighDpiMode>DpiUnawareGdiScaled</ApplicationHighDpiMode>是csproj的XML配置语法,不属于C#代码,不仅会引发编译错误,还会打乱DPI模式设置的执行顺序。
  • 方法调用顺序错误:Application.SetHighDpiMode必须在ApplicationConfiguration.Initialize()和Application.EnableVisualStyles()之前调用。因为ApplicationConfiguration.Initialize()内部会根据清单或csproj配置初始化高DPI模式,后续再调用SetHighDpiMode会被直接忽略,导致返回false。
    正确的代码顺序如下:
    public static string DpiVal = "";
    
    // 优先设置高DPI模式
    HighDpiMode dpi = (HighDpiMode)Properties.Settings.Default.DpiMode;
    bool status = Application.SetHighDpiMode(dpi);
    
    // 再执行初始化和样式启用
    ApplicationConfiguration.Initialize();
    Application.EnableVisualStyles();
    
    DpiVal = string.Format("SetHighDpiMode({0}) returned {1}. Current HighDpiMode: {2}.", dpi, status, Application.HighDpiMode.ToString());
    Application.Run(new Form1());
    
  • 默认清单的隐性配置:新版.NET的WinForms项目默认会启用SystemAware模式,即使你未手动修改csproj或清单,这个默认设置也会阻止SetHighDpiMode生效。解决方法是在csproj中显式设置<ApplicationHighDpiMode>DpiUnaware</ApplicationHighDpiMode>,或者在清单中不指定高DPI模式,给代码留出覆盖空间。

二、清单文件中指定ApplicationHighDpiMode的方法

应用清单文件(通常为app.manifest)中,需在<assembly>节点下的<application>节点内添加<windowsSettings>配置,没有类似csproj的<PropertyGroup>特殊组,具体格式如下:

<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
  <application xmlns="urn:schemas-microsoft-com:asm.v3">
    <windowsSettings>
      <!-- 基础高DPI设置 -->
      <dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true/PM</dpiAware>
      <!-- PerMonitorV2模式需额外添加此行 -->
      <dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">PerMonitorV2, PerMonitor</dpiAwareness>
    </windowsSettings>
  </application>
</assembly>

各模式对应的清单配置值:

  • DpiUnaware:<dpiAware>false</dpiAware>
  • SystemAware:<dpiAware>true</dpiAware>
  • PerMonitor:<dpiAware>true/PM</dpiAware>
  • PerMonitorV2:同时添加<dpiAware>true/PM</dpiAware>和<dpiAwareness>PerMonitorV2, PerMonitor</dpiAwareness>
  • DpiUnawareGdiScaled:<dpiAware>false/PM</dpiAware>

注意:若同时在csproj和清单中设置高DPI模式,csproj的配置优先级更高,会覆盖清单中的设置。

内容的提问来源于stack exchange,提问作者Borjan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 02:45:29