c# - 更改默认字体的 AutoScaleMode 问题

标签 c# .net winforms

当使用非默认字体时,Form.AutoScaleMode 属性和固定大小的控件存在一些问题。我将它归结为一个简单的测试应用程序 (WinForms 2.0),只有一种形式、一些固定大小的控件和以下属性:

class Form1 : Form
{
    // ...
    private void InitializeComponent()
    {
        // ...
        this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F);
        this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi;
        this.Font = new System.Drawing.Font("Tahoma", 9.25F);
        // ...
    }
}

在 96dpi、Windows XP 下,表单看起来正确,就像这个 96 dpi 示例:

96 dpi WinForm

在 120 dpi 下,Windows XP,Windows 窗体自动缩放功能产生这个 120 dpi 示例:

Previous WinForm scaled to 120 dpi

如您所见,组框、按钮、列表或 TreeView 缩放正确,多行文本框在垂直轴上变得太大,固定大小的标签在垂直和水平方向上缩放不正确。似乎是 .NET 框架中的错误?

编辑:一些提示:字体更改仅应用于包含表单,控件从表单继承其字体。如果可能的话,我想保持这种状态。

使用默认字体(Microsoft Sans Serif 8.25pt),不会出现此问题。使用 AutoScaleMode = Font(当然有足够的 AutoScaleDimensions)要么根本不缩放,要么完全像上面看到的那样缩放,具体取决于设置字体的时间(在更改 AutoScaleMode 之前或之后)。该问题并非特定于“Tahoma”字体,Microsoft Sans Serif, 9.25pt 也会出现此问题。

是的,我已经阅读了这篇 SO 帖子 high DPI problems 但它并没有真正帮助我。

有什么解决这个问题的建议吗?

EDIT2:关于我的意图的一些附加信息:我已经有大约 50 个固定大小的对话框,其中有数百个正确放置的固定大小控件。它们从旧的 C++ GUI 框架迁移到 C#/Winforms,这就是它们都是固定大小的原因。使用 9.25pt 字体,所有这些在 96 dpi 下看起来都不错。在旧框架下,缩放到 120 dpi 效果很好——所有固定大小的控件在两个维度上缩放相等。上周,当切换到 120 dpi 时,我们在 WinForms 下检测到这种奇怪的缩放行为。您可以想象,我们的大多数对话框现在在 120 dpi 下看起来非常糟糕。我正在寻找一种解决方案,避免完全重新设计所有这些对话框。

EDIT3:为了测试这种行为,恕我直言,设置一个 120 dpi 的虚拟 Windows XP 环境是个好主意,而开发环境位于 96 dpi 以下(至少,我是这样做的)。在 96 和 120 dpi 之间更改通常需要在 Win XP 下重新启动,否则您看不到实际发生的情况。

// As requested: the source code of Form1.cs 
namespace DpiChangeTest
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
            Font f = this.textBox1.Font;
        }
    }
}

 // here the source of Form1.Designer.cs:
namespace DpiChangeTest
{
    partial class Form1
    {
        private System.ComponentModel.IContainer components = null;

        protected override void Dispose(bool disposing)
        {
            if (disposing && (components != null))
            {
                components.Dispose();
            }
            base.Dispose(disposing);
        }

        #region Windows Forms Designer generated code

        private void InitializeComponent()
        {
            System.Windows.Forms.ListViewItem listViewItem2 = new System.Windows.Forms.ListViewItem("A list view control");
            System.Windows.Forms.TreeNode treeNode2 = new System.Windows.Forms.TreeNode("A TreeView control");
            this.button1 = new System.Windows.Forms.Button();
            this.groupBox1 = new System.Windows.Forms.GroupBox();
            this.textBox1 = new System.Windows.Forms.TextBox();
            this.label1 = new System.Windows.Forms.Label();
            this.listView1 = new System.Windows.Forms.ListView();
            this.treeView1 = new System.Windows.Forms.TreeView();
            this.SuspendLayout();
            // 
            // button1
            // 
            this.button1.Location = new System.Drawing.Point(12, 107);
            this.button1.Name = "button1";
            this.button1.Size = new System.Drawing.Size(150, 70);
            this.button1.TabIndex = 0;
            this.button1.Text = "Just a button";
            this.button1.UseVisualStyleBackColor = true;
            // 
            // groupBox1
            // 
            this.groupBox1.Location = new System.Drawing.Point(12, 12);
            this.groupBox1.Name = "groupBox1";
            this.groupBox1.Size = new System.Drawing.Size(150, 70);
            this.groupBox1.TabIndex = 1;
            this.groupBox1.TabStop = false;
            this.groupBox1.Text = "Just a groupbox";
            // 
            // textBox1
            // 
            this.textBox1.Location = new System.Drawing.Point(180, 12);
            this.textBox1.Multiline = true;
            this.textBox1.Name = "textBox1";
            this.textBox1.Size = new System.Drawing.Size(150, 70);
            this.textBox1.TabIndex = 2;
            this.textBox1.Text = "A multiline text box";
            // 
            // label1
            // 
            this.label1.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
            this.label1.Location = new System.Drawing.Point(179, 107);
            this.label1.Name = "label1";
            this.label1.Size = new System.Drawing.Size(150, 70);
            this.label1.TabIndex = 3;
            this.label1.Text = "A label with AutoSize=False";
            // 
            // listView1
            // 
            this.listView1.Items.AddRange(new System.Windows.Forms.ListViewItem[] {
            listViewItem2});
            this.listView1.Location = new System.Drawing.Point(12, 201);
            this.listView1.Name = "listView1";
            this.listView1.Size = new System.Drawing.Size(150, 70);
            this.listView1.TabIndex = 4;
            this.listView1.UseCompatibleStateImageBehavior = false;
            // 
            // treeView1
            // 
            this.treeView1.Location = new System.Drawing.Point(179, 201);
            this.treeView1.Name = "treeView1";
            treeNode2.Name = "Knoten0";
            treeNode2.Text = "A TreeView control";
            this.treeView1.Nodes.AddRange(new System.Windows.Forms.TreeNode[] {
            treeNode2});
            this.treeView1.Size = new System.Drawing.Size(150, 70);
            this.treeView1.TabIndex = 5;
            // 
            // Form1
            // 
            this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F);
            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi;
            this.ClientSize = new System.Drawing.Size(343, 289);
            this.Controls.Add(this.treeView1);
            this.Controls.Add(this.listView1);
            this.Controls.Add(this.label1);
            this.Controls.Add(this.textBox1);
            this.Controls.Add(this.button1);
            this.Controls.Add(this.groupBox1);
            this.Font = new System.Drawing.Font("Microsoft Sans Serif", 9.25F);
            this.Name = "Form1";
            this.Text = "Form1";
            this.ResumeLayout(false);
            this.PerformLayout();

        }

        #endregion

        private System.Windows.Forms.Button button1;
        private System.Windows.Forms.GroupBox groupBox1;
        private System.Windows.Forms.TextBox textBox1;
        private System.Windows.Forms.Label label1;
        private System.Windows.Forms.ListView listView1;
        private System.Windows.Forms.TreeView treeView1;
    }
}

 // and Main.cs
    [STAThread]
    static void Main()
    {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        Application.Run(new Form1());
    }

最佳答案

我终于找到了问题的答案。简而言之,当单独设置每个控件的字体而不是设置包含窗体的字体时,不会出现这种效果。这样,自动缩放功能就可以正常工作了。有趣的是,即使 AutoScaleMode 属性设置为 AutoScaleMode.Dpi,设置控件的字体也会更改自动缩放行为,而不仅仅是当它设置为 AutoScaleMode.Font 时.

作为实用的解决方案,我们创建了一个小型命令行程序,它读取 designer.cs 文件,扫描是否所有控件都有明确的字体分配,如果没有,则将分配添加到新创建的设计器代码副本中.我们将此程序嵌入到我们的自动测试套件中,因此每当表单获得新控件或添加新表单时,开发人员忘记添加显式字体分配,测试就会失败。在这期间,从我第一次提出这个问题(4 年前)开始,我们就有了这个解决方案,从那时起,它多次使我们免于扩展问题。

关于c# - 更改默认字体的 AutoScaleMode 问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2973165/

相关文章:

c# - 如何将动态创建的对象分配给字符串?

c# - 文件路径和文件流的区别?

c# - 使用调试 Visual Studio 代码的 Dotnet 监视

c# - 开始为 PowerPoint 开发插件

c# - 如何在类里面再次调用 "static void Main(string[] args) "

c# - 如何使richTextBox滚动?

c# - 当用户在文本框中按回车键时执行按钮单击事件

javascript - C# 和 Javascript 代码的计算有什么区别

.net - PropertyGrid - 属性值旁边是否可以有一个文件/目录选择按钮?

c# - 根据窗体大小在窗体上定位控件