Подтвердить что ты не робот

Проблемы с AutoScaleMode с измененным шрифтом по умолчанию

У меня есть некоторые проблемы с свойством 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 точек на дюйм:

96 dpi WinForm

При 120 dpi, Windows XP, функция автозагрузки Windows Forms создает этот пример с разрешением 120 точек на дюйм:

Previous WinForm scaled to 120 dpi

Как вы видите, групповые боксы, кнопки, список или древовидные представления масштабируются правильно, многострочные текстовые поля становятся слишком большими по вертикальной оси, а метка фиксированного размера не масштабируется правильно как в вертикальном, так и в горизонтальном направлении. Кажется, что ошибка в платформе .NET?

EDIT: некоторые подсказки: изменение шрифта применяется только к содержащейся форме, элементы управления наследуют их шрифт из формы. Я хотел бы сохранить его таким образом, если это возможно.

Использование шрифта по умолчанию (Microsoft Sans Serif 8.25pt), эта проблема не возникает. Использование AutoScaleMode = Font (с адекватными параметрами AutoScaleDimensions, конечно) либо не масштабируется вообще, либо масштабируется точно так же, как показано выше, в зависимости от того, когда установлен Font (до или после изменения AutoScaleMode). Проблема не связана с шрифтом "Tahoma", это происходит также с Microsoft Sans Serif, 9.25pt.

И да, я уже прочитал это сообщение SO высокие проблемы с DPI но мне это действительно не помогает.

Любые предложения о том, как это сделать?

EDIT2: Некоторая дополнительная информация о моем намерении: у меня около 50 уже работающих диалогов с фиксированным размером с несколькими сотнями правильно установленных элементов управления фиксированным размером. Они были перенесены из старой С++ GUI-структуры в С#/Winforms, поэтому они имеют фиксированный размер. Все они отлично смотрятся с разрешением 96 точек на дюйм, используя шрифт 9.25pt. В старой структуре масштабирование до 120 точек на дюйм работало нормально - все элементы фиксированного размера масштабировались одинаково в обоих измерениях. На прошлой неделе мы обнаружили это странное поведение масштабирования в WinForms при переключении на 120 dpi. Вы можете себе представить, что большинство наших диалогов теперь выглядят очень плохо при 120 dpi. Я ищу решение, которое позволяет полностью переделать все эти диалоги.

EDIT3: Для проверки этого поведения, IMHO, рекомендуется создать виртуальную среду Windows XP с разрешением 120 dpi, в то время как среда разработки находится под 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());
    }
4b9b3361

Ответ 1

Наконец-то я нашел ответ на мой вопрос. Короче говоря, эффект не возникает, если вы задаете шрифт каждого элемента управления индивидуально, а не устанавливаете шрифт содержащейся формы. Таким образом, функция автоматического масштабирования работает так, как должна. Интересно отметить, что установка шрифта элементов управления изменяет поведение автомасштабирования, даже если для свойства AutoScaleMode установлено значение AutoScaleMode.Dpi, а не только когда оно установлено на AutoScaleMode.Font.

Как прагматичное решение, мы создали небольшую программу командной строки, которая читает файлы designer.cs, сканирует, если все элементы управления имеют явное назначение шрифтов, а если нет, добавляет присваивание во вновь созданную копию кода дизайнера, Мы встроили эту программу в наш автоматический набор тестов, поэтому всякий раз, когда форма получает новые элементы управления или добавляется новая форма, а разработчик забывает добавлять явное назначение шрифтов, тесты не сработают. Между тем у нас есть это решение, работающее с того времени, когда я впервые задал этот вопрос (4 года назад), и с тех пор он избавил нас от проблем с масштабированием.

Ответ 2

Если бы эта разочаровывающая проблема, в результате чего расстояние в форме исказилось из-за несоответствия, изменило значение AutoScaleMode на "None", и проблема полностью исчезла.

Ответ 3

Я смог разрешить аналогичную проблему с компактной каркасной версией 3.5 на VS 2008. В моем случае у меня есть tabcontrol, и каждая вкладка имеет панель, и все они состыкованы как полные со своими родителями. Каждая панель содержит несколько элементов управления ярлыками и текстовыми полями, поэтому идея заключается в том, что когда пользователь открывает панель SIP (панель мягкого ввода/клавиатура), которая будет отображаться справа от полосы прокрутки, а элементы управления текстовыми полями будут масштабироваться по ширине, чтобы не рисовать дополнительную горизонтальную полосу прокрутки.

Моя первоначальная попытка заключалась в том, что режим автомасштабирования форм был установлен на dpi, каждое свойство autoscroll каждой вкладки установлено равным true, а свойство autoscroll для каждой панели установлено в true. Каждая метка была привязана к вершине, слева, и каждый элемент управления текстовым полем был привязан к левому, верхнему и правому. Формы были созданы в дизайнере с шириной экрана 240 пикселей, а при запуске на устройстве vga с шириной экрана 480 пикселей текстовые поля были бы раскрашены пространством справа, достаточным для 2 полос прокрутки (предположительно один для вкладки и один для панели), хотя полосы прокрутки не появлялись. При активации SIP поведение было правильным, поскольку все текстовые поля были изменены, но у меня по-прежнему было около 40 пикселей мертвого пространства между правой стороной текстового поля и полосой прокрутки.

Мне удалось решить проблему, просто установив значение свойства autoscroll для панелей в значение false, а затем установив значение true для времени выполнения, когда был активирован SIP. Это имело желаемый результат автомасштабирования по всей ширине экрана в ширину пикселя и динамическое изменение размера элементов управления текстовыми полями при активации или деактивации полосы прокрутки.

В качестве стороннего примечания компактный каркас (3.5) не имеет режима автомасштабирования Font (только none, dpi и inherit), но я попытался сбросить шрифт каждого элемента управления текстовым полем, как предполагал автор оригинала, но это не было 't влияют на автомасштабирование элементов управления.

Ответ 4

Я тоже обнаружил, что поведение нечетное, и поделилось аналогичными головными болями, пытаясь автоматически масштабировать элементы управления (и связанные с ними шрифты) в моем приложении в ответ на изменение размера или разрешения.

Для чего стоит, вот краткий обзор того, что я пытался применить исправление вручную:

Во-первых, при запуске приложения я захватываю разрешение пользовательской системы, обращаясь к члену Bounds в свойстве Screen:: PrimaryScreen и программно изменяя размер формы на основе процента отличие от системы времени разработки. Этот новый размер формы сохраняется и используется в качестве базового размера для всех будущих корректировок. Кроме того, изменяя размер формы во время выполнения, он вызывает событие SizeChanged, которое я обработал, чтобы выполнить масштабирование. В двух словах обработчик событий делает следующее:

  • Изменяет размеры всех элементов управления в соответствии с новыми значениями ширины и высоты после того, как пользователь выберет размер, будь то мышь или предопределенный размер.

  • Изменяет размер шрифта, связанный с каждым элементом управления, с помощью нового коэффициента масштабирования

Теоретически, если элементы управления перемещаются в новое место в зависимости от процента изменения размера формы, он должен сохранять их относительно всех остальных элементов управления. Конечно, каждый раз, когда размер формы изменяется пользователем, это происходит не только при начальной работе.

Я не уверен, что это решение глупо или нет, но время, которое я потратил, или потраченное впустую, сражаясь с AutoScale, AutoSize и Anchoring безрезультатно, было астрономическим. Я не пытаюсь захватить ваш раздел, Док, я просто подумал, что буду делиться своими мысленными процессами с вами и, возможно, воскресить эту тему в надежде, что у кого-то есть превосходное понимание этого кошмара.

Ответ 5

Имейте в виду, что, поскольку многие из упомянутых проблем связаны с размером шрифта, важно соответствовать семейству и размеру шрифта. Это означает, что шрифт установлен в базовой форме или базовом пользовательском контроле (если он у вас есть), и пусть элементы управления наследуют этот параметр. Я заметил, что, когда у меня есть форма с UserControl внутри нее, если я выбрал элемент управления и изменил размер шрифта, некоторые элементы изменились, а некоторые - нет. Я понял, что элементы, которые не изменяли размер, устанавливали определенную настройку шрифта (over-ridden). Именно в это время я понял, что это значит, когда свойства выделены жирным шрифтом. Так, например, если у вас есть ярлык, а шрифт - жирный шрифт, значит, кто-то его изменил. Вы должны очистить все эти реквизиты шрифтов, которые были установлены таким образом, чтобы они получили свой шрифт от родителя, в этом случае содержащую форму. Вы можете просто выделить текст свойства шрифта и удалить или щелкнуть правой кнопкой мыши ссылку на шрифт и выбрать clear. Это приведет к удалению строки шрифта из файла конструктора и разрешит элементу управления наследовать шрифт от его родителя. Это, вероятно, вернется к Microsoft Sans Serif, но если вы его построите, он подберет шрифт из своего родителя Конечно, вы должны следовать правильному дизайну, используя макетные панели и свойства привязки и док-станции, но я обнаружил, что в целом, если вы очистите все перегруженные шрифтовые реквизиты, вы обнаружите, что если вы выберете пользовательский элемент управления из вашей формы и измените автоскалог Нет, вам повезет больше Также для тестирования, если вы затем измените размер шрифта для управления пользователем, все элементы управления в нем должны изменить размер (при условии, что реквизиты шрифтов не будут перегружены) И пока форма разработана с использованием правильных макетов, все должно отлично отображаться при других разрешениях. По крайней мере, для меня это сработало.

Ответ 6

Для принятого решения о внесении изменений для каждого элемента управления: Вы тестировали изменение шрифта контейнера, но снова задали значения AutoScaleXXX?

Что-то вроде:

 this.SuspendLayout();
 this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F);
 this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; // Font in this case
 this.Font = new Font(....); // set your new font
 this.ResumeLayout();

Я сделал это при добавлении динамических элементов управления, но не для изменения шрифтов.

Ответ 7

У меня тоже была эта проблема. Особенно LinkLabels были показаны со слишком большим шрифтом, а метки AutoSize были обрезаны где-то в конце. Изменение AutoScaleMode на Dpi только в первом диалоговом окне (Main) разрешило его для всех форм. Спасибо за подсказку.

Ответ 8

В моем приложении WinForms есть настройки размера шрифта, где шрифт можно установить на трех уровнях (8pt, 10pt или 12pt) на главном экране, и он должен распространяться на все подформы.

Конкретные проблемы, с которыми я столкнулся, - это метки, которые не являются Autosize (обычно используются для многострочных меток) и многострочных текстовых полей.

Решение, которое я нашел, состояло в том, чтобы добавить следующую строку с соответствующим элементом управления в файлах Designer.cs в InitializeComponent():

this.Label1.Font = this.Font;

или

this.MultiLineTextbox.Font = this.Font;

Кажется, правильно настроил AutoScale.