我正在使用 Windows 窗体通过 SharpDX 托管 DirectX 渲染的内容
RenderForm
。问题是,当我设置表单 Size
时,它会根据显示器的缩放因子对其进行缩放,这不是我需要的,因为我进行基于像素的渲染。
我尝试将表单的
AutoScaleMode
设置为None
,但似乎没有效果。
我还玩过
DpiAwareness
中的System.Windows.Forms.ApplicationConfigurationSection
以及应用程序清单中的相应设置。
我的目标是以像素为单位完成所有事情。
我也有同样的问题。
我有一个.Net6.0项目,其中有很多继承自现有控件或定制控件的控件。
以下是我发现的。
Application.SetHighDpiMode(HighDpiMode.PerMonitorV2)
对我的项目没有帮助。控件仍根据 DPI 缩放调整大小。
Application.SetHighDpiMode(HighDpiMode.DpiUnaware)
可以阻止你的 winform 进行 DPI 缩放。但效果图太模糊,客户无法接受
更改app.config中的配置是没有用的。在.Net 6.0中,在app.config中添加以下配置会导致ConfigurationErrorsException。
<System.Windows.Forms.ApplicationConfigurationSection>
<add key="DpiAwareness" value="PerMonitorV2" />
</System.Windows.Forms.ApplicationConfigurationSection>
经过长时间的研究,我终于找到了在.NET 6.0 for Winforms中忽略DPI缩放的解决方案:
将 所有表单和控件的 AutoScaleMode 设置为 None。
不要使用点来设置字体大小,而是使用像素。如果您以 Point 指定字体大小,它将根据您的 DPI 设置进行放大。缩放很丑陋,因为您的控件可能无法按字体大小的比例缩放,从而使单词太大而无法适应控件(例如按钮或数据网格视图)。相比之下,如果您以像素为单位指定字体大小,则文字不会根据您的 DPI 设置进行缩放。
作为一种良好的做法,使用布局控件(例如表格布局、流动布局)、填充和边距来定位控件。尽管您的控件无法缩放,但您的主窗口可以缩放。这些为您提供控件之间的相对定位,一旦用户调整窗口大小,就会触发自动定位。
此行在创建对我有用的主表单之前运行:
Application.SetHighDpiMode(HighDpiMode.PerMonitorV2);
原因是,通过显式声明缩放意识,您可以选择退出 Windows 窗体,通过隐式乘以所有大小来为您处理缩放。
AutoScaleMode
结果是不需要的。
SetHighDpiMode
文档,清单方法也应该有效,但我怀疑在从 JetBrains Rider 启动项目时,有些侥幸阻止了它被采用。
Winform、.NET 4.7.2、 程序.cs
[DllImport("user32.dll", EntryPoint = "SetProcessDPIAware")]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool SetProcessDPIAware();
SetProcessDPIAware();
form.cs
//SharpDX
scaleFactor = GetDpiForSystem() / 96.0f;
Console.WriteLine(scaleFactor);
//float scaleFactor = 1.25f;
var targetProperties = new HwndRenderTargetProperties {
Hwnd = this.Handle,
//PixelSize = new Size2(this.Bounds.Right - this.Bounds.Left, this.Bounds.Bottom - this.Bounds.Top),
PixelSize = new Size2((int)(screenWidth * scaleFactor), (int)(screenHeight * scaleFactor)),
PresentOptions = PresentOptions.Immediately
};
但是会模糊。
如果我使用this.BackgroundImage = fullScreenCapture();,就没有问题。但是当使用 SharpDX 时,禁用 DPI 缩放似乎没有效果: windowRenderTarget.DrawBitmap(fullScreenCapture(), 1.0f, BitmapInterpolationMode.Linear);我不知道为什么。