WinForm 主题实现方法

前言

WinForm的主题实现没有bs里面那么舒服,下面做了一个简单实现,记录一下。

1、一个接口,需要做主题的控件、窗体都要实现这个接口.

  /// <summary>
    /// 使用主题的控件、窗体需要实现此接口
    /// </summary>
    public interface IThemeControl
    {
        ITheme ThisTheme { get; set; }
        /// <summary>
        /// 重置主题
        /// </summary>
        void ResetTheme();
    }

2、一个主题接口

   /// <summary>
    /// 主题
    /// </summary>
    public interface ITheme
    {
        int Code { get;  }
        /// <summary>
        /// 初始化
        /// </summary>
        void Init();

    }

3、一个主题控制类

/// <summary>
/// 主题设置
/// </summary>
public class Theme
{
    internal delegate void CheckedThemeEventHandle(ITheme theme);
    /// <summary>
    /// 改变主题事件
    /// </summary>
    static internal event CheckedThemeEventHandle CheckedThemeEvent;
    static ITheme currentTheme;
    /// <summary>
    /// 当前主题
    /// </summary>
    internal static ITheme CurrentTheme
    {
        get { return currentTheme; }
        set
        {
            if (value == null)
                return;
            currentTheme = value;
            currentTheme.Init();
            if (CheckedThemeEvent != null)
            {
                CheckedThemeEvent(value);
            }
        }
    }
    /// <summary>
    /// 加载控件的主题
    /// </summary>
    /// <param name="control"></param>
    internal static void LoadTheme(IThemeControl control)
    {
        control.ResetTheme();
    }
}

4、添加一个窗体通用的主题接口

 public interface IThemeBaseForm
    {
        /// <summary>
        /// 基本窗体背景色
        /// </summary>
        Color BaseFormBackgroundColor { get; }
        /// <summary>
        /// 基本窗体文字颜色
        /// </summary>
        Color BaseFormForeColor { get; }
        /// <summary>
        /// 标题栏颜色
        /// </summary>
        Color BaseFormTitleColor { get; }
    }

5、添加对应的窗体或控件的主题接口

窗体的样式接口(例子)

   public interface IThemeFrmLock : IThemeBaseForm
    {
        Color FrmLock_TxtFillColor { get; }
        Color FrmLock_TxtRectColor { get; }
        Color FrmLock_TxtForeColor { get; }
        Color FrmLock_btnFillColor { get; }
        Color FrmLock_btnForeColor { get; }
        Color FrmLock_btnRectColor { get; }

    }

控件的样式接口(例子)

public interface IThemeUCFileItem : ITheme
    {
        Color UCFileItem_BackgroundColor { get; }
        Color UCFileItem_ForeColor { get; }
        Color UCFileItem_BoxColor { get; }
        Image UCFileItem_Img1 { get; }
        Image UCFileItem_Img2 { get; }
        Image UCFileItem_Img3 { get; }
        Image UCFileItem_Img4 { get; }
        Image UCFileItem_Img5 { get; }
    }

我这里做一个深色一个浅色主题

深色的

 /// <summary>
    /// 深色
    /// </summary>
    public partial class Dark :
        ITheme,
        IThemeBaseForm,       
        IThemeFrmLock,      
        IThemeUCFileItem      
    {

        public int Code { get { return 1; } }
        /// <summary>
        /// 基本窗体背景色
        /// </summary>
        public Color BaseFormBackgroundColor { get { return Color.FromArgb(37, 41, 59); } }
        /// <summary>
        /// 基本窗体文字颜色
        /// </summary>
        public Color BaseFormForeColor { get { return Color.White; } }
        public Color BaseFormTitleColor { get { return Color.FromArgb(38, 45, 67); } }

        /// <summary>
        /// 初始化操作
        /// </summary>
        public void Init()
        {
            //这里做一些修改主题时候的业务
        }
        #region 重写运算符
        /// <summary>
        /// 重写==
        /// </summary>
        /// <param name="lhs"></param>
        /// <param name="rhs"></param>
        /// <returns></returns>
        public static bool operator ==(Dark lhs, ITheme rhs)
        {

            if (lhs == null && rhs == null)
                return true;
            else
            {
                if (lhs != null && rhs != null)
                {
                    if (lhs.Code == rhs.Code)
                        return true;
                    else
                        return false;
                }
                else
                    return false;
            }
        }

        /// <summary>
        /// 重写!=
        /// </summary>
        /// <param name="lhs"></param>
        /// <param name="rhs"></param>
        /// <returns></returns>
        public static bool operator !=(Dark lhs, ITheme rhs)
        {

            if (lhs == null && rhs == null)
                return false;
            else
            {
                if (lhs != null && rhs != null)
                {
                    if (lhs.Code == rhs.Code)
                        return false;
                    else
                        return true;
                }
                else
                    return true;
            }
        }


        public override bool Equals(object obj)
        {
            if (obj == null || GetType() != obj.GetType())
            {
                return false;
            }
            if (obj is ITheme)
            {
                if (Code == ((ITheme)obj).Code)
                    return true;
                else
                    return false;
            }
            else
            {
                return false;
            }
        }


        public override int GetHashCode()
        {
            return base.GetHashCode();
        }
        #endregion
    }

浅色的也一样 只需要实现

ITheme,
IThemeBaseForm,       
IThemeFrmLock,      
IThemeUCFileItem     这些接口就行(定义的控件接口,这里都要进行实现)然后添加具体的控件主题实现类
 /// <summary>
    /// FrmLock
    /// </summary>
    public partial class Dark
    {
        public Color FrmLock_TxtFillColor { get { return Color.FromArgb(34, 40, 60); } }
        public Color FrmLock_TxtRectColor { get { return Color.FromArgb(65, 75, 101); } }
        public Color FrmLock_TxtForeColor { get { return Color.White; } }
        public Color FrmLock_btnFillColor { get { return Color.FromArgb(46, 54, 76); } }
        public Color FrmLock_btnForeColor { get { return Color.FromArgb(175, 193, 225); } }
        public Color FrmLock_btnRectColor { get { return Color.FromArgb(65, 75, 101); } }
    }
然后就是去控件或窗体里面做事情了,实现接口Theme.IThemeControl,构造函数里面添加CheckedThemeEvent事件
 public partial class FrmLock : FrmWithTitle,Theme.IThemeControl
    {

        public FrmLock()
        {
            try
            {
                InitializeComponent();               
                Theme.Theme.CheckedThemeEvent += Theme_CheckedThemeEvent;
            }
            catch (Exception ex)
            {
                
            }
        }
        void Theme_CheckedThemeEvent(Theme.ITheme theme)
        {
            if (this.Visible)
            {
                ThisTheme = theme;
            }
        }

VisibleChanged事件添加内容

  private void FrmLock_VisibleChanged(object sender, EventArgs e)
        {
            if (Visible)
            {
                ThisTheme = Theme.Theme.CurrentTheme;
            }
        }

实现的接口

  Theme.ITheme thisTheme = null;
        /// <summary>
        /// 当前页面正在使用的主题
        /// </summary>
        public Theme.ITheme ThisTheme
        {
            get
            {
                if (thisTheme == null)
                {
                    ThisTheme = Theme.Theme.CurrentTheme;
                }
                return thisTheme;
            }
            set
            {
                if (thisTheme != value)
                {
                    thisTheme = value;
                    Theme.Theme.LoadTheme(this);
                }
            }
        }

        public void ResetTheme()
        {
            var t = (Theme.IThemeFrmLock)ThisTheme;
            this.BackColor = t.BaseFormBackgroundColor;
            this.lblTitle.BackColor = t.BaseFormTitleColor;
            this.lblTitle.ForeColor = t.BaseFormForeColor;

            ucControlBase1.FillColor = t.FrmLock_TxtFillColor;
            ucControlBase1.RectColor = t.FrmLock_TxtRectColor;
            txtPW.BackColor = t.FrmLock_TxtFillColor;
            txtPW.ForeColor = t.FrmLock_TxtForeColor;
            tongyong_btnPaiZhaoPath.FillColor = t.FrmLock_btnFillColor;
            tongyong_btnPaiZhaoPath.RectColor = t.FrmLock_btnRectColor;
            tongyong_btnPaiZhaoPath.ForeColor = t.FrmLock_btnForeColor;
        }

以上就是修改代码,下面看调用

Theme.Theme.CurrentTheme = new Theme.Dark();

效果

WinForm 主题实现方法