在很久很久以前,WPF 诞生之初,有一个神奇的单位,它的名字叫做——设备无关单位(DIP,Device Independent Unit)。微软给它描绘了一片美好的愿景——在任何显示器上显示的尺寸是相同的。

What the ** is this unit!!! 神 TM 相同!!!

UWP 采用有效像素(Effective Pixels)来描述尺寸,这是才是能够自圆其说的一套尺寸描述;WPF 的尺寸机制与 UWP 完全就是同一套,使用有效像素才能解释 WPF 尺寸变化上的各种特性!


 

统一概念

在继续讨论之前,我们必须统一几个概念。不能说那些意义不明确的词,尤其是“宽高”“大小”“尺寸”“更大”。试想你说一个按钮的宽高是 200,那么它的宽高到底是多少呢?一个屏幕上的按钮和另一个屏幕上的按钮哪个更大呢?

在本文中,对于尺寸,我们只说三个概念:

  • 物理尺寸(单位:厘米)
  • 显示器像素个数(单位:个)
  • 有效像素(即 WPF 中最常用的那个单位;在本文结束之前,这应该是一个未定义的概念)

如果我们说 A 按钮比 B 按钮的物理宽度更大,那么无论它们显示在哪个显示器上,都具备相同的关系——因为我们可以拿尺子来量。

如果我们说 A 按钮比 B 按钮在宽度上占用的显示器像素个数更多,我们也可以拿放大镜去屏幕上一个点一个点地数——当然,各种截图工具已经在最佳分辨率下具备数像素个数的功能了(这里一定要突出最佳分辨率)。

而有效像素(Effective Pixels,本文记其为 epx)就是本文从 UWP 中引入的尺寸概念。当我们说按钮的有效像素宽度为 200 时,指的是你在 WPF 的 XAML 或 C# 代码中写下了 Width="200"

接下来,当我们谈论尺寸时,只会用以上三个概念进行比较,而不会再用模糊不清的尺寸名词。


从愿景看有效像素的意义

有效像素单位的诞生一定是为了解决某种尺寸问题,而且是因为现有的尺寸单位无法简单地描述这一问题。而我们就要准确描述这一问题,并将得到的单位定义成“有效像素”。

吐槽 DIP

WPF 曾经说自己用的是“设备无关单位”(DIP),愿景是在所有显示器上显示的物理尺寸相同。比如你在代码中写了 Width="96" 的按钮,那么在所有显示器上其尺寸为 1 英寸。

其实简单测试就不难发现这是一个根本无法自圆其说的愿景,具体无法自圆其说的点有两个。

  1. WPF 说自己的开发无需考虑 DPI 缩放,因为它会自己做缩放。那么当你写下 Width="96" 时,到底缩放还是不缩放呢?缩放就迁就了 DPI 缩放的特性,违背了物理尺寸相同的特性;不缩放就迁就了物理尺寸相同的特性,丢失了 DPI 缩放的特性。
  2. 在非 PC 设备(手机、平板电脑、大屏幕电视)上,如果依然保持物理尺寸相同,那么 PC 上显示合适的 3cm 的按钮在手机上将占据大半个屏幕,在电视上将小得几乎看不见。怎么能让一个 UI 框架做出这么脑残的设计呢?

#### 有效像素(epx)的愿景 有效像素概念的出现,就摒除了 WPF 物理尺寸相同这样荒谬而无法自圆其说的设定。但为了给有效像素设下定义,我们来看看微软到底期望这样的尺寸单位带来哪些方便吧:

▲ 如果此处看不到视频,请前往 Channel 9 观看:Designing Universal Windows Platform apps

具体说来,对于手机和平板电脑(笔记本、Surface)这些近距离观看的设备,其物理尺寸可以更小;对于客厅摆放的大屏幕电视,观看距离较远,物理尺寸应该更大。相同的界面元素在不同设备上显示时,呈现出来的效果在视野角度上是相近的,这才是人眼观看比较舒适的尺寸概念的设计。


▲ 图片来自于微软 UWP 设计指导文档 Introduction to Universal Windows Platform (UWP) app design (Windows apps)

可以看出,有效像素的出现解决了我在 以上吐槽 中列举出无法自圆其说的第 2 点。认识到一个优秀的屏幕显示单位并不是按物理尺寸定义,而是根据不同的使用场景有所不同。第 1 点也部分得到了缓解——接受 DPI 缩放的特性,放弃承认物理尺寸相同的设定。

有效像素(epx)的局限性

一个好的概念除了要充分展示自己的愿景,也要看清自己的局限性。

而有效像素的局限性就在于——它的愿景只是理想状态下才能有的效果,而微软本身允许硬件厂商和用户进行设置以偏离理想状态。

具体是这样的:

  1. 显示器厂商为了自己的销售目标,会推出各种各样的型号——有高端的,有低端的,有主打性价比的。而性价比的主要来源就是——“噱头”——在部分参数上非常漂亮,部分参数却缩水严重。比如同样是 34 寸的 21:9 超宽屏显示器,5999 元的可以是 3440×1440 像素个数,而 3999 元的就只能是 2560×1080 像素个数。前者每英寸像素点数接近 96,而后者则低多了。Windows 操作系统上支持的最低 DPI 设置只能是 96 了,不能再低;以至于后者实际上在相同观看距离上比前者显示的界面元素的物理尺寸会大很多。这是硬件厂商的销售策略,你一个虚拟的单位还能拿它怎么样!
    这其实是此愿景不能实现的最主要原因了——各大显示器厂商都存在不按照最佳观看效果设置显示器参数的问题。这也是为什么我们经常能发现有些笔记本上的图标和字体大小被默认设置得小得可怜,或者超大屏幕设备上文字小得远处看不清的原因。(这里我们只谈显示器厂商在 EDID 信息中设置的最佳时序,这个时序欺骗了操作系统使之给出了不合适的显示效果;不要说用户可以改的问题,毕竟让用户改已经提高了门槛了。)

  2. 用户可以随时修改屏幕显示分辨率,修改系统或屏幕的 DPI 值。在显示分辨率与显示器实际物理分辨率不一致的情况下,用户还能设置画面的填充方式(居中或是拉伸)。
    我们认为,用户主动设置 DPI 是出于自己的一些目的——希望放大或缩小界面元素,而这有可能是因为原有大小对用户自己来说看起来不够舒适。(这里不想吐槽设置分辨率还不设置为居中显示的用户,那种画面模糊的感觉,怎么能承受!)

事实上,目前为止,只有一款设备真正达到了微软期望中的理想状态,那就是——Surface Studio!其它都只能算作接近,或者连接近都算不上。

给有效像素下个定义

结合微软对有效像素的愿景,结合实际情况,我认为“有效像素”的定义应该是这样的:

在理想状态下,1 有效像素等于用户观看距离 50cm 时,观看屏幕上 1/96 英寸的物理距离所对应的视角大小
非理想状态下,1 有效像素等于显示器点对点显示像素时,1 屏幕像素乘以系统 DPI 值除以 96

WPF 和 UWP 的尺寸单位都可以用有效像素来理解,而这本身就是它们两个框架内建的单位系统。(彻底抛弃那个不能自圆其说的 DIP 吧!)

有效像素的特性

在以上定义之下,再研究有效像素的特性时,我们便能接受那些非理想状态下的不同行为,不再像 WPF 的 DIP 那样绝对而富有争议。

按钮的大小之争

当我们在代码中写下 Width="96" 时,这个按钮到底多大?

谈物理尺寸:

  • 在 Surface Studio 这样的理想设备上,如果用户没有胡乱设置,它的物理宽度是 1 英寸;
  • 在同一个显示器设备上,如果显示器的 PPI 是 96 pixels/inch,且用户使用最佳分辨率
    • DPI 值设置为 96,则它的物理宽度是 1 英寸
    • DPI 值设置为 144,则它的物理宽度是 1.5 英寸
    • DPI 值设置为 192,则它的物理宽度是 2 英寸
  • 在以上情况下,如果 DPI 值固定为 96,但用户降低了分辨率
    • 居中点对点显示,则它的物理宽度是 1 英寸
    • 拉伸显示,则它的物理宽度大于 1 英寸
  • 换一台显示器,PPI 值更大,则相同情况下的每一种情况都比以上物理宽度更小

谈显示器像素个数:

  • 用户使用了最佳分辨率

    • 在 DPI 值为 96 时,显示完按钮宽度所用的屏幕像素个数为 96
    • DPI 值设置为 192 时,则显示完按钮宽度所用的屏幕像素个数是 192
  • 在以上情况下,如果用户降低了分辨率
    • 居中点对点显示,显示完按钮宽度所用的屏幕像素个数为 96
    • 拉伸显示,显示完按钮宽度所用的屏幕像素个数大于为 96,虚拟的系统像素个数依然等于 96

接受现实

看看按钮实际的大小,你会发现,影响因素真的太多太多了!当我们不再沉浸在 DIP 的理想中,不再纠结有效像素的愿景的时候,便能觉得有效像素其实为我们考虑 DPI 缩放问题做了不少努力,确实能减轻我们 UI 的开发工作量。

将 UWP 的有效像素(Effective Pixels)引入 WPF的更多相关文章

  1. WindowsXamlHost:在 WPF 中使用 UWP 控件库中的控件

    在 WindowsXamlHost:在 WPF 中使用 UWP 的控件(Windows Community Toolkit) 一文中,我们说到了在 WPF 中引入简单的 UWP 控件以及相关的注意事项 ...

  2. 【广州.NET社区推荐】【译】Visual Studio 2019 中 WPF & UWP 的 XAML 开发工具新特性

    原文 | Dmitry 翻译 | 郑子铭 自Visual Studio 2019推出以来,我们为使用WPF或UWP桌面应用程序的XAML开发人员发布了许多新功能.在本周的 Visual Studio ...

  3. 【译】Visual Studio 2019 中 WPF & UWP 的 XAML 开发工具新特性

    原文 | Dmitry 翻译 | 郑子铭 自Visual Studio 2019推出以来,我们为使用WPF或UWP桌面应用程序的XAML开发人员发布了许多新功能.在本周的 Visual Studio ...

  4. WPF 获取元素(Visual)相对于屏幕设备的缩放比例,可用于清晰显示图片

    原文:WPF 获取元素(Visual)相对于屏幕设备的缩放比例,可用于清晰显示图片 我们知道,在 WPF 中的坐标单位不是屏幕像素单位,所以如果需要知道某个控件的像素尺寸,以便做一些与屏幕像素尺寸相关 ...

  5. [UWP]XAML中的响应式布局技术

    响应式布局的概念是一个页面适配多个终端及不同分辨率.在针对特定屏幕宽度优化应用 UI 时,我们将此称为创建响应式设计.WPF设计之初响应式设计的概念并不流行,那时候大部分网页设计师都按着宽度960像素 ...

  6. 从淘宝 UWP 的新功能 -- 比较页面来谈谈 UWP 的窗口多开功能

    前言 之前在 剁手党也有春天 -- 淘宝 UWP ”比较“功能诞生记 这篇随笔中介绍了一下 UWP 淘宝的“比较”新功能呱呱坠地的过程.在鲜活的文字背后,其实都是程序员不眠不休的血泪史(有血有泪有史) ...

  7. [UWP]创建自定义VisualState Trigger

    这篇博客将介绍在UWP程序中如何创建和使用自定义VisualState Trigger. 上一篇博客中介绍了如何使用AdaptiveTrigger.目前UWP内置的StateTrigger只有Adap ...

  8. [UWP]UWP中获取联系人/邮件发送/SMS消息发送操作

    这篇博客将介绍如何在UWP程序中获取联系人/邮件发送/SMS发送的基础操作. 1. 获取联系人 UWP中联系人获取需要引入Windows.ApplicationModel.Contacts名称空间. ...

  9. WPF The Hard Way

    WPF The Hard Way Windows Presentation Foundation (WPF) 是微软下一代显示系统,用于生成能带给用户震撼视觉体验的 Windows 客户端应用程序.  ...

随机推荐

  1. oracle sql - remove a user's all objects

    DECLARE TYPE cst_table_list IS TABLE OF VARCHAR2(40); TYPE cst_list IS TABLE OF VARCHAR2(40); TYPE n ...

  2. codeforces291E Tree-String Problem

    本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作. 本文作者:ljh2000 作者博客:http://www.cnblogs.com/ljh2000-jump/ ...

  3. 在Web API 2 中实现带JSON的Patch请求

    译文:http://www.cnblogs.com/kexxxfeng/p/the-patch-verb-in-web-api-2-with-json.html 原文:https://carly.io ...

  4. 启用/禁用以太网的批处理,用于一个网卡切换本地网络和wifi使用(Win10)

    注意下面时英文版上默认网络使用,同时接入了网线和wifi时,本地网络优先wifi. 所以禁用本地网络就会自动连接到wifi,启用本地网络,就会禁用wifi. 批处理支持 -y 参数,跳过用户输入y,代 ...

  5. HDU 2492 BIT/逆序数/排列组合

    Ping pong Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total S ...

  6. day24 Restful api 设计和CRM 客户关系管理

    博客: Restful: http://www.cnblogs.com/alex3714/articles/6808013.html http://www.cnblogs.com/alex3714/a ...

  7. 2793 [Poi2012]Vouchers

    我们直接模拟就可以了= = now[x]表示x的倍数已经取到x * i了,于是每次读入x,直接向上枚举x个没取过的数即可. /************************************* ...

  8. 用U盘安装ubuntu

    用U盘安装操作系统,并不鲜见,对于Windows,可以用大白菜安装XP.Win7等,本质上是在U盘上安装一个小型的windows(WinPE),然后利用ghost一键还原技术,把U盘中的XP.gho( ...

  9. LINUX系统下的shell命令---grep、sed、awk

    1)grep文本过滤命令 1.grep基本认识 (Global  search  regular expression and  print  out the  line全局搜索研究正则表达时并显示出 ...

  10. recovery.conf文件详解

    在恢复过程中,用户可以通过使用recovery.conf文件来指定恢复的各个参数,如下: 归档恢复设置 restore_command:用于获取一个已归档段的XLOG日志文件的命令 archive_c ...