首先得解什麼是Dpi(Density independent pixels ,裝置無關畫素),百度百科的解釋DPI是指每英寸的畫素,對應介面顯示即是螢幕上每英寸的畫素。
如標準的Windows DPI(96Dpi),代表1英寸96個畫素。
假設有一個96px*96px的按鈕,如果在標準標準的Windows DPI的情況下看起來就是英寸的大小,如果在其他Dpi的情況下假設為192Dpi,實際只需要將原來的96px*96px按鈕畫素大小翻倍即可。
而WPF就是通過改變畫素值來實現解析度無關,具體公式如下:
[物理單位尺寸]=[裝置無關單位尺寸]×[系統DPI]
其中裝置無關單位尺寸值和Windows DPI的尺寸是一樣的。上面那個例子變成公式就是
1/96英寸 * 192Dpi = 2px;而真實尺寸 = 設定的畫素值 * 物理單位尺寸 即 96px*2px = 192px;
提一下我遇到問題的情況,我寫了一個在圖片上定位然後顯示框的功能,然後那個框不是圖片上的,而是一個元件,需要的是將框和定位點和長度傳遞給顯示框。
圖片很大,圖片要適應程式的寬高,所以有個縮放值。然後圖片長寬除縮放值的即為渲染到介面圖片的大小。然後我想著計算出來框的定位點和長度,同理除縮放值就可以。
結果在我的電腦上執行正常,然後在其他電腦上執行,定位點和框大小都變大了。
最後測試是螢幕的縮放不同導致的。
對於圖片顯示在縮放後,WPF的真實尺寸是設定的畫素值 * 物理單位尺寸 。而給定的自定義控制元件屬性是並不會乘物理單位尺寸,也就是縮放情況下是顯示是正常的。
解決方法其實很簡單,在將框和定位點和長度除縮放值再除螢幕縮放值就可得到真實值。
而WPF中螢幕縮放值最簡單的獲取方法:
double screenscale = System.Windows.Forms.Screen.PrimaryScreen.Bounds.Width / SystemParameters.PrimaryScreenWidth;//windows double screenscale1 = NSScreen.MainScreen.Frame.Width/ SystemParameters.PrimaryScreenWidth;//MacOs
後面發現 其實WPF的解析度無關性並不是真正的解析度無關,當你將螢幕比例縮放後,它還是將各個控制元件都放大了
例如先在1080p解析度下建立一個WPF程式
介面設定為全螢幕化,只有兩個按鈕一個按鈕高1000,一個按鈕高80。
執行結果如下
然後改變縮放為125%
再執行結果如下
可以看到小按鈕被擠出螢幕了。同理,我遍歷button,然後將Button的大小除於縮放比例
private void StackPanel_Loaded(object sender, RoutedEventArgs e) { double screenscale = System.Windows.Forms.Screen.PrimaryScreen.Bounds.Width / SystemParameters.PrimaryScreenWidth; if (sender is StackPanel panel) { foreach (Button button in panel.Children) { button.Width /= screenscale; button.Height /= screenscale; } } }
最後樣式和縮放為100%一致。
如有問題,歡迎批評指正。