SuperAPI AI 工具集

wpf-high-dpi-analyzer

编程与开发

查看项目

更新于 10-15 10:47

技能介绍

用途

wpf-high-dpi-analyzer 用于分析和修复 WPF 应用程序的高 DPI 支持问题。它识别 DPI 相关缺陷,并针对每显示器 DPI 感知、位图缩放以及高分辨率显示器上的布局问题提供修复方案。

主要能力

  • 检测 DPI 感知配置问题
  • 查找硬编码像素值
  • 识别位图缩放问题
  • 检查每显示器 DPI 支持
  • 分析变换与布局问题
  • 审查 app.manifest 中的 DPI 设置
  • 为常见 DPI 问题生成修复
  • 测试多显示器 DPI 场景

使用方式

该技能通过输入 Schema 接收参数:

  • projectPath(必填,字符串):WPF 项目路径
  • targetDpiMode(枚举,默认 per-monitor-v2):可选 system、per-monitor、per-monitor-v2
  • checkCategories(数组,默认 ["manifest", "hardcoded-pixels", "bitmaps", "layouts"]):可选 manifest、hardcoded-pixels、bitmaps、layouts、transforms、fonts
  • generateFixes(布尔,默认 true)

输出 Schema 包含:

  • success(布尔)
  • dpiMode(字符串)
  • issues(数组):每项包含 severity(critical/high/medium/low)、category、file、line、description、fix
  • recommendations(字符串数组)

DPI 感知模式

System DPI Aware(旧版)

<!-- app.manifest -->
<application xmlns="urn:schemas-microsoft-com:asm.v3">
  <windowsSettings>
    <dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true</dpiAware>
  </windowsSettings>
</application>

Per-Monitor DPI Aware(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>

Per-Monitor V2 DPI Aware(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>

常见问题与修复

硬编码像素值

<!-- BAD: Hardcoded pixels -->
<Button Width="100" Height="30"/>
<Grid Margin="10,5,10,5"/>
<TextBlock FontSize="12"/>

<!-- GOOD: Use device-independent units or relative sizing -->
<Button MinWidth="80" MinHeight="24" Padding="16,4"/>
<Grid Margin="{StaticResource StandardMargin}"/>
<TextBlock Style="{StaticResource BodyTextStyle}"/>

位图图像

<!-- BAD: Single resolution bitmap -->
<Image Source="icon.png"/>

<!-- GOOD: Use vector or provide multiple resolutions -->
<Image>
  <Image.Source>
    <DrawingImage>
      <!-- Vector drawing -->
    </DrawingImage>
  </Image.Source>
</Image>

<!-- Or use BitmapScalingMode for crisp scaling -->
<Image Source="icon.png"
       RenderOptions.BitmapScalingMode="HighQuality"/>

动态 DPI 处理

// Handle DPI changes at runtime
public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();

        // Get current DPI
        var dpiScale = VisualTreeHelper.GetDpi(this);
        Debug.WriteLine($"DPI: {dpiScale.PixelsPerDip * 96}");
    }

    protected override void OnDpiChanged(DpiScale oldDpi, DpiScale newDpi)
    {
        base.OnDpiChanged(oldDpi, newDpi);

        // Handle DPI change
        Debug.WriteLine($"DPI changed from {oldDpi.PixelsPerDip * 96} to {newDpi.PixelsPerDip * 96}");

        // Reload high-DPI assets if needed
        ReloadAssets(newDpi);
    }

    private void ReloadAssets(DpiScale dpi)
    {
        // Load appropriate resolution assets
        var scale = dpi.PixelsPerDip;
        string suffix = scale >= 2 ? "@2x" : scale >= 1.5 ? "@1.5x" : "";
        // Load assets with suffix
    }
}

Per-Monitor V2 设置

// App.xaml.cs
public partial class App : Application
{
    protected override void OnStartup(StartupEventArgs e)
    {
        // Enable Per-Monitor V2 DPI awareness (Windows 10 1703+)
        if (Environment.OSVersion.Version >= new Version(10, 0, 15063))
        {
            // Per-Monitor V2 is automatic with manifest, but verify
            var awareness = GetProcessDpiAwareness();
            Debug.WriteLine($"DPI Awareness: {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;
    }
}

变换问题

// BAD: Manual scaling calculations
var scale = 96.0 / GetSystemDpi();
transform.ScaleX = scale;
transform.ScaleY = scale;

// GOOD: Let WPF handle scaling
// Use device-independent units, WPF handles the rest
<Canvas>
    <Rectangle Canvas.Left="10" Canvas.Top="10"
               Width="100" Height="50"/>
</Canvas>

字体缩放

<!-- BAD: Hardcoded font size -->
<TextBlock FontSize="14"/>

<!-- GOOD: Use named styles or relative sizing -->
<TextBlock Style="{DynamicResource MaterialDesignBody1TextBlock}"/>

<!-- Or use system font size -->
<TextBlock FontSize="{x:Static SystemFonts.MessageFontSize}"/>

项目配置

<!-- .csproj -->
<PropertyGroup>
  <TargetFramework>net8.0-windows</TargetFramework>
  <UseWPF>true</UseWPF>

  <!-- Enable high DPI support -->
  <ApplicationHighDpiMode>PerMonitorV2</ApplicationHighDpiMode>
</PropertyGroup>

<!-- Include app.manifest -->
<ItemGroup>
  <None Update="app.manifest">
    <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
  </None>
</ItemGroup>

测试多 DPI

# Change display scaling via PowerShell (requires restart)
Set-ItemProperty -Path "HKCU:\Control Panel\Desktop" -Name "LogPixels" -Value 144  # 150%

# Test with multiple monitors at different DPIs
# Use Windows display settings to set different scales per monitor

最佳实践

  • 使用 Per-Monitor V2:Windows 10+ 上最佳的缩放支持
  • 避免硬编码像素:使用相对或自动尺寸
  • 使用矢量图形:图标使用 SVG 或 DrawingImage
  • 提供多分辨率位图:@1x、@1.5x、@2x
  • 处理 OnDpiChanged:DPI 变化时重新加载资源
  • 在多个 DPI 级别测试:100%、125%、150%、200%

相关技能

  • wpf-xaml-style-generator - DPI 感知样式
  • desktop-accessibility process - 无障碍测试
  • visual-regression-setup - 不同 DPI 下的视觉测试

相关智能体

  • wpf-dotnet-expert - WPF 专业知识
  • desktop-ux-analyst - UX 审查

限制

资料未提供该技能的收费、价格、平台支持范围、具体安装命令及性能指标等信息。