Как получить позицию и размер элемента управления из исходных настроек дизайнера? - PullRequest
0 голосов
/ 21 октября 2019

Windows (в зависимости от шрифта / масштаба / масштабирования) изменяет размер моей формы. Я хотел бы программно найти исходную позицию и размер формы и элементов управления (которые были установлены в конструкторе. Во время выполнения эти размеры и позиции изменяются при создании формы.

1 Ответ

0 голосов
/ 23 октября 2019

Windows (в зависимости от шрифта / масштаба / масштабирования) изменяет размер моей формы.

Windows не меняет размер вашей формы. Ваша форма настроена на автоматическое масштабирование. Это контролируется свойством AutoScaleMode . Значение designer по умолчанию равно System.Windows.Forms.AutoScaleMode.Font (по умолчанию Inherit). Общий обзор автоматического масштабирования WinForm можно найти в документации Текущая поддержка автоматического масштабирования . Общее альтернативное значение для использования - System.Windows.Forms.AutoScaleMode.DPI. Когда автоматическое масштабирование включено, коэффициент масштабирования вычисляется с использованием значения AutoScaleDimensions и значения, оцениваемого во время выполнения с использованием DPI, сообщаемого приложению. AutoScaleDimensions устанавливается в сгенерированном дизайнером коде.

Если приложение объявлено с поддержкой DPI, используется истинное значение DPI. Если он не поддерживает DPI, Windows сообщает этому приложению, что оно работает с разрешением 96 т / д. Сообщаемое значение DPI также влияет на показатели, используемые при масштабировании на основе шрифтов.

Я бы хотел программно найти исходную позицию и размер формы и элементов управления (которые были установлены в конструкторе. Во время выполнения эти размеры и позиции изменяются при создании формы.

Это может быть достигнуто путем перехвата точки перед применением автоматического масштабирования. Нет прямого способа сделать это, поскольку вы имеете дело с автоматически сгенерированным кодом (метод InitializeComponent файла Form.designer.cs файла). Именно в этом методе устанавливаются AutoScaleDimensions и AutoScaleMode.

При создании новой формы этот метод выглядит следующим образом.

private void InitializeComponent()
{
    this.components = new System.ComponentModel.Container();
    this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
    this.ClientSize = new System.Drawing.Size(800, 450);
    this.Text = "Form1";
}

Обратите внимание, чтоAutoScaleDimensions недвижимость пока не объявлена ​​в методе,., он будет добавлен как только вы сделаете некоторые изменения формы (изменить свойство или добавить элемент управления), а также новая информация записывается в файл The AutoScaleDimensions свойство будет толькозаписывается, если для AutoScaleMode установлено значение DPI или Font.

Ниже приведен результат изменения формы Size.

private void InitializeComponent()
{
    this.SuspendLayout();
    // 
    // Form1
    // 
    this.AutoScaleDimensions = new System.Drawing.SizeF(8F, 16F);
    this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
    this.ClientSize = new System.Drawing.Size(782, 453);
    this.Name = "Form1";
    this.Text = "Form1";
    this.ResumeLayout(false);
}

Цель shВ связи с вышеизложенным показано, как получить значение для установки свойства AutoScaleDimensions в следующем предлагаемом решении.

Предлагаемое решение :

В конструкторе установитесвойство AutoScaleMode формы имеет значение Inherit или None. Затем измените код конструктора формы, чтобы отразить следующее:

SizeF scalingFactor;
public Form1()
{
    InitializeComponent();

    SuspendLayout();
    AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
    AutoScaleDimensions = new System.Drawing.SizeF(8.0F, 16.0F);

    // at this point you can obtain the scaling factor that will
    // be applied on ResumeLayout
    scalingFactor = AutoScaleFactor;

    // store the design-time bounds in the control's Tag property
    RecursivelyRecordBounds(this);
    ResumeLayout(true);
}

Также добавьте этот метод в код формы.

private static void RecursivelyRecordBounds(Control c)
{
    c.Tag = c.Bounds;
    foreach (Control cc in c.Controls)
    {
        cc.Tag = cc.Bounds;
        if (cc.Controls.Count > 0)
        {
            RecursivelyRecordBounds(cc);
        }
    }
}

Для целей этого примера время разработки каждого элемента управленияBounds хранится в его свойстве Tag. Обратите внимание, что установка двух свойств автоматического масштабирования должна быть заключена в область SupendLayout / ResumeLayout. Также важно сначала установить свойство AutoScaleMode перед установкой свойства AutoScaleDimensions.

Альтернативное решение ( hack ) - оставить для свойства AutoScaleMode значение Font. или DPI и полагаться на наблюдаемую картину метода Initialize. В этом методе свойство Text формы всегда устанавливается после двух свойств масштабирования. Это позволяет использовать событие TextChanged, чтобы указать правильное время для получения границ времени разработки.

public Form1()
{
    EventHandler eh = (s,e) => RecursivelyRecordBounds(this);;
    TextChanged += eh;
    InitializeComponent();
    TextChanged -= eh;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...