You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何让.NET 6 Windows Forms忽略DPI缩放以适配像素渲染?

解决Windows Forms + SharpDX RenderForm 像素级渲染的DPI缩放问题

1. 启用Per-Monitor DPI Awareness v2(核心步骤)

这是让应用程序精准感知显示器缩放比例的基础,旧模式无法满足像素级需求:

方法A:修改应用程序清单

在项目的app.manifest中添加以下配置(无清单则新建一个):

<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, PerMonitor</dpiAwareness>
  </windowsSettings>
</application>

确保清单已嵌入程序集(项目属性→应用程序→资源→清单选择对应文件)。

方法B:代码强制设置(清单失效时备用)

在Main方法最开头调用:

using System.Runtime.InteropServices;

[DllImport("user32.dll")]
private static extern bool SetProcessDpiAwarenessContext(int dpiFlag);

// 程序启动时执行
SetProcessDpiAwarenessContext(-4); // 对应DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2

2. 自定义RenderForm实现像素尺寸锁定

SharpDX的RenderForm默认会跟随系统缩放,需重写逻辑确保客户端区域严格匹配目标像素:

using SharpDX.Windows;
using System.Windows.Forms;

public class PixelRenderForm : RenderForm
{
    private int _targetPixelWidth;
    private int _targetPixelHeight;

    public PixelRenderForm(string title) : base(title)
    {
        AutoScaleMode = AutoScaleMode.None;
        FormBorderStyle = FormBorderStyle.FixedSingle; // 可选,避免拖拽缩放干扰
    }

    // 设置目标像素尺寸
    public void SetPixelSize(int width, int height)
    {
        _targetPixelWidth = width;
        _targetPixelHeight = height;
        SyncFormSizeWithDpi();
    }

    private void SyncFormSizeWithDpi()
    {
        // 计算当前DPI缩放比例(96为标准DPI)
        var dpiScale = DeviceDpi / 96f;
        // 转换为窗体客户端区域的逻辑尺寸,确保缩放后正好是目标像素
        var clientSize = new Size((int)(_targetPixelWidth / dpiScale), (int)(_targetPixelHeight / dpiScale));
        // 调整窗体整体尺寸(包含边框)
        Size = ClientSizeToSize(clientSize);
    }

    protected override void OnDpiChanged(DpiChangedEventArgs e)
    {
        base.OnDpiChanged(e);
        SyncFormSizeWithDpi();
        // 触发渲染目标更新事件
        PixelSizeChanged?.Invoke(this, new Size(_targetPixelWidth, _targetPixelHeight));
    }

    public event EventHandler<Size> PixelSizeChanged;
}

使用时直接调用SetPixelSize(1920, 1080),即可确保客户端区域为1920×1080物理像素。

3. 同步DirectX渲染目标尺寸

在初始化和DPI变化时,基于目标像素尺寸创建渲染目标:

var renderForm = new PixelRenderForm("Pixel-Perfect DirectX");
renderForm.SetPixelSize(1920, 1080);

// DPI变化时更新渲染目标
renderForm.PixelSizeChanged += (s, size) =>
{
    // 销毁旧渲染目标
    // ...
    // 创建新渲染目标,尺寸为size.Width × size.Height
    // ...
};

// 渲染循环中设置视口为像素尺寸
var viewport = new SharpDX.Mathematics.Interop.RawViewportF(0, 0, renderForm._targetPixelWidth, renderForm._targetPixelHeight);
deviceContext.Rasterizer.SetViewport(viewport);

4. 清理WinForms自动缩放残留

在Program.cs中确保DPI模式正确:

ApplicationConfiguration.Initialize();
Application.SetHighDpiMode(HighDpiMode.PerMonitorV2);

内容的提问来源于stack exchange,提问作者LOST

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.18 21:00:23