1. 程式人生 > >WPF 不同DPI下,窗口大小的處理

WPF 不同DPI下,窗口大小的處理

his ble bsp 位置 location helper ren object 獲取

在設置桌面不同分辨率以及較大DPI下,窗口如何顯示的問題。(此例中僅設置高度)

前端:

  1. 設置窗口內容自適應SizeToContent="WidthAndHeight"
  2. 添加ViewBox -- 設置默認不拉伸Stretch="None",當DPI超大時如超過1920*1080p的175%(即win10默認不支持的比例顯示),開啟ViewBox縮放
  3. 頂層布局容器RootGrid添加高寬最大值和最小值。
 1 <Window x:Class="WindowHeightChangedForDpi.MainWindow"
 2         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation
" 3 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 4 xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 5 xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 6 xmlns:local="clr-namespace:WindowHeightChangedForDpi" 7 mc:Ignorable="d" 8
Title="MainWindow" SizeToContent="WidthAndHeight" WindowStartupLocation="CenterScreen"> 9 <Viewbox x:Name="RootViewbox" Stretch="None"> 10 <Grid x:Name="RootGrid" Width="1000" MaxHeight="680" MinHeight="520" ClipToBounds="True"> 11 12 </Grid> 13 </Viewbox> 14
</Window>

後臺:

  1. 添加對Loaded事件的監聽,並在之後註銷。窗口只需要首次初始其高度即可。
  2. 獲取屏幕的高度和任務欄的高度 -- 具體可以參考C# 獲取當前屏幕的寬高和位置
  3. 比較當前可顯示高度(屏幕高度-任務欄高度)與窗口的最大/最小高度,然後設置當前窗口的實際高度。
  4. 如果可顯示高度比最小值還小,則開啟ViewBox內容縮放。ViewBox的高度為當前可顯示高度。
  5. 如果當前窗口有陰影,可設置陰影高度大小。保證窗口在可顯示區域內正常顯示。
 1     public partial class MainWindow : Window
 2     {
 3         public MainWindow()
 4         {
 5             InitializeComponent();
 6             Loaded += InitWindowActualHeight_OnLoaded;
 7         }
 8 
 9         #region 設置窗口對屏幕高度的自適應
10 
11         private void InitWindowActualHeight_OnLoaded(object sender, RoutedEventArgs e)
12         {
13             Loaded -= InitWindowActualHeight_OnLoaded;
14             InitWindowActualHeight();
15         }
16 
17         private const double WindowShadowHeight = 0;
18 
19         private void InitWindowActualHeight()
20         {
21             //獲取任務欄高度
22             var taskbarHeight = SystemParameters.PrimaryScreenHeight - SystemParameters.WorkArea.Height;
23             //獲取窗體所在屏幕的高度
24             var height = GetScreenHeight();
25             var visibleAreaHeight = height - taskbarHeight;
26 
27             //可顯示高度 > 窗口最大高度
28             if (visibleAreaHeight > RootGrid.MaxHeight + WindowShadowHeight)
29             {
30                 //設置高度等於最大高度
31                 RootGrid.Height = RootGrid.MaxHeight;
32             }
33             //可顯示高度 < 窗口最小高度
34             else if (visibleAreaHeight < RootGrid.MinHeight + WindowShadowHeight)
35             {
36                 //設置Viewbox高度=可視高度-陰影高度(此處通過綻放顯示窗口,所以不能通過設置窗口或者設置內容的高度來實現)
37                 RootViewbox.Height = visibleAreaHeight - WindowShadowHeight;
38                 //等比例縮小
39                 RootViewbox.Stretch = Stretch.Uniform;
40             }
41             else
42             {
43                 //設置高度等於最小高度
44                 RootGrid.Height = RootGrid.MinHeight;
45             }
46         }
47         const double DpiPercent = 96;
48         private double GetScreenHeight()
49         {
50             var intPtr = new WindowInteropHelper(this).Handle;//獲取當前窗口的句柄
51             var screen = Screen.FromHandle(intPtr);//獲取當前屏幕
52 
53             double height = 0;
54             using (Graphics currentGraphics = Graphics.FromHwnd(intPtr))
55             {
56                 double dpiXRatio = currentGraphics.DpiX / DpiPercent;
57                 double dpiYRatio = currentGraphics.DpiY / DpiPercent;
58                 height = screen.Bounds.Height / dpiYRatio;
59                 //var width = screen.Bounds.Width / dpiXRatio;
60                 //var left = screen.Bounds.Left / dpiXRatio;
61                 //var top = screen.Bounds.Top / dpiYRatio;
62             }
63             return height;
64         }
65         #endregion

註:獲取的屏幕高度為屏幕像素,需要轉換為WPF單位。

WPF 不同DPI下,窗口大小的處理