Проблемы AutoScaleMode с измененным шрифтом по умолчанию - PullRequest
33 голосов
/ 04 июня 2010

У меня есть некоторые проблемы со свойством 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);
        // ...
    }
}

При 96 dpi, Windows XP, форма выглядит правильно, как в примере 96 dpi:

96 dpi WinForm

При разрешении 120 т / д в Windows XP функция автоматического масштабирования Windows Forms приводит к примеру с разрешением 120 т / д:

Previous WinForm scaled to 120 dpi

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

РЕДАКТИРОВАТЬ: некоторые подсказки: изменение шрифта применяется только к вмещающей форме, элементы управления наследуют свой шрифт от формы. Я хотел бы сохранить это, если это возможно.

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

И да, я уже читал этот ТАК пост проблемы с высоким разрешением но это не очень помогает мне.

Есть предложения, как это обойти?

РЕДАКТИРОВАТЬ 2: Некоторая дополнительная информация о моем намерении: у меня есть около 50 уже работающих диалогов фиксированного размера с несколькими сотнями правильно размещенных элементов управления фиксированного размера. Они были перенесены из более старой графической среды C ++ в C # / Winforms, поэтому все они имеют фиксированный размер. Все они выглядят хорошо с 96 dpi, используя шрифт 9.25pt. При старой структуре масштабирование до 120 dpi работало нормально - все элементы управления фиксированного размера масштабировались одинаково в обоих измерениях. На прошлой неделе мы обнаружили странное поведение масштабирования под WinForms при переключении на 120 dpi. Вы можете себе представить, что большинство наших диалогов теперь выглядят очень плохо при 120 dpi. Я ищу решение, которое позволяет избежать полного перепроектирования всех этих диалогов.

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

Ответы [ 8 ]

34 голосов
/ 15 июня 2010

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

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

3 голосов
/ 16 октября 2015

Если бы эта неприятная проблема приводила к тому, что интервал в форме становился непонятным, изменил значение AutoScaleMode на «Нет», и проблема полностью исчезла.

1 голос
/ 16 марта 2016

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

1 голос
/ 19 декабря 2011

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

Что бы это ни стоило, вот краткое описание того, что я пытался применить ручное исправление:

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

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

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

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

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

1 голос
/ 01 сентября 2011

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

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

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

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

0 голосов
/ 17 июля 2017

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

Особые проблемы, с которыми я столкнулся, связаны с метками, которые не имеют авторазмера (обычно используются для многострочных меток) и многострочными текстовыми полями.

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

this.Label1.Font = this.Font;

или

this.MultiLineTextbox.Font = this.Font;

Кажется, это правильно настроило автоматическое масштабирование.

0 голосов
/ 12 мая 2016

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

0 голосов
/ 09 января 2015

Для принятого решения о внесении изменений для каждого элемента управления: Вы тестировали изменение шрифта контейнера, но снова устанавливали значения 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();

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...