this.AutoScaleMode = AutoScaleMode.Dpi
,但它没有解决这个问题。
有人有什么想法吗?this.AutoScaleMode = AutoScaleMode.Dpi
,但它没有解决这个问题。
有人有什么想法吗?编辑:自 .NET 4.7 起,Windows Forms 在高 DPI 上的支持得到了改进。 在 learn.microsoft.com 上阅读更多信息。但它仅适用于 Win 10 创作者更新版本及更高版本,因此根据您的用户群体,现在可能还不可行。
虽然有些困难,但并非不可能实现。当然,您最好选择迁移到 WPF,但这可能不切实际。
我花费了很多时间来解决这个问题。以下是一些规则和指南,可以在没有FlowLayoutPanel或TableLayoutPanel的情况下正确地解决它:
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); // for design in 96 DPI
我保证,如果您按照这些指南操作,即使您放置了具有特定锚定点并且不使用流面板的控件,也会没问题。我们构建的一个应用程序已在数百台具有不同DPI设置的机器上部署,我们不再收到任何投诉。所有表单/容器/网格/按钮/文本字段等大小都正确缩放,字体也是如此。图片也可以正常工作,但在高DPI下可能会稍微失真。
编辑:此链接包含许多有用信息,尤其是如果选择使用AutoScaleMode.DPI:相关stackoverflow问题链接
注意: 这不会修复控件在 DPI 改变时的移动,它只会修复模糊的文本!!。
如何在高dpi设置下修复模糊的Windows Forms:
现在,进入Program.cs(或者你的Main方法所在的文件),并将其更改为:
namespace myApplication
{
static class Program
{
[STAThread]
static void Main()
{
// ***this line is added***
if (Environment.OSVersion.Version.Major >= 6)
SetProcessDPIAware();
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new MainForm());
}
// ***also dllimport of that function***
[System.Runtime.InteropServices.DllImport("user32.dll")]
private static extern bool SetProcessDPIAware();
}
}
保存并编译。现在你的表单应该再次变得清晰易懂。
来源: http://crsouza.com/2015/04/13/how-to-fix-blurry-windows-forms-windows-in-high-dpi-settings/
如何在高DPI设置下修复模糊的Windows窗体?this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi;
protected void Portrait()
{
this.SuspendLayout();
this.crawlTime.Location = new System.Drawing.Point(88, 216);
this.crawlTime.Size = new System.Drawing.Size(136, 16);
this.crawlTimeLabel.Location = new System.Drawing.Point(10, 216);
this.crawlTimeLabel.Size = new System.Drawing.Size(64, 16);
this.crawlStartTime.Location = new System.Drawing.Point(88, 200);
this.crawlStartTime.Size = new System.Drawing.Size(136, 16);
this.crawlStartedLabel.Location = new System.Drawing.Point(10, 200);
this.crawlStartedLabel.Size = new System.Drawing.Size(64, 16);
this.light1.Location = new System.Drawing.Point(208, 66);
this.light1.Size = new System.Drawing.Size(16, 16);
this.light0.Location = new System.Drawing.Point(192, 66);
this.light0.Size = new System.Drawing.Size(16, 16);
this.linkCount.Location = new System.Drawing.Point(88, 182);
this.linkCount.Size = new System.Drawing.Size(136, 16);
this.linkCountLabel.Location = new System.Drawing.Point(10, 182);
this.linkCountLabel.Size = new System.Drawing.Size(64, 16);
this.currentPageBox.Location = new System.Drawing.Point(10, 84);
this.currentPageBox.Size = new System.Drawing.Size(214, 90);
this.currentPageLabel.Location = new System.Drawing.Point(10, 68);
this.currentPageLabel.Size = new System.Drawing.Size(100, 16);
this.addressLabel.Location = new System.Drawing.Point(10, 4);
this.addressLabel.Size = new System.Drawing.Size(214, 16);
this.noProxyCheck.Location = new System.Drawing.Point(10, 48);
this.noProxyCheck.Size = new System.Drawing.Size(214, 20);
this.startButton.Location = new System.Drawing.Point(8, 240);
this.startButton.Size = new System.Drawing.Size(216, 20);
this.addressBox.Location = new System.Drawing.Point(10, 24);
this.addressBox.Size = new System.Drawing.Size(214, 22);
//note! USING JUST AUTOSCALEMODE WILL NOT SOLVE ISSUE. MUST USE BOTH!
this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F); //IMPORTANT
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi; //IMPORTANT
this.ResumeLayout(false);
}
protected void Landscape()
{
this.SuspendLayout();
this.crawlTime.Location = new System.Drawing.Point(216, 136);
this.crawlTime.Size = new System.Drawing.Size(96, 16);
this.crawlTimeLabel.Location = new System.Drawing.Point(160, 136);
this.crawlTimeLabel.Size = new System.Drawing.Size(48, 16);
this.crawlStartTime.Location = new System.Drawing.Point(64, 120);
this.crawlStartTime.Size = new System.Drawing.Size(248, 16);
this.crawlStartedLabel.Location = new System.Drawing.Point(8, 120);
this.crawlStartedLabel.Size = new System.Drawing.Size(48, 16);
this.light1.Location = new System.Drawing.Point(296, 48);
this.light1.Size = new System.Drawing.Size(16, 16);
this.light0.Location = new System.Drawing.Point(280, 48);
this.light0.Size = new System.Drawing.Size(16, 16);
this.linkCount.Location = new System.Drawing.Point(80, 136);
this.linkCount.Size = new System.Drawing.Size(72, 16);
this.linkCountLabel.Location = new System.Drawing.Point(8, 136);
this.linkCountLabel.Size = new System.Drawing.Size(64, 16);
this.currentPageBox.Location = new System.Drawing.Point(10, 64);
this.currentPageBox.Size = new System.Drawing.Size(302, 48);
this.currentPageLabel.Location = new System.Drawing.Point(10, 48);
this.currentPageLabel.Size = new System.Drawing.Size(100, 16);
this.addressLabel.Location = new System.Drawing.Point(10, 4);
this.addressLabel.Size = new System.Drawing.Size(50, 16);
this.noProxyCheck.Location = new System.Drawing.Point(168, 16);
this.noProxyCheck.Size = new System.Drawing.Size(152, 24);
this.startButton.Location = new System.Drawing.Point(8, 160);
this.startButton.Size = new System.Drawing.Size(304, 20);
this.addressBox.Location = new System.Drawing.Point(10, 20);
this.addressBox.Size = new System.Drawing.Size(150, 22);
//note! USING JUST AUTOSCALEMODE WILL NOT SOLVE ISSUE. MUST USE BOTH!
this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F); //IMPORTANT
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi; //IMPORTANT
this.ResumeLayout(false);
}
对我来说像魅力一样运作良好。
看起来这是Windows的问题。删掉这两行就解决了。
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
这就是我找到的解决方案:
在Windows Forms中设计DPI感知应用程序真的很困难。您需要使用布局容器,在DPI更改时正确地调整大小(例如TableLayoutPanel或FlowLayoutPanel)。所有控件也需要调整大小。这些容器的配置可能是一个挑战。
对于简单的应用程序,可以在合理的时间内完成,但对于大型应用程序来说,确实是很多工作。
从经验角度看:
AutoScaleMode
属性设置为 None
我曾经为此苦苦挣扎,但最终在Windows 10和其他系统上找到了一个超级简单的解决方案。
在你的WinForms App.config
文件中粘贴以下内容:
<System.Windows.Forms.ApplicationConfigurationSection>
<add key="DpiAwareness" value="PerMonitorV2" />
</System.Windows.Forms.ApplicationConfigurationSection>
app.manifest
文件,并将以下行粘贴或注释掉:<!-- Windows 10 -->
<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}" />
ScaleByDPI 函数将接收一个 Control 参数,通常是一个窗体,然后递归迭代所有子控件(若 (control.HasChildren == true)),并将您的应用程序控件和字体大小以及图像、图标和图形的尺寸缩放到操作系统配置的 DPI。请尝试为它们实现此功能。
ScaleByDPI 函数的特殊注意事项:
a. 对于所有具有默认字体大小的控件,您需要将它们的 Font.Size 设置为 8.25。
b. 您可以通过 (control.CreateGraphics().DpiX / 96) 和 (control.CreateGraphics().DpiY / 96) 来获取 devicePixelRatioX 和 devicePixelRatioY 值。
c. 您需要根据 control.Dock 和 control.Anchor 值定义的算法来缩放 Control.Size 和 Control.Location。请注意,control.Dock 可能有 6 种可能的值,而 control.Anchor 可能有 16 种可能的值。
d. 这个算法需要设置下一个布尔变量的值:isDoSizeWidth、isDoSizeHeight、isDoLocationX、isDoLocationY、isDoRefactorSizeWidth、isDoRefactorSizeHeight、isDoRefactorLocationX、isDoRefactorLocationY、isDoClacLocationXBasedOnRight、isDoClacLocationYBasedOnBottom。请保留html标签。
e. 如果您的项目使用的控件库不是Microsoft控件,这些控件可能需要特殊处理。
关于上述(d.)布尔变量的更多信息:
*有时一组控件(可能是按钮)需要在同一垂直线上依次放置,并且它们的Anchor值包括右侧但不包括左侧,或者它们需要在同一水平线上依次放置,并且它们的Anchor值包括底部但不包括顶部,在这种情况下,您需要重新计算控件的位置值。
*对于Anchor包含Top和Bottom和/或Left和Right的控件,您需要重新调整控件的大小和位置值。
ScaleByDPI函数的用途:
a. 将以下命令添加到任何Form构造函数的末尾:ScaleByDPI(this);
b. 在动态向Form添加任何控件时,也要调用ScaleByDPI([ControlName])。
当您在构造函数结束后动态设置任何控件的大小或位置时,请创建并使用以下函数之一,以获取缩放后的 Size 或 Location 值:ScaleByDPI_X、ScaleByDPI_Y、ScaleByDPI_Size、ScaleByDPI_Point。
为了将您的应用程序标记为 DPI 感知应用程序,请将 dpiAware 元素添加到您的应用程序程序集清单中。
将所有 Control.Font 的 GraphicsUnit 设置为 System.Drawing.GraphicsUnit.Point。
在所有容器的 *.Designer.cs 文件中,将 AutoScaleMode 值设置为 System.Windows.Forms.AutoScaleMode.None。
对于 ComboBox 和 TextBox 等控件,更改 Control.Size.Height 不起作用。在这种情况下,更改 Control.Font.Size 将修复控件的高度。
如果窗体的 StartPosition 值为 FormStartPosition.CenterScreen,则需要重新计算窗口的位置。
<application xmlns="urn:schemas-microsoft-com:asm.v3">
<windowsSettings>
<dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">unaware</dpiAwareness>
</windowsSettings>
</application>