名称: wpf高dpi分析器 描述: 分析和修复WPF应用程序的高DPI支持、每显示器DPI感知和缩放问题 允许工具: 读取、搜索、全局匹配、Bash 标签: [wpf, dpi, 缩放, 无障碍, windows]
wpf高dpi分析器
分析和修复WPF应用程序的高DPI支持。此技能识别DPI相关问题,并为高分辨率显示器上的每显示器DPI感知、位图缩放和布局问题提供修复方案。
能力
- 检测DPI感知配置问题
- 查找硬编码像素值
- 识别位图缩放问题
- 检查每显示器DPI支持
- 分析变换和布局问题
- 审查app.manifest DPI设置
- 生成常见DPI问题的修复方案
- 测试多显示器DPI场景
输入模式
{
"类型": "对象",
"属性": {
"项目路径": {
"类型": "字符串",
"描述": "WPF项目的路径"
},
"目标DPI模式": {
"枚举": ["系统", "每显示器", "每显示器-v2"],
"默认": "每显示器-v2"
},
"检查类别": {
"类型": "数组",
"项": {
"枚举": ["清单", "硬编码像素", "位图", "布局", "变换", "字体"]
},
"默认": ["清单", "硬编码像素", "位图", "布局"]
},
"生成修复": {
"类型": "布尔值",
"默认": true
}
},
"必需": ["项目路径"]
}
输出模式
{
"类型": "对象",
"属性": {
"成功": { "类型": "布尔值" },
"DPI模式": { "类型": "字符串" },
"问题": {
"类型": "数组",
"项": {
"类型": "对象",
"属性": {
"严重性": { "枚举": ["严重", "高", "中", "低"] },
"类别": { "类型": "字符串" },
"文件": { "类型": "字符串" },
"行号": { "类型": "数字" },
"描述": { "类型": "字符串" },
"修复": { "类型": "字符串" }
}
}
},
"建议": {
"类型": "数组",
"项": { "类型": "字符串" }
}
},
"必需": ["成功", "问题"]
}
DPI感知模式
系统DPI感知(传统)
<!-- app.manifest -->
<application xmlns="urn:schemas-microsoft-com:asm.v3">
<windowsSettings>
<dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true</dpiAware>
</windowsSettings>
</application>
每显示器DPI感知(Windows 8.1+)
<application xmlns="urn:schemas-microsoft-com:asm.v3">
<windowsSettings>
<dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true/PM</dpiAware>
</windowsSettings>
</application>
每显示器V2 DPI感知(Windows 10 1703+)
<application xmlns="urn:schemas-microsoft-com:asm.v3">
<windowsSettings>
<dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true/PM</dpiAware>
<dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">PerMonitorV2</dpiAwareness>
</windowsSettings>
</application>
常见问题和修复
硬编码像素值
<!-- 错误:硬编码像素 -->
<Button Width="100" Height="30"/>
<Grid Margin="10,5,10,5"/>
<TextBlock FontSize="12"/>
<!-- 正确:使用设备独立单位或相对尺寸 -->
<Button MinWidth="80" MinHeight="24" Padding="16,4"/>
<Grid Margin="{StaticResource StandardMargin}"/>
<TextBlock Style="{StaticResource BodyTextStyle}"/>
位图图像
<!-- 错误:单分辨率位图 -->
<Image Source="icon.png"/>
<!-- 正确:使用矢量或提供多分辨率 -->
<Image>
<Image.Source>
<DrawingImage>
<!-- 矢量绘图 -->
</DrawingImage>
</Image.Source>
</Image>
<!-- 或使用BitmapScalingMode进行清晰缩放 -->
<Image Source="icon.png"
RenderOptions.BitmapScalingMode="HighQuality"/>
动态DPI处理
// 运行时处理DPI变化
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
// 获取当前DPI
var dpiScale = VisualTreeHelper.GetDpi(this);
Debug.WriteLine($"DPI: {dpiScale.PixelsPerDip * 96}");
}
protected override void OnDpiChanged(DpiScale oldDpi, DpiScale newDpi)
{
base.OnDpiChanged(oldDpi, newDpi);
// 处理DPI变化
Debug.WriteLine($"DPI从 {oldDpi.PixelsPerDip * 96} 变为 {newDpi.PixelsPerDip * 96}");
// 如果需要,重新加载高DPI资源
ReloadAssets(newDpi);
}
private void ReloadAssets(DpiScale dpi)
{
// 加载适当分辨率的资源
var scale = dpi.PixelsPerDip;
string suffix = scale >= 2 ? "@2x" : scale >= 1.5 ? "@1.5x" : "";
// 加载带后缀的资源
}
}
每显示器V2设置
// App.xaml.cs
public partial class App : Application
{
protected override void OnStartup(StartupEventArgs e)
{
// 启用每显示器V2 DPI感知(Windows 10 1703+)
if (Environment.OSVersion.Version >= new Version(10, 0, 15063))
{
// 每显示器V2通过清单自动启用,但需要验证
var awareness = GetProcessDpiAwareness();
Debug.WriteLine($"DPI感知: {awareness}");
}
base.OnStartup(e);
}
[DllImport("shcore.dll")]
private static extern int GetProcessDpiAwareness(IntPtr hprocess, out int awareness);
private static int GetProcessDpiAwareness()
{
GetProcessDpiAwareness(IntPtr.Zero, out int awareness);
return awareness;
}
}
变换问题
// 错误:手动缩放计算
var scale = 96.0 / GetSystemDpi();
transform.ScaleX = scale;
transform.ScaleY = scale;
// 正确:让WPF处理缩放
// 使用设备独立单位,WPF处理其余部分
<Canvas>
<Rectangle Canvas.Left="10" Canvas.Top="10"
Width="100" Height="50"/>
</Canvas>
字体缩放
<!-- 错误:硬编码字体大小 -->
<TextBlock FontSize="14"/>
<!-- 正确:使用命名样式或相对尺寸 -->
<TextBlock Style="{DynamicResource MaterialDesignBody1TextBlock}"/>
<!-- 或使用系统字体大小 -->
<TextBlock FontSize="{x:Static SystemFonts.MessageFontSize}"/>
项目配置
<!-- .csproj -->
<PropertyGroup>
<TargetFramework>net8.0-windows</TargetFramework>
<UseWPF>true</UseWPF>
<!-- 启用高DPI支持 -->
<ApplicationHighDpiMode>PerMonitorV2</ApplicationHighDpiMode>
</PropertyGroup>
<!-- 包含app.manifest -->
<ItemGroup>
<None Update="app.manifest">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>
测试多DPI
# 通过PowerShell更改显示缩放(需要重启)
Set-ItemProperty -Path "HKCU:\Control Panel\Desktop" -Name "LogPixels" -Value 144 # 150%
# 在不同DPI的多显示器上测试
# 使用Windows显示设置为每个显示器设置不同的缩放比例
最佳实践
- 使用每显示器V2:Windows 10+上的最佳缩放支持
- 避免硬编码像素:使用相对或自动尺寸
- 使用矢量图形:图标使用SVG或DrawingImage
- 提供多分辨率位图:@1x、@1.5x、@2x
- 处理OnDpiChanged:DPI变化时重新加载资源
- 在多个DPI级别测试:100%、125%、150%、200%
相关技能
wpf-xaml样式生成器- DPI感知样式桌面无障碍流程 - 无障碍测试视觉回归设置- 不同DPI下的视觉测试
相关代理
wpf-dotnet专家- WPF专业知识桌面用户体验分析师- UX审查