【沧海拾昧】C# .NET8 WinForms程序在主显示器125%/150%缩放下尺寸显示异常的解决办法

#C0106


沧海茫茫千钟粟,且拾吾昧一微尘

------《沧海拾昧集》@CuPhoenix


【阅前敬告】 沧海拾昧集仅做个人学习笔记之用,所述内容不专业不严谨不成体系 【如有问题必是本集记录有谬,切勿深究】


问题

使用 C#(.NET8)进行 WinForms 程序开发时,如果主显示器的缩放比例不为100%,会出现窗体和控件显示尺寸异常的问题,网上通常的方案是在 Program.cs 中加入 SetProcessDPIAware(); 函数,但该函数可能对 .NET8 的 WinForms 程序无效。

c 复制代码
[STAThread]
    static void Main() {
        if (Environment.OSVersion.Version.Major >= 6) SetProcessDPIAware();
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        Application.Run(new Form1());             // Edit as needed
    }

    [System.Runtime.InteropServices.DllImport("user32.dll")]
    private static extern bool SetProcessDPIAware();

解决

通过参考 .NET8 的官方文档和 Git 手册,在 项目名.csproj 文件中(可以搜索 <Project Sdk = "Microsoft.NET.Sdk"> 找到该文件),将 <PropertyGrop></Property>中的内容修改为:

html 复制代码
<PropertyGroup>
  <OutputType>WinExe</OutputType>
  <TargetFramework>net8.0-windows</TargetFramework>
  <Nullable>enable</Nullable>
  <UseWindowsForms>true</UseWindowsForms>
  <ImplicitUsings>enable</ImplicitUsings>
  <ApplicationHighDpiMode>DpiUnawareGdiScaled</ApplicationHighDpiMode>
  <ForceDesignerDpiUnaware>true</ForceDesignerDpiUnaware>
</PropertyGroup>

说明

资料1WinForms GitHub 手册 - Designer HighDpi mode 中提到:

Issues

The Winforms designer, when operating in SystemAware/PermonitorV2 mode, serializes layout metrics into the > > source file based on the Dpi setting of the current display device on which it is being rendered. This may lead to two kinds of problems.

WinForms applications developed on a machine with DPI settings different from the machine where they are> > > executed may encounter layout inconsistencies.
Solution

html 复制代码
<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
   <OutputType>WinExe</OutputType>
   <TargetFramework>net7.0-windows</TargetFramework>
   <Nullable>enable</Nullable>
   <UseWindowsForms>true</UseWindowsForms>
    <ImplicitUsings>enable</ImplicitUsings>
    <ApplicationHighDpiMode>SystemAware</ApplicationHighDpiMode>
    <ForceDesignerDpiUnaware>true</ForceDesignerDpiUnaware>
  </PropertyGroup>

但该解决方案中设置的 <ApplicationHighDpiMode> 属性值是错误的,SystemAware 将查询主监视器的 DPI 一次,并将此值用于所有监视器上的应用程序,因此不能解决问题。

资料2.NET8 Learn - ApplicationHighDpiMode,通过微软官方的学习手册,查阅该属性值的取值。ApplicationHighDpiMode 可设置为 HighDpiMode 枚举值之一:

说明
DpiUnaware 应用程序窗口不会缩放 DPI 更改,并且始终假定比例系数为 100%。
DpiUnawareGdiScaled 类似于 DpiUnaware,但提高了基于 GDI/GDI+ 的内容的质量。
PerMonitor 此窗口会在创建 DPI 时对其进行检查,并在 DPI 更改时调整缩放比例。
PerMonitorV2 类似于 PerMonitor,但启用了子窗口 DPI 更改通知、comctl32 控件的改进缩放和对话框缩放。
SystemAware 如果未指定,则为默认值。窗口查询主监视器的 DPI 一次,并将此值用于所有监视器上的应用程序。

选择合适的取值(如 DpiUnawareGdiScaled)即可。

敬谢诸君。


相关推荐
工程师0078 小时前
C# 基于 HSL 与基恩士 PLC 通信
c#·mc协议·基恩士plc
张人玉12 小时前
c# DataSet 类
数据库·c#·dataset
秦苒&12 小时前
【C语言】详解数据类型和变量(一):数据类型介绍、 signed和unsigned、数据类型的取值范围、变量、强制类型转换
c语言·开发语言·c++·c#
一个帅气昵称啊12 小时前
.Net通过EFCore和仓储模式实现统一数据权限管控并且相关权限配置动态生成
.net·efcore·仓储模式
c#上位机12 小时前
C#异步编程之async、await
开发语言·c#
郑州光合科技余经理12 小时前
实战分享:如何构建东南亚高并发跑腿配送系统
java·开发语言·javascript·spring cloud·uni-app·c#·php
用户2986985301413 小时前
如何在 C# .NET 中将 Markdown 转换为 PDF 和 Excel:完整指南
后端·c#·markdown
天天进步201513 小时前
工厂模式的应用:数据读取与算法创建的解耦—— QuantConnect/Lean 源码分析系列二
c#
xiaowu08013 小时前
C# GetType的常规用法汇总
开发语言·c#
老朱佩琪!13 小时前
Unity桥接模式
unity·设计模式·c#·桥接模式