原文:论wpf的设备无关性 - 简书

WPF从发布之日起,一直将“分辨率无关(resolution independence)”作为其亮点,声称使用WPF制作的用户界面在轻巧的Ultra-Mobile PC的屏幕上和在50英寸的电视机上都能很好地显示。微软之所以称WPF具备“分辨率无关”这一特性,主要是因为WPF的坐标单位设计成为以1/96英寸为一个逻辑像素单位,而不是与设备相关的像素单位。

但是微软本身对WPF“分辨率无关”这一特性没有作更多的具体解释,导致用户会产生很多误解。

误解之一

改变显示器的分辨率设置,同一个WPF的用户界面和绘制的图形尺寸不会变化。

这个可以用一个非常简单的实验证明该结论是错误的。新建一个WPF应用程序窗口,其中高度为400DIUs(DIU:Device independent unit,设备无关单位),宽度为600DIUs,让这个窗口分别在分辨率设置为1280 * 1024和800*600的环境下运行,如下图所示,两个窗口的尺寸是明显不一样的。

 
 
 
 

图 1 左图为1280 * 1024分辨率,右图为800*600分辨率

误解之二

改变显示的DPI设置,同一个WPF的用户界面和绘制的图形尺寸不会变化。

显示的DPI设置,在XP系统下是通过右键——属性——设置选项卡——高级,可以调用出来,如下图所示:

 
 

图 2 显示属性DPI设置

这个也可以用同样的方法进行证明该结论是错误的。仍然是高度为400DIUs[1],宽度为600DIUs的窗口分别运行在96DPI和192DPI两种设置环境下。从下图也可以明显看出窗口的尺寸是不一样的。

 
 
 
 

图 3 左图为96DPI,右图为192DPI

在不同屏幕上,如果DPI设置相同,则同一个WPF的用户界面和绘制的图形尺寸不会变化。

在这个地方有必要对屏幕的DPI设置进行一下解释说明。DPI设置是指屏幕上每英寸多少个像素,比如当前设置为96DPI,即屏幕上96个像素为1英寸。一般的Windows XP系统有正常尺寸(96DPI)、大尺寸(120DPI)和自定义尺寸三种选项。既然WPF的坐标单位是以1/96英寸为一个逻辑像素单位,那么我们有理由相信,如果两个显示器的DPI设置是相同的,那么同一个WPF的用户界面和绘制的图形尺寸不会变化。很遗憾,这样的结论依旧是一个错误。

CalvinP.Schrotenboer 也用一个实验证明这是一个错误。实验环境如表 1,比如桌面LCD显示器实际屏幕宽度和高度(像素单位)为1600 x 1200,这个和普通的分辨率设置需要区分,这是显示设备的最大分辨率或者说是物理分辨率,即物理上该显示器屏幕上是1600 x 1200个像元,英文中又称这种分辨率为“native resolution(原生分辨率)”。由于两个屏幕物理尺寸也不一样,所以实际的物理DPI可以通过表中的计算公式得到。实际的物理DPI和操作系统的DPI设置是没有什么联系的。

表 1实验环境

在两个不同系统当中运行同一个WPF应用程序,该程序了绘制了一条长为384DIUs的直线,换算成英寸即为384/96= 4英寸。结果在两个系统当中的实际尺寸如下图所示:

 
 

图 4 上图实际尺寸为4.08英寸,下图实际尺寸为3.28英寸(CalvinP.Schrotenboer,2006)

问题出在哪儿了?

其实从表 1当中就能看出一些端倪,原因正是在于实际的物理DPI和操作系统设置的DPI不一致造成的。WPF无法知道当前使用设备实际的物理DPI为多少,相反通过操作系统的API函数获得操作系统的DPI值,然后简单地认为这就是实际的物理DPI值。比如在桌面LCD显示器上,实际一个物理像元的尺寸为1/94英寸,由于操作系统设置为96DPI,因此WPF还固执地以为一个实际的像元为1/96英寸,因此线段长度为1/94 * 384 = 4.08英寸。笔记本显示器实际一个物理像元的尺寸为1/117英寸,因此线段长度为1/117 * 384 = 3.28英寸。这个值和我们测量的结果正好相符。

那么我们有理由推测,如果将操作系统的DPI设置成实际的物理DPI,则能做到真正的“分辨率独立”,即在两个不同显示器上显示的线段长度都为4英寸,如图 5所示:

 
 
 
 

图 5 左图为桌面LCD显示器,将DPI设置成为94,右图为笔记本显示器,将DPI设置成为117

WPF的“分辨率无关”到现在为止已经是山高月小,水落石出。那么我们还要接着讨论另一个问题,在显示器上存在这样的问题,那么是否在打印机上也存在这样的问题呢?仍然可以用一个实验证明。同样绘制一个4英寸的直线,分别在DPI设置为96DPI和120DPI下进行打印,得到的打印结果尺寸相同。如下图所示:

 
 
 
 

图 6 左图为系统设置120DPI下打印结果,右图为系统设置96DPI下打印结果

结论

通过上面几个实验分析,我们可以得到如下两个结论:

(1)              WPF在打印得时候可以做到“分辨率无关”,即同一个WPF用户界面和绘制的图形尺寸在任何一台打印机上输出都是一致的;

(2)              当显示器实际象元的物理尺寸和系统设置的DPI保持一致的时候,WPF可以在显示器上做到“分辨率无关”,即同一个WPF用户界面和绘制的图形尺寸在任何一台显示器(实际象元的物理尺寸和系统设置的DPI保持一致)上输出都是一致的。反之则无法保证。

更多的讨论

“分辨率无关”这样一个概念,由于微软本身讨论得不多,的确容易造成误解。最为详细地讨论了WPF当中“分辨率无关”的是CalvinP.Schrotenboer 的一篇博文“Is WPF Really Resolution Independent?”。当然Charles Peztold也在自己的博客当中讨论过这个问题。另外在微软的论坛上StephenW,Charles Peztold等人也就WPF的“分辨率无关”和“设备无关”作了比较深入的讨论。

用户固然可以不理睬这些,但是对于一个程序员来说,尤其是一个正在做绘图程序的程序员,尤其尤其是一个还需要打印输出的绘图程序员,是需要清楚这其中细节的。而且了解细节本身也是一件很愉快的事情。

作者:yang13
链接:https://www.jianshu.com/p/5d56826d36e0
来源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。

论wpf的设备无关性 - 简书的更多相关文章

  1. 2000条你应知的WPF小姿势 基础篇<78-81 Dialog/Location/WPF设备无关性>

    在正文开始之前需要介绍一个人:Sean Sexton. 来自明尼苏达双城的软件工程师.最为出色的是他维护了两个博客:2,000ThingsYou Should Know About C# 和 2,00 ...

  2. c#字符串加载wpf控件模板代码 - 简书

    原文:c#字符串加载wpf控件模板代码 - 简书 ResourceManager resManagerA = new ResourceManager("cn.qssq666.Properti ...

  3. WPF 与设备无关的单位

    WPF从发布之日起,一直将“分辨率无关(resolution independence)”作为其亮点,声称使用WPF制作的用户界面在轻巧的Ultra-Mobile PC的屏幕上和在50英寸的电视机上都 ...

  4. WPF显示尺寸与设备无关问题

    WPF单位 WPF窗口以及其中的所有元素都是用与设备无关的单位进行度量.一个与设备无关的单位被定义为1/96英寸.WPF程序统一用下面一个公式来定义物理单位尺寸: [ 物理单位尺寸(像素)] = [ ...

  5. WPF概述(硬件加速及分辨率无关性)

    一.名词解释 WPF(Windows Presentation Foundation),直译为Windows表示基础,是专门用来编写程序表示层的技术和工具. 大部分程序都是多层架构的,一般至少包含三层 ...

  6. WPF 任务栏颜色 - 简书

    原文:WPF 任务栏颜色 - 简书 先看看效果,这种效果可以用来做进度条或者消息通知闪烁.   image.png   image.png   image.png   image.png 有一个好消息 ...

  7. WPF使用IDataErrorInfo接口进行数据校验 - 简书

    原文:WPF使用IDataErrorInfo接口进行数据校验 - 简书 class ValidationBindableBase : BindableBase, IDataErrorInfo { pu ...

  8. WPF之路-键盘与鼠标事件 - 简书

    原文:WPF之路-键盘与鼠标事件 - 简书 键盘事件 事件类型分为以下几个类型 生命周期事件:在元素加载与卸载的时候发生 鼠标事件:鼠标动作 键盘事件:键盘动作 手写笔事件:适用于win7以上的系统 ...

  9. WPF ControllTemplate Triggers小记 - 简书

    原文:WPF ControllTemplate Triggers小记 - 简书 WPF中,样式模板中如果定义EventTrigger事件方式实现动画.那么需要注意两点: 1.对于绑定的属性的Event ...

随机推荐

  1. [转载]解决/usr/bin/ld: cannot find -lxxx

    在linux环境编译应用程式或lib的source code时常常会出现如下的错误讯息: /usr/bin/ld: cannot find -lxxx 这些讯息会随着编译不同类型的source cod ...

  2. CF 149D Coloring Brackets(区间DP,好题,给配对的括号上色,求上色方案数,限制条件多,dp四维)

    1.http://codeforces.com/problemset/problem/149/D 2.题目大意 给一个给定括号序列,给该括号上色,上色有三个要求 1.只有三种上色方案,不上色,上红色, ...

  3. Java开源框架 iBase4J 搭建笔记

    项目地址:https://gitee.com/iBase4J/iBase4J 搭建步骤:     1.git 代码     2.安装 Zookeeper     3.打包部署 Dubbo Admin ...

  4. WCF与各语言通信框架比较

  5. COCOS2DX 3.0 优化提升渲染速度 Auto-batching

    COCOS2DX 3.0 优化提升渲染速度 Auto-batching 近期在看COCOS2DX 3.0的Auto-batching合批与Auto Culling动态缩减功能以下就来细致看看吧:整合好 ...

  6. Android学习笔记之ProgressBar案例分析

    (1) <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:to ...

  7. Bash脚本中的操作符

    一.文件測试操作符 假设以下的条件成立将会返回真. -e 文件存在 -a 文件存在 这个选项的效果与-e同样. 可是它已经被"弃用"了, 而且不鼓舞使用. -f 表示这个文件是一个 ...

  8. CXF WebService中传递复杂对象(List、Map、Array)

    转自:https://wenku.baidu.com/view/047ce58ed0d233d4b14e69eb.html 现在开始介绍传递复杂类型的对象.如JavaBean.Array.List.M ...

  9. 绘图中的drawRect

    rect参数:代表的是当前view的bounds 1 为什么要在drawRect方法里面写绘图代码 因为只有在这个方法中才能获取到当前view相关的图形上下文对象 有了这个图形上写文对象后才能进行绘图 ...

  10. C++ MAP使用

    1. map的构造函数map<int,string> maphai;map<char,int> maphai;map<string,char> mapstring; ...