Win32桌面程序為什么要適配高DPI

1674 人瀏覽 | 時間: 2016-12-14 20:21:40 | 作者: dybb8999

首先,DPI全名是Dots Per Inch 就是每英寸中像素點的個數。Windows中默認為96,這是很久很久以前Windows規定的。

那為什么DPI變了,就變模糊呢?是因為,原來DPI是100%的時候,每英寸96個像素,當你換了一個顯示器,顯示器大小沒變,但是從1366*768變成了1920*1080,如果系統還是按照每英寸96像素顯示窗口,那個窗口會變的非常小,所以就需要把系統的DPI從100%提升至125%,才能讓要顯示的東西變大一些讓我們看起來不會太累。

但是變大為什么就會變模糊呢?(這個例子我把DPI從125%提升到175%)

Windows有一個DWM(Desktop Window Manager) ,它會負責處理窗口的顯示。當你的DPI較高,而你的程序又不會自己處理的時候,它就會來幫助程序完成DPI適配。

首先假設你的DPI是200%,我們程序運行的時候,系統會告訴程序DPI是100%,然后程序就會繼續按照100%的方式來繪制窗口,這個坐標是縮小以后的(我們調用GetSystemMetrics(SM_CXSCREEN)會發現獲得的結果是經過處理的),當我們的程序繪制完成后,DWM再把整個窗口進行200%的放大(就像把一張小圖片放大),然后繪制到屏幕上,看起來就像程序支持高DPI一樣,但是結果就是會變模糊。

當我把DPI設置為175%,我們窗口獲取到的數據:

能看到我的屏幕X軸方向原來是1920像素,但是我們獲得的數據為1097(1920/1.75)

然后我告訴系統,我們的窗口會自動處理DPI縮放,不需要幫助:

可以看出,獲得的數據變回了正常的1920,獲取的DPI變為了168(1.75*96)

雖然說使用GetWindowRect()也能獲得經過縮放后的坐標,但是我沒成功- - 

Windows在Windows8.1和WindowsServer 2012 R2開始加入了一個API:SetProcessDpiAwareness 它負責告訴系統是否需要DWM的幫助。

HRESULT WINAPI SetProcessDpiAwareness(
  _In_ PROCESS_DPI_AWARENESS value );
typedef enum _PROCESS_DPI_AWARENESS { 
  PROCESS_DPI_UNAWARE            = 0,
  PROCESS_SYSTEM_DPI_AWARE       = 1,
  PROCESS_PER_MONITOR_DPI_AWARE  = 2 } PROCESS_DPI_AWARENESS;

PROCESS_DPI_UNAWARE 告訴系統改程序自己無法處理不同DPI,獲取的數據都是被處理過的。
PROCESS_SYSTEM_DPI_AWARE 告訴系統該程序會在啟動的顯示器上自己支持不同的DPI,但是如果程序被拖動到了其他DPI不一樣的顯示器上時,需要DWM的幫助。
PROCESS_PER_MONITOR_DPI_AWARE 告訴系統任何時候該程序都能適應不同的DPI,不需要任何幫助。

如果你的程序支持 PROCESS_PER_MONITOR_DPI_AWARE,當你的窗口移動到DPI不同的顯示器上時,會收到 WM_DPICHANGED 消息。

主要相關API:
SetProcessDpiAwareness :設置當前進程的DPI感知等級。
GetDpiForMonitor :查詢顯示的DPI。
MonitorFromPoint :獲取指定點的顯示器的句柄。
MonitorFromRect :獲取與指定矩形相交面積最大的顯示器句柄。

MonitorFromPoint和MonitorFromRect可以得到GetDpiForMonitor需要的句柄 

要讓我們的程序能適配高DPI,只需要告訴系統我們能自己處理,然后根據分辨率和DPI計算不同的數據應該就行了,文章的第一張圖我就是這樣做到的。

差不多就這些了╮(╯▽╰)╭

參考文檔:
關于Windows高DPI的一些簡單總結
Tutorial: Writing High-DPI Win32 Applications

標注
評論
站內搜
百度搜
傳送到手機
手機掃碼,識別文字,完成傳送x
加載中...
標注內容x
加載中...
添加標注x
收藏 0 點贊 0

相關閱讀

趣头条自媒体赚钱么 江苏11选5晚上几点结束 大发快三高手计划下载 钜派投资派客会 北京快中彩玩法说明 全国十大最安全的理财平台排名 秒速快3破解 北京赛车手机版 广东36选7开奖走势综合 福彩七乐彩2020023 宝牛e配资