WPF單位真的與解析度無關嗎?

来源:http://www.cnblogs.com/lelehellow/archive/2017/07/12/7153922.html
-Advertisement-
Play Games

轉載自http://www.cnblogs.com/helloj2ee/archive/2009/04/21/1440709.htm WPF從發佈之日起,一直將“解析度無關(resolution independence)”作為其亮點,聲稱使用WPF製作的用戶界面在輕巧的Ultra-Mobile P ...


轉載自http://www.cnblogs.com/helloj2ee/archive/2009/04/21/1440709.htm

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


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...