关于WinForms的跨显示器DPI自适应

点击上方蓝字关注“汪宇杰博客”

640?wx_fmt=png

导语

WinForms 是运行在Windows上的传统.NET桌面应用技术框架。由于历史原因,它对高DPI以及跨不同DPI屏幕的支持有些问题,本文将探索尽可能的解决方案。

Windows 的“黑历史”

Windows 系统的默认DPI(更确切的说法叫 PPI)是96。PPI 的意思是 Pixels per inch,也就是每英寸屏幕显示多少像素的意思。这个值越高,表示屏幕的显示能力越细腻。

但也意味着,要显示物理尺寸和低PPI屏幕相同的画面,高PPI屏幕需要更多的像素来填充。对于一张非矢量图来说,这个问题不好解决,由于向高像素拉伸,这个图片会被“拉模糊”。类似的问题也发生在Windows中,特别是老程序,设计的时候只考虑了96 PPI。而这个历史原因可以在微软的这篇博客里找到详解:

https://blogs.msdn.microsoft.com/fontblog/2005/11/08/where-does-96-dpi-come-from-in-windows/

例:在150% DPI的屏幕上,Windows管理控制台(MMC)均会发生模糊。(可能在微信或网页里不明显)

而在100% DPI 的屏幕上,图像是清晰的。

640?wx_fmt=png

努力的 Windows 10

由于现在的电脑高分屏(HDPI)越来越多,Windows 10 每半年一次的 Feature Update 一直在努力解决 DPI 的问题。我们可以通过下图的设置搭配,解决很多老程序的DPI适配。但是很难做到跨屏幕DPI自适应。

640?wx_fmt=png640?wx_fmt=png

所谓跨屏幕DPI自适应(Per Monitor-DPI aware),意思就是当你的电脑有外接屏幕时,Windows会选择适配该屏幕的DPI来显示外接屏幕的图像。这个DPI很可能和你电脑的主屏幕是不一样的。例如,用 Surface Pro 外接一个 1920x1080 的22寸显示器,那么Surface的主屏幕通常是 150%以上DPI,而外接显示器是100%。

如果程序自己不支持 Per Monitor-DPI aware,那么你用Windows自带的兼容模式调整完,会发现虽然两个屏幕都是清晰的图像,但是应用界面在低DPI屏幕上会被放大。并不完美。所以最地道的解决方式,是开发支持 Per Monitor-DPI aware 的程序。

微软自己的应用也有这方面的改进。例如 Visual Studio 2019 开始已经天然支持 Per Monitor-DPI aware。(要求 Windows 10 v1803及.NET Framework 4.8)

640?wx_fmt=png

WinForms 能抢救吗

Windows桌面开发最native的三种技术分别是:WinForms、WPF、UWP。因为UWP诞生于现代,所以天生没有DPI适配问题。而WPF的XAML界面也可以轻松适配DPI。唯独 WinForms 历史包袱太重,不改是不行的。我们来试试能否抢救。

首先,我在VS2019中使用150% DPI的主屏幕,设计器视图不模糊,但按钮尺寸有问题,控件位置如下:

640?wx_fmt=png

留意红色箭头位置。在VS里一切正常。然而运行起来,在150% DPI的主屏幕是会模糊,并且控件错位。

640?wx_fmt=png

将窗口拖动到100% DPI的屏幕上,UI不模糊,但控件依旧错位。

640?wx_fmt=png

按照微软官网文档 https://docs.microsoft.com/en-us/dotnet/framework/winforms/high-dpi-support-in-windows-forms 的描述,.NET Framework 从4.7开始,改善WinForms的DPI支持。因此第一步,我将该程序的运行时改为4.7.2(Windows 10 1803以上版本自带)

在应用根目录加入一个 app.manifest 文件。

640?wx_fmt=png

取消注释其中的 assembly/compatibility/application 下的Windows 10 GUID。

<!-- Windows 10 -->

<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}" />

然后在 App.config 底下加入:

<System.Windows.Forms.ApplicationConfigurationSection>

  <add key="DpiAwareness" value="PerMonitorV2" />

</System.Windows.Forms.ApplicationConfigurationSection>

现在发现控件位置在150% DPI的主屏幕上正确显示,整个UI不模糊。

640?wx_fmt=png

但是在 100% DPI 的屏幕上,虽然UI不模糊,但是控件位置依然不正确,并且TextBox变的巨大无比。

640?wx_fmt=png

微软文档里没提别的方法。但是我发现将运行时改成.NET Framework 4.8 可以修复这个TextBox的爆,但是控件位置依然不正确。

640?wx_fmt=png

经过仔细观察,发生问题的并不是 TextBox、Label、Checkbox 这几个控件,而是 MonthCalendar 在100% DPI的屏幕上比 150% 的主屏宽。并且 Panel、TableLayoutPanel和Dock的组合拳都没法办法解决这个问题。

.NET Core 3.0 能解决吗?

.NET Core 3.0 目前还在preview 6阶段。从我实验的结果来看,它的DPI适配不需要App.config,而是在Program.cs里加入:

Application.SetHighDpiMode(HighDpiMode.PerMonitorV2);

但最终效果和以上的.NET Framework 4.8的效果是一样的,虽然跨DPI屏幕界面不会模糊,但是 MonthCalendar 的宽度问题依旧。

结论

在 Windows 10 v1903 上(其他版本我没试过),通过 .NET Framework 4.8 + app.manifest + app.config 的配置,可以一定程度上让 WinForms 具有 Per Monitor-DPI aware 的能力,但是部分控件的尺寸还是会不一样,因此发布程序之前需要仔细测试,保证UI可用性,再向用户提供跨屏幕DPI自适应支持。

我的样例程序代码:https://github.com/EdiWang/DotNet-Samples/tree/master/WinForms-DPI-PMA/PerMonitorAwareDPIForms

640?wx_fmt=gif

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/314766.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

.NET开发框架(九)-NLB网络负载平衡配置实战(视频)

&#xff08;NLB配置实战教程-有声视频-第二节&#xff09;请持续关注公众号&#xff0c;第三节&#xff08;NLBARR)正在录制中~第六章IIS负载均衡教程&#xff0c;至今共有37人参与学习尚未学习第六章-IIS负载均衡-视频教程的童靴&#xff0c;赶紧跟上进度&#xff0c;别掉队了…

C#各版本新增加功能

本系列文章主要整理并介绍 C# 各版本的新增功能。C#8.0 于 2019年4月 随 .NET Framework 4.8 与 Visual Studio 2019 一同发布&#xff0c;但是当前处于预览状态。预计在2019年9月正式发布。目前提供以下功能可供试用&#xff1a;Readonly 成员默认接口成员【*重要&#xff0c;…

宣告推出.NET Core 3.0 Preview 7

译&#xff1a;艾心0626今天&#xff0c;我们宣布推出.NET Core 3.0 Preview 7。我们已经从创建新特性阶段过渡到了完善版本阶段。对于接下来的预览版&#xff0c;我们将把重点放在质量(改进)上。在Windows&#xff0c;macOS和Linux上下载.NET Core 3.0 Preview 7。.NET Core 3…

基于Masstransit实现Eventbus的功能

Masstransit 是一个非常优秀的基于消息进行通信的分布式应用程序框架&#xff0c;详情参考官网。在介绍AA.ServiceBus之前&#xff0c;先介绍下几个概念.分布式分布式系统如何定义&#xff1f;这里引用一下Distributed Systems Concepts and Design(Third Edition)中的一句话&a…

微软解释为什么Rust是系统编程的最佳选择

上周&#xff0c;MSRC&#xff08;微软安全响应中心&#xff09;透露出拥抱 Rust 的打算&#xff0c;随后他们将这个话题扩展为一个系列&#xff0c;进一步阐述了使用安全的系统编程语言的的必要性&#xff0c;以及选择 Rust 的原因。在该系列最新一篇文章中&#xff0c;MSRC 团…

你可能不知道的Docker资源限制

本篇内容涉及Docker的内存与CPU限制&#xff0c;可以用于在实际开发中为指定容器设置限制最大使用的资源量&#xff0c;预计阅读时间为5分钟。01—What is 资源限制&#xff1f;默认情况下&#xff0c;容器是没有资源限制的&#xff0c;它会尽可能地使用宿主机能够分配给它的资…

东南亚的IT公司,我劝你善良!

来源公众号&#xff1a;半佛仙人&#xff08;ID&#xff1a;banfoSB&#xff09;“真的救我一条‘狗命’&#xff0c;可以吗&#xff0c;谢谢您了&#xff0c;我真的撑不住了。”5月3日&#xff0c;小巴在朋友圈看到这条信息&#xff0c;附着一张长图&#xff0c;定位&#xff…

小白开学Asp.Net Core 《九》

小白开学Asp.Net Core 《九》 — — 前端篇&#xff08;不务正业&#xff09;在《小白开学Asp.Net Core 三》中使用了X-admin 2.x 和 Layui将管理后端的界面重新布局了&#xff0c;里面简单的介绍了layui table 的使用以及页面table所需的数据做了简单的封装。今天扩展学习下。…

.net持续集成sonarqube篇之sonarqube安装与基本配置

Sonarqube下载与安装Sonarqube下载地址是:https://www.sonarqube.org/downloads/下载版本有两个,一个是长期支持版,另一个是最新版,此处安装的是最新版,目前版本是7.3,下载的时候点击醒目的蓝色按钮即可(此时下载的是社区版),下面有三个无底色按钮下载链接,分别对应的是开发者版…

Codeforces Round #296 (Div. 1) D. Fuzzy Search FFT匹配字符串

传送门 文章目录题意&#xff1a;思路&#xff1a;题意&#xff1a; n,m,k≤2e5n,m,k\le2e5n,m,k≤2e5 思路&#xff1a; 直接考虑fftfftfft来匹配字符串。 由于kkk是给定的&#xff0c;所以难度低了很多&#xff0c;普通的字符串匹配不能处理这种可以范围相等的情况&#xf…

迁移 WinForm 应用从 dotnet framework 到 dotnetcore3.0

迁移 WinForm 应用从 dotnet framework 到 dotnetcore3.0Intro微软从 dotnetcore3.0 开始已经开始支持 wpf 以及 winform 的开发&#xff0c;dotnet core 3.0 preview7 已经发布&#xff0c;官方称已经可以准备上生产了 Production Ready迁移这篇WPF的迁移还是比较不错的&#…

HDU - 6992 Lawn of the Dead 线段树 + 思维

传送门 文章目录题意&#xff1a;思路&#xff1a;题意&#xff1a; 给你一张n∗mn*mn∗m的图&#xff0c;其中有kkk个点不能走&#xff0c;你只能向下和向右走&#xff0c;问你能到达多少点。 n,m,k≤1e5n,m,k\le1e5n,m,k≤1e5 思路&#xff1a; 可以发现每个点如果其左边和…

EZNEW.NET开发框架100%重磅开源

EZNEW.NET是一套基于领域驱动开发(DDD)为指导思想的企业级项目通用开发框架。通过将当前主流的开发技术和最佳的开发实践相结合&#xff0c;将开发中常见且严重影响开发效率的繁琐技术细节进行了模块化的封装&#xff0c;让开发人员能将更多更多精力聚焦在系统业务的分析中去&a…

黑暗爆炸OJ 3028. 食物 生成函数

传送门 文章目录题意&#xff1a;思考题意&#xff1a; 思考 考虑将每个条件转换成生成函数&#xff1a; (1)f1(x)1x2...11−x2(1)f_1(x)1x^2...\frac{1}{1-x^2}(1)f1​(x)1x2...1−x21​ (2)f2(x)1x1−x21−x(2)f_2(x)1x\frac{1-x^2}{1-x}(2)f2​(x)1x1−x1−x2​ (3)f3(x)1x…

「Azure」数据分析师有理由爱Azure之一-Azure能带给我们什么?

前面我们以相同的方式从数据分析师的视角介绍了Sqlserver&#xff0c;本系列亦同样地延续下去&#xff0c;同样是挖掘数据分析师值得使用的Azure云平台的功能。因云平台功能太多&#xff0c;笔者所接触的面也十分有限&#xff0c;有更专业的读者欢迎补充。对云服务的一点点小认…

POJ - 3734 Blocks 指数生成函数

传送门 文章目录题意&#xff1a;思路&#xff1a;题意&#xff1a; 一段长度为nnn的序列&#xff0c;你有红黄蓝绿四种颜色的砖块&#xff0c;问你铺砖的方案数&#xff0c;每块砖长度为111&#xff0c;其中红黄颜色个数必须为偶数。 思路&#xff1a; 考虑多重集合排列数&…

理想化的DevOps团队里只需要有Dev就够了?

&#xff08;图片来源于网络&#xff09;几天前&#xff0c;本公众号发布的一篇译文列举了9种DevOps团队结构适用类型与7种反型&#xff08;点击查看原文&#xff09;。文章转发到朋友圈之后&#xff0c;很多DevOps同行留言&#xff08;吐槽&#xff09;了自己团队的现状&#…

hdu 1521 排列组合 多重集排列 + 指数生成函数

传送门 文章目录题意&#xff1a;思路&#xff1a;题意&#xff1a; 思路&#xff1a; 显然是多重集排列数&#xff0c;我们考虑构造指数生成函数&#xff0c;让后模拟一下多项式乘法即可啦。 由于存在分数&#xff0c;所以直接用doubledoubledouble即可。 //#pragma GCC opt…

架构杂谈《七》

容器VS虚拟机一、什么是虚拟机虚拟机&#xff08;Virtual Machine&#xff09;指通过软件模拟的具有完整硬件系统功能的、运行在一个完全隔离环境中的完整计算机系统。虚拟系统通过生成现有操作系统的全新虚拟镜像&#xff0c;它具有真实windows系统完全一样的功能&#xff0c;…

#3027. [Ceoi2004]Sweet 生成函数 + 组合数学

传送门 文章目录题意&#xff1a;思路&#xff1a;题意&#xff1a; 思路&#xff1a; 这个题显然可以容斥来写&#xff0c;刚学生成函数就来水一下。 对于每一堆iii我们写出其生成函数Fi(x)∑k0mi(1xx2...xmi)1−x1mi1−xF_i(x)\sum_{k0}^{m_i}(1xx^2...x^{m_i})\frac{1-x^{1…