如何为.NET 8 WPF桌面应用配置PerMonitor DpiAwareness实现跨屏UI缩放?
.NET 6+ WPF 跨显示器自动DPI缩放完整实现
一、修正项目配置(*.csproj)
你之前设置的Switch.System.Windows.DoNotScaleForDpiChanges=true是阻止WPF自动处理DPI变化的核心原因,先将其改为false,同时添加高DPI模式配置:
<Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <OutputType>WinExe</OutputType> <TargetFramework>net6.0-windows</TargetFramework> <UseWPF>true</UseWPF> <!-- 启用Per-Monitor V2 DPI感知,实现跨显示器自适应 --> <ApplicationHighDpiMode>PerMonitorV2</ApplicationHighDpiMode> </PropertyGroup> <ItemGroup> <!-- 允许WPF自动处理DPI变化 --> <RuntimeHostConfigurationOption Include="Switch.System.Windows.DoNotScaleForDpiChanges" Value="false" /> <RuntimeHostConfigurationOption Include="Switch.System.IO.UseLegacyPathHandling" Value="false" /> </ItemGroup> </Project>
二、App.xaml 基础配置
保持Application的基础结构即可:
<Application x:Class="WpfDpiScaleDemo.App" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" StartupUri="MainWindow.xaml"> <Application.Resources> </Application.Resources> </Application>
三、App.xaml.cs 全局DPI兜底处理
在应用启动时确保DPI感知模式生效:
using System; using System.Windows; using Windows.Win32.PInvoke; namespace WpfDpiScaleDemo { public partial class App : Application { protected override void OnStartup(StartupEventArgs e) { // 兜底设置PerMonitorV2模式,避免项目配置未生效的情况 var currentProcess = System.Diagnostics.Process.GetCurrentProcess(); SetProcessDpiAwarenessContext(DPI_AWARENESS_CONTEXT.DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2); base.OnStartup(e); } } }
四、主窗口布局(MainWindow.xaml)
使用相对布局容器,避免固定像素尺寸,确保控件随DPI自适应:
<Window x:Class="WpfDpiScaleDemo.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="DPI自适应演示" WindowStartupLocation="CenterScreen"> <Grid Margin="20"> <StackPanel VerticalAlignment="Center" HorizontalAlignment="Center"> <TextBlock Text="跨显示器DPI自适应测试" FontSize="24" Margin="0 0 0 10"/> <Button Content="点击测试" Width="120" Height="40" FontSize="14"/> <TextBlock x:Name="DpiInfoText" Margin="0 10 0 0"/> </StackPanel> </Grid> </Window>
五、主窗口DPI事件处理(MainWindow.xaml.cs)
监听窗口DPI变化,更新UI状态:
using System; using System.Windows; using System.Windows.Media; namespace WpfDpiScaleDemo { public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); UpdateDpiInfo(); // 绑定DPI变化事件 this.DpiChanged += MainWindow_DpiChanged; } private void MainWindow_DpiChanged(object sender, DpiChangedEventArgs e) { UpdateDpiInfo(); // 自定义控件需要手动调整的逻辑可在此添加 } private void UpdateDpiInfo() { var dpiScale = VisualTreeHelper.GetDpi(this); DpiInfoText.Text = $"当前DPI缩放比例: {dpiScale.DpiScaleX:P0}"; } } }
关键注意事项
PerMonitorV2是WPF跨显示器自适应的最优模式,支持窗口在不同DPI显示器间移动时自动缩放。- 禁止使用固定Width/Height的布局方式,优先用Grid、StackPanel等相对布局容器,控件尺寸用
*或Auto。 - 字体大小尽量使用相对单位,WPF默认字体会自动随DPI缩放。
- 第三方控件需确保支持Per-Monitor DPI感知,否则可能出现缩放异常。
内容的提问来源于stack exchange,提问作者wpf
相关产品推荐
相关产品推荐

