[转]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设置是没有什么联系的。

 

 

在两个不同系统当中运行同一个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设置为96DPI120DPI下进行打印,得到的打印结果尺寸相同。如下图所示:

 

图 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实验环境

 

实验环境

系统一

系统二

显示器类型

桌面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

 

 

 

参考文献

【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使用下面的公式进行计算:
     [物理单位尺寸] = [设备无关单位尺寸]×[系统DPI]

 

比如绘制一个96*96的按钮

 

(1)DPI为96
物理单位尺寸=1/96 inch * 96 DPI= 1 pixel.

那么我们的按钮占有多少个像素呢? 毫无疑问是96*96像素.
那么96像素是多大呢? 既然你的DPI是96,那么很容易就知道,那就是1 inch.

 

(2)DPI为120
物理单位尺寸=1/96 inch * 120 DPI= 1.25 pixel.

那么我们的按钮占有多少个像素呢? 1.25 pixel *96=120 。同样的按钮现在显示成120个像素了。
那么120个像素有多大? 由于DPI是120,很显然,这个尺寸就是1 inch。

 

因此, DPI为120的时候和DPI为96的时候,物理尺寸是一样的。

 

 

那么普通的Windows程序为什么做不到这一点呢?

因为普通的Windows程序使用的是设备相关的单位.

     当你在一个普通的Windows程序中指定一个按钮为96*96的时候,就意味着这个按钮的大小是96pixel*96pixel,无论系统的DPI是多少,其大小都是96pixel. 如果在一台DPI为96的显示器上,其尺寸就是96 pixel/96 DPI=1 inch. 而到了一台DPI为120的显示器上,就成了96 pixel/120 DPI=0.8 inch了.

     其本质区别就是,WPF中的尺寸是一个实实在在的物理尺寸,每一个单位就是1/96英寸.和任何设备都没有关系. 而普通的Windows程序中的尺寸,像素,是一个逻辑尺寸.一个像素到底有多大,还需要依靠设备来决定.

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值