更改所有子窗体WinForm的字体大小

时间:2020-05-25 13:03:09

标签: c# winforms

我正在使用WinForm在C#中创建应用程序。我希望能够使用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 个答案:

答案 0 :(得分:1)

其他字体不会更改字体大小,而仅在当前格式上更改字体的原因是,由于其他格式无法知道字体大小实际上已更改,因此您必须添加一种方法通知他们,以便他们也可以更新字体大小。 为此,您可以使用EventHandler(或创建您的自定义事件处理程序),将其添加到TemplateForm类中,并在构造函数中进行订阅,每当字体更改时引发事件,并在trigger方法中更新字体相应。 总之,您的代码应如下所示:

    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 .....
    }

答案 1 :(得分:1)

显然,您设计的概念是“所有标签的唯一字体”。只要您想到一个,就应该想到一个静态类或一个单例。两者都有其优点和缺点。您选择的哪个不在此问题范围内

无论如何,这个也是唯一的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;
        }
    }
}

我们需要一种方法,该方法具有一系列输入控件,然后输出:此一系列控件加上所有子控件和孙控件等

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会这样做)

每一个LableFont发生变化时,都需要通知每个TemplateForm

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>();