C# ApplyTheme 方法同时处理所有表单

分享于2022年07月17日 c# visual-studio 问答
【问题标题】:C# ApplyTheme 方法同时处理所有表单(C# ApplyTheme method to work on all forms simultaneously)
【发布时间】:2022-01-27 09:25:16
【问题描述】:

我正在尝试为我的应用实现主题转换器。到目前为止,我已经这样做了:

BaseForm - 具有所有要继承的功能,它很长,所以如果需要,我会在此处发布。我遇到的问题如下:

MainForm 有一个按钮可以打开用户设置,用户可以在其中更改主题。问题是,我设法让主题适用,但仅适用于 UserSettings 窗口,我希望它适用于打开的任何内容(如果还有其他内容)。

编辑:添加更多代码

using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Text;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Windows.Forms;
using IniParser;
using ME___Tooling_Designer_App.Properties;

namespace ME___Tooling_Designer_App.Configuration;

public partial class UserSettings : BaseForm
{
    public UserSettings()
    {
        InitializeComponent();
        ApplyTheme();
        ReadConfiguration();
    }

// this is where the theme should be applied upon close
private void CBoxTheme_DropDownClosed(object sender, EventArgs e)
    {
        var parser = new FileIniDataParser();

        var data = parser.ReadFile(_filePathSettings);

        if (cBoxTheme.SelectedIndex == 0)
        {
            data["User_Settings"]["Theme"] = "Dark";
            parser.WriteFile(_filePathSettings, data);
            GlobalTheme = Enumerators.Theme.Dark;
        }

        if (cBoxTheme.SelectedIndex == 1)
        {
            data["User_Settings"]["Theme"] = "Light";
            parser.WriteFile(_filePathSettings, data);
            GlobalTheme = Enumerators.Theme.Light;
        }
        ApplyTheme();
    }

public override void ApplyThemeSpecific(ThemeSettings settings)
    {
        panel1.BackColor = settings.PrimaryColor;
        label2.ForeColor = settings.PrimaryFontColor;
        btnExit.BackColor = settings.PrimaryColor;
        btnExit.ForeColor = settings.PrimaryFontColor;
        groupBox1.ForeColor = settings.PrimaryFontColor;
        groupBox2.ForeColor = settings.PrimaryFontColor;

        panel2.BackColor = settings.SecondaryColor;
    }

编辑:这是 BaseForm 代码:​​

using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Text;
using System.Windows.Forms;

namespace ME___Tooling_Designer_App.Configuration;

public class BaseForm : Form
{

    public static List FontCollections;


    public static Enumerators.Theme GlobalTheme { get; set; }

    public void ApplyTheme()
    {
        var settings = new ThemeSettings();

        if (GlobalTheme == Enumerators.Theme.Dark)
        {
            settings.PrimaryColor = Color.FromArgb(32, 30, 50);
            settings.SecondaryColor = Color.FromArgb(32, 30, 45);
            settings.TertiaryColor = Color.FromArgb(11, 7, 17);
            settings.QuaternaryColor = Color.FromArgb(23, 21, 32);
            settings.QuinaryColor = Color.FromArgb(35, 32, 39);
            settings.SenaryColor = Color.LightGray;
            settings.SeptenaryColor = Color.Gainsboro;
            settings.PrimaryFontColor = Color.Gainsboro;
        }

        else if (GlobalTheme == Enumerators.Theme.Light)
        {
            settings.PrimaryColor = Color.LightGray;
            settings.SecondaryColor = Color.GhostWhite;
            settings.TertiaryColor = Color.Gainsboro;
            settings.QuaternaryColor = Color.DarkGray;
            settings.QuinaryColor = Color.Silver;
            settings.SenaryColor = Color.Gray;
            settings.SeptenaryColor = Color.Black;
            settings.PrimaryFontColor = Color.Black;
        }

        ApplyThemeSpecific(settings);
    }

    public virtual void ApplyThemeSpecific(ThemeSettings settings)
    {
    }
}

public class Enumerators
{
    public enum Theme
    {
        NotSet,
        Light,
        Dark
    }
}

public class ThemeSettings
{
    public Color PrimaryColor { get; set; }
    public Color SecondaryColor { get; set; }
    public Color TertiaryColor { get; set; }
    public Color QuaternaryColor { get; set; }
    public Color QuinaryColor { get; set; }
    public Color SenaryColor { get; set; }
    public Color SeptenaryColor { get; set; }
    public Color PrimaryFontColor { get; set; }
}

这是我的 Program.cs:

using System;
using System.Windows.Forms;
using IniParser;
using ME___Tooling_Designer_App.Configuration;
using ME___Tooling_Designer_App.Forms;

namespace ME___Tooling_Designer_App
{
    static class Program
    {
        /// 
        /// The main entry point for the application.
        /// 
        [STAThread]
        static void Main()
        {

            var parser = new FileIniDataParser();

            var data = parser.ReadFile(Application.StartupPath + @"\" + "Config" + @"\" + "settings.ini");

            var themeSetting = data["User_Settings"]["Theme"];

            Application.EnableVisualStyles();
            Application.SetHighDpiMode(HighDpiMode.SystemAware);
            Application.SetCompatibleTextRenderingDefault(false);
            if (themeSetting == "Light")
            {
                BaseForm.GlobalTheme = Enumerators.Theme.Light;
            }
            else if (themeSetting == "Dark")
            {
                BaseForm.GlobalTheme = Enumerators.Theme.Dark;
            }
            else
            {
                BaseForm.GlobalTheme = Enumerators.Theme.NotSet;
            }

            Application.Run(new Login());
        }

    }
}

尝试将其作为 MainForm.ApplyTheme 进行,但仍然返回到 UserSettings

编辑:添加 MainForm 的 sn-ps:

namespace ME___Tooling_Designer_App.Forms;

public partial class MainForm : BaseForm
{
    /// 
    ///     Constructor
    /// 
    public MainForm()
    {
        InitializeComponent();
        ApplyTheme();
        CreateDirectories();
        CustomizeDesign();
        InitializeDatFiles();
        InitializeIniConfiguration();
        ReadFont();
        ReadComputer();
        ReadSystem();
        TestTrial();
        DaysRemainColoring();
        CompareComputerNameAndLicense();
        lblUser.Text = Environment.UserName;
    }

public override void ApplyThemeSpecific(ThemeSettings settings)
    {
        panelTopBar.BackColor = settings.PrimaryColor;
        btnInfo.BackColor = settings.PrimaryColor;
        btnMinimize.BackColor = settings.PrimaryColor;
        btnExitTop.BackColor = settings.PrimaryColor;

        panelCenter.BackColor = settings.SecondaryColor;

        panelSideMenu.BackColor = settings.TertiaryColor;
        panelSideMenuLogo.BackColor = settings.TertiaryColor;
        btnMainMenu.BackColor = settings.TertiaryColor;
        btnSettings.BackColor = settings.TertiaryColor;
        btnSave.BackColor = settings.TertiaryColor;
        btnLoad.BackColor = settings.TertiaryColor;
        btnExit.BackColor = settings.TertiaryColor;

        panelQuickView.BackColor = settings.QuaternaryColor;

        panelMainMenu.BackColor = settings.QuinaryColor;
        panelSettings.BackColor = settings.QuinaryColor;
        btnNewProject.BackColor = settings.QuinaryColor;
        btnExistingProject.BackColor = settings.QuinaryColor;
        btnReadProject.BackColor = settings.QuinaryColor;
        btnSearchProject.BackColor = settings.QuinaryColor;
        btnUserSettings.BackColor = settings.QuinaryColor;
        btnAppSettings.BackColor = settings.QuinaryColor;
    }


【解决方案1】:

解决办法是加个定时器

因为你的问题是更新所有窗口,所以只需要给每个窗口添加一个定时器控件即可。

定时器:

C# ApplyTheme method to work on all forms simultaneously

基本形式:

using System.Drawing;
using System.Windows.Forms;

namespace WindowsFormsApp4 {
    public partial class BaseForm : Form {
        public BaseForm () {
            }
        private static Image baseImage=null;
        public static Image BaseImage {
            get {
                return baseImage;
                }
            set {
                baseImage = value;
                }
            }
        }
    }

设置表单:

using System;

namespace WindowsFormsApp4 {
    public partial class SettingsForm : BaseForm {
        public SettingsForm () {
            InitializeComponent();
            }

        private void button1_Click (object sender, EventArgs e) {
            BaseImage = Resource.tiger;
            }

        private void button2_Click (object sender, EventArgs e) {
            BaseImage = Resource.windows;
            }

        private void timer1_Tick (object sender, EventArgs e) {
            this.BackgroundImage = BaseImage;
            }
        }
    }

表格1:

using System;

namespace WindowsFormsApp4 {
    public partial class Form1 : BaseForm {
        public Form1 () {
            InitializeComponent();          
            }
        private void button1_Click (object sender, EventArgs e) {
            SettingsForm settingsForm=new SettingsForm();
            settingsForm.ShowDialog();
            }

        private void timer1_Tick_1 (object sender, EventArgs e) {
                this.BackgroundImage = BaseImage;
            
            }
        }
    }

Resource.resx:

C# ApplyTheme method to work on all forms simultaneously

输出:

C# ApplyTheme method to work on all forms simultaneously

您可以根据需要进行更改。

如果您有任何问题,请在下方评论,我会继续跟进。

  • 我昨天遇到了一些麻烦来解决这个问题,但我走的是正确的道路,虽然有点不同。无论如何,这很有效,我建议的只有一件事是在表单打开和表单关闭时启动和停止计时器我这样做是这样的: private void BtnUserSettings_Click(object sender, EventArgs e) { var userSettings = new UserSettings(); userSettings.Show(); HideSubMenu(); themeTimer.Start(); userSettings.FormClosed += ThemeTimer_Stop; }