所以,这是一个场景:我试图使我的所有形式(Winforms)在4K和1080p中看起来都很好,也称为高DPI或" dpi-aware"。我(为了这个问题的目的)有三种形式: frmCompanyMasterEdit ,它继承自 frmBaseEdit ,它继承自 frmBase ,继承了 System.Windows.Forms.Form中。
我尝试过旧的方法,让我的应用程序在清单中识别DPI:
<application xmlns="urn:schemas-microsoft-com:asm.v3">
<windowsSettings>
<dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true</dpiAware>
</windowsSettings>
</application>
这样,除了我可以解决的小锚定问题之外,这种形式在4K看起来很完美,看起来就像那样但在1080p中有点模糊。这是4K:4K both old and new ways。
无论如何,所以我抓住它并尝试.NET 4.7中描述的新方法,针对4.7框架并添加以下代码:
到app.config
<System.Windows.Forms.ApplicationConfigurationSection>
<add key="DpiAwareness" value="PerMonitorV2" />
</System.Windows.Forms.ApplicationConfigurationSection>
到app.manifest
<!-- Windows 10 compatibility -->
<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}" />
并且还从app.manifest中取出旧代码,以便不覆盖新的.NET 4.7方式。我确保将代码放在适当的位置。 所以这里的形式在4K中看起来像上面的图像,但现在在1080p中它被放大了如下所示: 1080p new way
无论哪种方式,除了较小的锚定问题之外,该形式在4k中看起来很棒,并且它(旧的方式)是正确的尺寸但在1080p中有点模糊或者在1080p中不模糊但是真的放大了。 我还必须在所有designer.vb文件中更改这两行,如下所示:
Me.AutoScaleDimensions = New System.Drawing.SizeF(96.0!, 96.0!)
Me.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi
我不知道为什么我不能让它在1080p中看起来合适。就像我说的,我的目标是4.7 .NET框架。我正在使用适当版本的Windows 10(版本1709 / Creator&#39; s版)。 1080p缩放为100%。此外,我们没有资源升级到WPF。
答案 0 :(得分:3)
我已经成功为我的两个Winforms应用程序添加了DPI支持,这些应用程序分别针对.NET 4.5和4.7。
过去,我尝试通过清单文件添加支持,但没有运气。幸运的是,我找到了以下解决方案:
using System;
using System.Runtime.InteropServices;
using System.Windows.Forms;
namespace WinformsApp
{
static class Program
{
[DllImport("Shcore.dll")]
static extern int SetProcessDpiAwareness(int PROCESS_DPI_AWARENESS);
// According to https://msdn.microsoft.com/en-us/library/windows/desktop/dn280512(v=vs.85).aspx
private enum DpiAwareness
{
None = 0,
SystemAware = 1,
PerMonitorAware = 2
}
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
SetProcessDpiAwareness((int)DpiAwareness.PerMonitorAware);
Application.Run(new MainForm());
}
}
}
以上代码是您的Program.cs文件的样子。当然,你必须将它移植到VB,但它应该很容易做到。
这在Windows 10中完美运行,无需任何其他修改。
在两个Winforms应用程序中的一个中,我使用像素坐标在Graphics
类中渲染字符串,这导致我的字符串被偏移。修复非常简单:
private void DrawString(Graphics g, string text, int x, int y)
{
using (var font = new Font("Arial", 12))
using (var brush = new SolidBrush(Color.White))
g.DrawString(text, font, brush, LogicalToDeviceUnits(x), LogicalToDeviceUnits(y));
}
基本上,我必须使用Control.LogicalToDeviceUnits(int value)
来缩放像素坐标。
除此之外,我根本不需要触摸我的代码。
答案 1 :(得分:0)
在我的情况下,我对设置进程DPI意识的推荐方法遇到了很多小故障:最小表单尺寸无法正常工作,在具有不同DPI的监视器之间移动表单时,随机弄乱了表单,没有明显的原因裁剪了表单,字体Segoe UI无法正确缩放,将控件固定在splitter容器中会使所有内容漂浮在错误的位置,等等。
还有一个问题,就是图标变小,您需要更新代码以有选择地加载按钮,ListView,TreeView等更高分辨率的版本。
我最终使用的替代方法是使用Windows 10的设置来覆盖“ GDI缩放”的缩放行为。可以在应用的清单中声明。
这里是设置,您可以先尝试一下,看看它是否满足您的需求:
可以通过修改项目中的app.manifest文件并添加以下条目来自动设置此设置:
<asmv3:application>
<asmv3:windowsSettings xmlns="http://schemas.microsoft.com/SMI/2017/WindowsSettings">
<gdiScaling>true</gdiScaling>
</asmv3:windowsSettings>
</asmv3:application>
该代码可能会给您一个错误,提示您无法识别“ asmv3”。要添加asmv3名称空间,请修改您的app.manifest使其包含它:
之前:
<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
之后:
<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1" xmlns:asmv3="urn:schemas-microsoft-com:asm.v3">