Reputation: 235
In my application I have got an option to customise display a bit. Basically, now it is about changing buttons' and pictureboxes' images, changing form icons etc. As you can see in the code I provided bellow. So, in this case, I have done this by simply loading a bunch of resources (images) and then when I change theme:
if (Properties.Settings.Default.Theme == "Purple")
{
foreach (var form in Application.OpenForms.Cast<Form>())
{
form.Icon = Properties.Resources.Purple;
}
Main f1 = (Main)Application.OpenForms["Main"];
Settings f2 = (Settings)Application.OpenForms["Settings"];
f1.btn_Exit.Image = Properties.Resources.EXIT_purple;
f2.btn_SaveSettings.Image = Properties.Resources.SaveSettings_purple;
f1.pictureBox1.Image = Properties.Resources.Preview_purple;
}
This dramatically increases the size of the application, so I came up with changing BackColor instead of loading another images. I have tried to solve this in the following way:
if (Properties.Settings.Default.Theme == "Purple")
{
foreach (var form in Application.OpenForms.Cast<Form>())
{
form.Icon = Properties.Resources.Purple;
}
Main f1 = (Main)Application.OpenForms["Main"];
Settings f2 = (Settings)Application.OpenForms["Settings"];
f1.btn_Exit.BackColor = Color.FromArgb(164, 57, 226);
f2.btn_SaveSettings.BackColor = Color.FromArgb(164, 57, 226);
f2.pictureBox1.BackColor = Color.FromArgb(164, 57, 226);
}
So, form icon should be changed on all running forms and I have managed to successfully do so, but when it comes to buttons and pictureboxes, I am not seeing any results, that is buttons and pictureboxes are simply not changing. Besides form icons, I should change btn_Exit
located on the Main
form, btn_SaveSettings
located on the Settings
form, and pictureBox1
located on the Settings
form as well.
How can I solve this issue?
Upvotes: 0
Views: 1971
Reputation: 2409
If it was me doing it I would make an interface. This interface would have a reference to the correct picture/icon/color for your different controls. The Settings for you application would hold an instance of the correct theme. Each form I would OnLoad update all the necessary items and call it a day. It's probably not the most elegant solution, but it would make it easy and quick when you go to add more themes.
This is what I was thinking about. I hope this clears up my approach.
public class Settings
{
public static ITheme Theme {get {return theme;}{set theme = value}}
theme = new DefaultTheme();
}
public interface ITheme
{
public Color BackgroundColor {get;}
public Color ButtonBackgroundColor { get;}
//... etc
}
public class DefaultTheme : ITheme
{
public Color BackgroundColor {get{ return Color.White;}}
public Color ButtonBackgroundColor { get { return Color.Gray;}}
}
from here you have 2 approaches. Both require you to put a Event "OnLoad" If you have 1 or 2 forms maybe put this code each Form (not recommended) or you could use an extension like method.
here is first approach. put the code directly in each frame.
public class SaveFrame : Frame
{
public SaveFrame()
{
InitializeComponents();
}
public Form_OnLoad()
{
var theme = Settings.Theme;
this.Background = theme.BackgroundColor;
foreach(Button b in this.Controls)
{
if(b != null)
b.Background = theme.ButtonBackgroundColor;
}
}
}
or create an extension method. and put it in the OnLoad
public static class FormExtensions
{
public static void UpdateTheme(this Form form, ITheme theme)
{
form.Background = theme.BackgroundColor;
foreach(Button b in form.Controls)
{
if(b != null)
b.Background = theme.ButtonBackgroundColor;
}
}
}
public class SaveFrame : Form
{
public SaveFrame()
{
InitializeComponents();
}
public Form_OnLoad()
{
this.UpdateTheme(Settings.Theme);
}
}
public class MainFrame :Form
{
public MainFrame()
{
InitializeComponents();
}
public Form_OnLoad()
{
this.UpdateTheme(Settings.Theme);
}
}
Upvotes: 0