Изменить размер шрифта всех дочерних элементов WinForm - PullRequest
1 голос
/ 25 мая 2020

Я делаю приложение на C# с помощью WinForm. Я хотел бы иметь возможность изменять размер шрифта всех меток внутри этого приложения, используя ctrl + scroll. На данный момент я могу изменить шрифт всех меток внутри одной формы, но я хотел бы применить это изменение размера шрифта ко всей форме, а не только к текущей форме.

Чтобы создать все формы, я использую шаблон:

public partial class TemplateForm : DockContent
{
    static public UInt16 percentageFontSize = 100;
    public TemplateForm()
    {
        InitializeComponent();
    }

    private void TemplateForm_MouseWheel(object sender, MouseEventArgs e)
    {
        if (!ModifierKeys.HasFlag(Keys.Control))
        {
            return;
        }
        if (e.Delta > 0)
        {
            percentageFontSize += 10;
            if (percentageFontSize >= 2000)
            {
                percentageFontSize = 2000;
            }
        }
        else
        {
            percentageFontSize -= 10;
            if (percentageFontSize <= 10)
            {
                percentageFontSize = 10;
            }
        }
        SetAllControlsFont(this.Controls);
    }

    public static void SetAllControlsFont(System.Windows.Forms.Control.ControlCollection ctrls)
    {
        foreach (Control ctrl in ctrls)
        {
            if (ctrl.Controls != null)
                SetAllControlsFont(ctrl.Controls);

            ctrl.Font = new Font("Microsoft Sans Serif", 8* percentageFontSize / 100);

        }
    }
}

Каждый «документ» использует этот шаблон:

public partial class Form1 : TemplateForm
{
    public AccForm()
    {
        InitializeComponent();
    }
}

public partial class Form2 : TemplateForm
{
    public AccForm()
    {
        InitializeComponent();
    }
}

«this.Controls» только предоставляет мне доступ к управлению выбранная форма. Я думаю, что смогу добиться этого, получив полный контроль над формой с помощью TemplateForm, но я не могу понять, как это сделать. У вас есть идеи, как этого добиться?

Ответы [ 2 ]

1 голос
/ 25 мая 2020

Очевидно, в вашем дизайне есть понятие «один-единственный шрифт для всех этикеток». Всякий раз, когда вы думаете об одном-единственном, вы должны думать либо о классе stati c, либо о синглтоне. У обоих есть свои преимущества и недостатки. Какой из них вы выберете, выходит за рамки этого вопроса

В любом случае, этот единственный LabelFont имеет метод для изменения шрифта, и после его установки возникает событие.

class LabelFont
{
    private Font labelFont; // TODO: consider to initialize with a proper default value.
    public event EventHandler LabelFontChanged;

    protected virtual void OnLabelFontChanged()
    {
        this.LabelFontChanged?.Invoke(this, EventArgs.Empty);
    }

    public Font LabelFont
    {
        get => this.labelFont;
        set
        {
            this.labelFont = value;
            this.OnLabelFontChanged;
        }
    }
}

Нам нужен метод с вводом последовательности элементов управления и выходом: эта последовательность элементов управления плюс все дочерние элементы управления и дочерние элементы управления и т. Д. c

public static IEnumerable<Control> ToDecendants(this IEnumerable<Control> controls)
{
    foreach (Control control in controls)
    {
        // first return this control
        yield return control

        // then return decendants of the child controls
        IEnumerable<Control> decendants = control.Controls
            .Cast<Control>();
            .ToDecendants();
        foreach (Control decendant in decendants)
        {
            foreach (Control decendant in decendants)
                yield return decendant;
        }
    }
}

Возможно, вы сможете что-то сделать с LINQ и SelectMany. Не забудьте добавить сам элемент управления, а не только дочерние элементы (что сделает SelectMany)

Каждую TemplateForm необходимо уведомлять всякий раз, когда изменяется один-единственный LableFont

class TemplateForm
{
    private static LabelFont LabelFont => ... // get either static, or singleton

    public TemplateForm()
    {
         ...

         // get notified when the LableFont changes
         LabelFont.LabelFontChanged += OnLabelFontChanged;
    }

    // TODO: Dispose: desubscribe from LabelFontChanged

    private void OnLableFontChanged(object sender, EventArgs e)
    {
        LabelFont labelFont = (LabelFont) sender; // if singleton, otherwise use static
        Font labelFont = labelFont.LabelFont;
        IEnumerable<Control> decendants = this.Controls.Cast<Control>
            .ToDecendants();

        foreach (Control decendant in decendants)
        {
             decendant.Font = labelFont;
        }
  }

Или если вы хотите обновить только шрифт элементов управления Label:

IEnumerable<Control> labelDecendants= this.Controls
    .Cast<Control>
    .ToDecendants()
    .OfType<Label>();
1 голос
/ 25 мая 2020

Ну, причина того, что размер шрифта не изменяется в других формах, а изменяется только в текущей, заключается в том, что другие формы не имеют возможности узнать, что размер действительно изменился, вы должны добавить способ чтобы уведомить их, чтобы они также могли обновить размер шрифта. Для этого вы можете использовать EventHandler (или создать свой собственный обработчик событий), добавить его в свой класс TemplateForm и подписаться на него в конструкторе. Вы вызываете событие всякий раз, когда происходит изменение шрифта, а в методе триггера вы обновляете шрифт соответственно. В целом ваш код должен выглядеть примерно так:

    static public EventHandler fontSizeChangedEvent;
    static public UInt16 percentageFontSize = 100;
    public TemplateForm()
    {
        MouseWheel += TemplateForm_MouseWheel;
        fontSizeChangedEvent += FontSizeChanged;
    }

    private void TemplateForm_MouseWheel(object sender, MouseEventArgs e)
    {
        //// rest of code .....

        fontSizeChangedEvent.Invoke(this, new EventArgs());
        SetAllControlsFont();
    }

    public void FontSizeChanged(object sender, EventArgs e)
    {
        // Only update for the other forms, not the one that raised the event
        if (sender != this)
            SetAllControlsFont();
    }

    public void SetAllControlsFont(ControlCollection ctrls = null)
    {
        if (ctrls == null)
            ctrls = this.Controls;

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