[C#]WPF 解析度的無關性的問題

2023-07-27 12:13:57

什麼是WPF的解析度無關性?

首先得解什麼是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的真實尺寸是設定的畫素值 * 物理單位尺寸 。而給定的自定義控制元件屬性是並不會乘物理單位尺寸,也就是縮放情況下是顯示是正常的。

解決方法其實很簡單,在將框和定位點和長度除縮放值再除螢幕縮放值就可得到真實值。

而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%一致。

 

 

如有問題,歡迎批評指正。