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实验环境
|
实验环境 |
系统一 |
系统二 |
|
显示器类型 |
桌面LCD显示器 |
笔记本LCD显示器 |
|
屏幕宽度和高度 (像素单位) |
1600 x 1200 |
1400 x 1050 |
|
屏幕宽度和高度 (英寸单位) |
17.0 x 12.75 |
12.0 x 9.0 |
|
实际的物理DPI |
纵向:1600 / 17.0 = 94DPI 横向:1200 / 12.75 = 94DPI |
纵向:1400 / 12 = 117DPI 横向:1050 / 9 = 117DPI |
|
操作系统的DPI设置 |
96DPI |
96DPI |
在两个不同系统当中运行同一个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的“分辨率无关”和“设备无关”作了比较深入的讨论。
用户固然可以不理睬这些,但是对于一个程序员来说,尤其是一个正在做绘图程序的程序员,尤其尤其是一个还需要打印输出的绘图程序员,是需要清楚这其中细节的。而且了解细节本身也是一件很愉快的事情。
参考文献
【1】 CalvinP.Schrotenboer(2006), Is WPF Really Resolution Independent? http://www.wpflearningexperience.com/?p=41
【2】 StephenW, Charles Peztold,etc(2007), Resolution Independence?, http://social.msdn.microsoft.com/Forums/en-US/wpf/thread/33bdb15c-a04c-4c17-85e1-6c2802f80b90
转载自:http://www.cnblogs.com/helloj2ee/archive/2009/04/21/1440709.html
WPF 与设备无关的单位的更多相关文章
- 论wpf的设备无关性 - 简书
原文:论wpf的设备无关性 - 简书 WPF从发布之日起,一直将“分辨率无关(resolution independence)”作为其亮点,声称使用WPF制作的用户界面在轻巧的Ultra-Mobile ...
- 2000条你应知的WPF小姿势 基础篇<78-81 Dialog/Location/WPF设备无关性>
在正文开始之前需要介绍一个人:Sean Sexton. 来自明尼苏达双城的软件工程师.最为出色的是他维护了两个博客:2,000ThingsYou Should Know About C# 和 2,00 ...
- WPF显示尺寸与设备无关问题
WPF单位 WPF窗口以及其中的所有元素都是用与设备无关的单位进行度量.一个与设备无关的单位被定义为1/96英寸.WPF程序统一用下面一个公式来定义物理单位尺寸: [ 物理单位尺寸(像素)] = [ ...
- 第15章 设备无关位图_15.1 DIB文件格式
15.1 DIB文件格式(一种文件格式,扩展名为BMP) 15.1.1 OS/2风格的DIB 文件格式 字段 说明 文件头 (BITMAPFILEHEADER) 1.共14个字节 2.缩写建议用bmf ...
- device-independent bitmap (DIB) 设备无关位图
设备无关位图即独立于设备的位图(DIB)与"Device-Dependent Bitmaps (DDB) 设备相关位图"相比,它不再依赖于具体的设备,从而更适合在不同的计算机之间传 ...
- 第15章 设备无关位图_15.3 DIB和DDB的结合
第15章 设备相关位图_15.3 DIB和DDB的结合 15.3.1 从DIB创建DDB (1)hBitmap =CreateDIBitmap(…)——注意这名称会误导,实际上创建的是DDB 参数 说 ...
- 【笨嘴拙舌WINDOWS】设备无关图(*.bmp)
设备无关图在windows上面就是一个扩展名为.bmp的文件.我们知道每一种文件都是一个二进制流,只是这个二进制流的开头几个字节是规定了文件的格式..bmp的文件格式如下 “其中信息头是windows ...
- 第15章 设备无关位图_15.2 显示和打印DIB
15.2.1 探究DIB (1)DIB文件的结构 整个文件 紧凑DIB(整个文件除文件头) 文件头(File Header) 信息头(Information Header) 信息头(Informati ...
- 为C1Chart for WPF添加自定义标题、坐标轴单位标签以及旋转坐标轴注释
对于图表控件C1Chart for WPF,我们在添加数据,选择图表类型这些基本可视化数据展示后,经常需要通过标题.坐标轴单位标签等信息辅助说明图表对实际场景的意义.C1Chart for WPF并没 ...
随机推荐
- WCF服务库创建-20140919
1. 创建wcf服务库 2. 宿主到web程序上 // 宿主wcf服务库 RouteTable.Routes.Add(new ServiceRoute("ctserver.dll" ...
- 在 CentOS 下手工安装 Docker v1.1x
Docker在 centos 6.x 下面默认最新的版本是1.7, 然而这个并不符合我的实际需求, 尤其我需要 docker-compose 来作为编配工具部署swarm, 所以我只有手工安装了. 首 ...
- JavaScript筑基篇(二)->JavaScript数据类型
说明 介绍JavaScript数据类型 目录 前言 参考来源 前置技术要求 JavaScript的6种数据类型 哪6种数据类型 undefined 类型 null 类型 boolean 类型 numb ...
- a2
Alpha 冲刺报告 队名: 组长:吴晓晖 今天完成了哪些任务: 代码量300+,完成了百度地图API的引入. 展示GitHub当日代码/文档签入记录: 明日计划: 整理下这两个功能,然后补些bug ...
- # ML学习小笔记—Classification
关于本课程的相关资料http://speech.ee.ntu.edu.tw/~tlkagk/courses_ML17.html 通过模型可以分类输入,此时根据分类结果的正确与否会有一个Loss函数.找 ...
- android入门 — ListView点击事件
listView中提供了两种点击事件的处理方法,分别是OnItemClick和OnItemLongClick. OnItemClick提供的是点击操作的处理,OnItemLongClick提供的是长按 ...
- LintCode-67.二叉树的中序遍历
二叉树的中序遍历 给出一棵二叉树,返回其中序遍历. 样例 给出一棵二叉树 {1,#,2,3}, 返回 [1,3,2]. 挑战 你能使用非递归实现么? 标签 递归 二叉树 二叉树遍历 code /** ...
- MVC 枚举 转 SelectListItem
ViewBag.userlevel = new SelectList(Enum.GetNames(typeof(AdminLevels)),"", "", te ...
- asp.net mvc4中Json的应用
做一个简单的 Json实例,从页面获取后台的Json数据 1.控制台: public class HomeController : Controller { // // GET: /Home/ pub ...
- 新jQuery中attr 与 prop的不同
使用最新版本jquery,在对checkbox操作时发现 attr属性全选,反选等不起作用,后查发现新版本对标签属性的设置发生了变化. 在高版本的jquery引入prop方法后,什么时候该用prop? ...