I'm creating a Form and I want the menu bar to have different colors. There are many posts on this, I've managed to alter all the colors, except for a white block/line down the left hand side of the menu.
I'm using .Net Core 3.1, Windows Forms application.
The white block behind the Exit ToolstripMenuItem: it becomes wider when a Separator is used.
Thin white line on the above menus.
I'm using a professional renderer to override the colors.
public class DxColorTable : ToolStripProfessionalRenderer
{
public DxColorTable(dynamic theme) : base(new DxCols(theme)) { }
}
public class DxCols : ProfessionalColorTable
{
private readonly dynamic theme = DefaultTheme.Default;
public DxCols(dynamic theme)
{
this.theme = theme;
}
public override Color MenuBorder
{
get { return this.theme.MenuSelectedColor; }
}
public override Color MenuItemBorder
{
get { return this.theme.MenuSelectedColor; }
}
public override Color MenuItemPressedGradientBegin
{
get { return this.theme.MenuSelectedColor; }
}
public override Color MenuItemPressedGradientEnd
{
get { return this.theme.MenuSelectedColor; }
}
public override Color MenuItemSelected
{
get { return this.theme.MenuSelectedColor; }
}
public override Color MenuItemSelectedGradientBegin
{
get { return this.theme.MenuSelectedColor; }
}
public override Color MenuItemSelectedGradientEnd
{
get { return this.theme.MenuSelectedColor; }
}
public override Color ToolStripBorder
{
get { return this.theme.MenuBackgroundColor; }
}
public override Color ToolStripDropDownBackground
{
get { return this.theme.MenuBackgroundColor; }
}
public override Color ToolStripGradientBegin
{
get { return this.theme.MenuBackgroundColor; }
}
public override Color ToolStripGradientEnd
{
get { return this.theme.MenuBackgroundColor; }
}
public override Color ToolStripGradientMiddle
{
get { return this.theme.MenuBackgroundColor; }
}
public override Color ToolStripContentPanelGradientBegin
{
get
{
return this.theme.MenuBackgroundColor;
}
}
public override Color ToolStripContentPanelGradientEnd
{
get
{
return this.theme.MenuBackgroundColor;
}
}
}
You forgot to override the three properties that define the Image margin area.
You need to specify a Color value for the ImageMarginGradient part.
It's particularily visible when you add a ToolStripComboBox or a ToolStripSeparator. Note that it doesn't affect standard ToolStripMenuItems, even when these show an Image, when a Background Color has already been set in the designer.
public override Color ImageMarginGradientBegin => this.theme.MenuBackgroundColor;
public override Color ImageMarginGradientMiddle => this.theme.MenuBackgroundColor;
public override Color ImageMarginGradientEnd => this.theme.MenuBackgroundColor;
If you don't need to show Images, you can hide the Image margin area:
([Your ToolStripMenuItem].DropDown as ToolStripDropDownMenu).ShowImageMargin = false;
This question already has answers here:
How to change menu hover color
(4 answers)
Closed 7 years ago.
I have looked into all search results from StackOverflow to no avail, including: How to change menu hover color
I have a menu strip which is black with white font color. When you select it the font stays white but the box turns white too. How do i set the "selected" back color of a menu item?
By "selected" i mean you clicked on the menu option. NOT hover.
https://msdn.microsoft.com/en-us/library/System.Windows.Forms.ProfessionalColorTable(v=vs.110).aspx
I checked this out but none of these targeted the top tier menu item.
private class MyRenderer : ToolStripProfessionalRenderer
{
public MyRenderer() : base(new MyColors()) { }
}
private class MyColors : ProfessionalColorTable
{
public override Color ToolStripDropDownBackground
{
get { return Color.Black; }
}
public override Color MenuItemSelectedGradientBegin
{
get { return Color.Gray; }
}
public override Color MenuItemSelectedGradientEnd
{
get { return Color.Red; }
}
}
Use MenuItemPressedGradientBegin / End instead of MenuItemSelectedGradientBegin / End to change the color of the "primary" bar.
Menu.Renderer = new MyRenderer();
private class MyRenderer : ToolStripProfessionalRenderer
{
public MyRenderer() : base(new MyColors()) { }
}
private class MyColors : ProfessionalColorTable
{
public override Color MenuItemPressedGradientBegin
{
get { return Color.Gray; }
}
public override Color MenuItemPressedGradientEnd
{
get { return Color.Red; }
}
}
I have a MenuStrip and I want to change it's color. So far, I have this code:
public class TestColorTable : ProfessionalColorTable
{
public override Color MenuItemSelected
{
get{ return Color.LightGray; } // Don't mind the colors...
}
public override Color MenuItemBorder
{
get { return Color.LightGray; }
}
public override Color MenuItemSelectedGradientBegin
{
get { return Color.LightGray; }
}
public override Color MenuItemSelectedGradientEnd
{
get { return Color.LightGray; }
}
public override Color MenuItemPressedGradientBegin
{
get { return Color.DimGray; }
}
public override Color MenuItemPressedGradientEnd
{
get { return Color.DimGray; }
}
public override Color MenuBorder
{
get { return Color.LightGray; }
}
}
With this code, as well as the designer, I managed to change the color of almost every element of my MenuStrip. Almost.
Here are the results:
As you can see, there are two issues: 1) The two separators and 2) That thin white border around the submenus.
Any ideas on how to change the color of those two parts of my MenuStrip?
For the separator color try overriding the SeparatorDark and or SeparatorLight property of the ProfessionalColorTable class.
As for the thin white border around the submenus..., well, its actually not a border. It's the ToolStripDropDown (the submenu) background itself. Try overriding the ToolStripDropDownBackground property of the ProfessionalColorTable class to change its color.
Example:
public class TestColorTable : ProfessionalColorTable
{
...
public override Color SeparatorDark
{
get { return Color.DimGray; }
}
public override Color ToolStripDropDownBackground
{
get { return Color.DimGray; }
}
...
}
I have a custom form which extends Form, and it overrides the OnPaint method to draw the form in a specific design using the Theme. I have a custom class "Theme" which contains four colors to set on the form:
public class Theme
{
public Color BackColor { get; set; }
public Color MouseHoverColor { get; set; }
public Color ThemeColor { get; set; }
public Color ForeColor { get; set; }
}
The theme has a custom UITypeEditor which uses a custom theme editor using color pickers, which I have tested and works fine:
public class ThemeTypeEditor : UITypeEditor
{
public override UITypeEditorEditStyle GetEditStyle(ITypeDescriptorContext context)
{
return UITypeEditorEditStyle.Modal;
}
public override object EditValue(ITypeDescriptorContext context, IServiceProvider provider, object value)
{
var editor = new ThemeEditor((CustomForm) context.Instance);
if (editor.ShowDialog() == DialogResult.OK)
{
return editor.Theme;
}
return base.EditValue(context, provider, value);
}
}
I also have a static class "Themes" which contains a default theme for the form to use:
public static class Themes
{
public static Theme DarkGreen = new Theme
{
BackColor = Color.FromArgb(53, 53, 53),
ForeColor = Color.FromArgb(237, 234, 235),
MouseHoverColor = Color.FromArgb(65,65,65),
ThemeColor = Color.FromArgb(32, 203, 88)
};
}
And in my custom form, I have this property which is used by the OnPaint method:
private Theme theme = (Theme) Themes.DarkGreen;
[Category("Appearance"),
Description("Specifies the Theme for this form."),
Editor(typeof(ThemeTypeEditor), typeof(UITypeEditor)),
DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
public Theme Theme {
get { return theme; }
set {
theme = value;
Invalidate();
}
}
However, when I try to alter the theme in the designer on a new form which extends CustomForm, the designer does not update and the theme reverts to Themes.DarkGreen at runtime. I am unsure as to what I should be doing for this, as it is my understanding that I should be able to alter the theme and see the changes at design-time and runtime. As stated, the OnPaint method uses the Theme field above to draw the background color of the form and additional painted graphics. Any help is appreciated.
EDIT:
The form in the form designer changes when the project is built and run, but the actual running form remains unchanged. I would like to have the changes be immediately visible when the theme is applied, and for it to be applied on the built application.
EDIT 2:
I decided to show a MessageBox to debug this. I placed one in my ThemeTypeEditor's EditValue method before it returned the new theme, and sure enough, it works, and the theme values are correct. However, I also placed a MessageBox in my Theme Property setter, after Invalidate();, and nothing shows. It's like the property's set isn't being called at all.
I solved this by changing various things. The first was creating a base class named ComponentBase which extends Component and implement INotifyPropertyChanged:
public class ComponentBase : Component, INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
[NotifyPropertyChangedInvocator]
private void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
var handler = PropertyChanged;
if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
}
protected bool SetField<T>(ref T field, T value, [CallerMemberName] string propertyName = null)
{
if (EqualityComparer<T>.Default.Equals(field, value)) return false;
var changeService = GetService(typeof(IComponentChangeService)) as IComponentChangeService;
if (changeService != null)
changeService.OnComponentChanged(this, TypeDescriptor.GetProperties(this).Find(propertyName, false), field, value);
field = value;
OnPropertyChanged(propertyName);
return true;
}
}
This meant that I needed to remove the Auto-Property nature of the properties of my Theme. I changed the Editor of each Color in the Theme so that it used the color picker, and gave them a DesignerSerializationVisibility of Visible:
public sealed partial class Theme : ComponentBase
{
private Color backgroundColor;
[Category("Theme")]
[DisplayName("Background Color")]
[Editor(typeof (ThemeTypeEditor), typeof (UITypeEditor))]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
[TypeConverter(typeof (ThemeColorConverter))]
public Color BackgroundColor
{
get { return backgroundColor; }
set { SetField(ref backgroundColor, value); }
}
private Color foregroundColor;
[Category("Theme")]
[DisplayName("Foreground Color")]
[Editor(typeof(ThemeTypeEditor), typeof(UITypeEditor))]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
[TypeConverter(typeof(ThemeColorConverter))]
public Color ForegroundColor
{
get { return foregroundColor; }
set { SetField(ref foregroundColor, value); }
}
private Color highlightColor;
[Category("Theme")]
[DisplayName("Highlight Color")]
[Editor(typeof(ThemeTypeEditor), typeof(UITypeEditor))]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
[TypeConverter(typeof(ThemeColorConverter))]
public Color HighlightColor
{
get { return highlightColor; }
set { SetField(ref highlightColor, value); }
}
private Color borderColor;
[Category("Theme")]
[DisplayName("Border Color")]
[Editor(typeof(ThemeTypeEditor), typeof(UITypeEditor))]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
[TypeConverter(typeof(ThemeColorConverter))]
public Color BorderColor
{
get { return borderColor; }
set { SetField(ref borderColor, value); }
}
private Color themeColor;
[Category("Theme")]
[DisplayName("Theme Color")]
[Editor(typeof(ThemeTypeEditor), typeof(UITypeEditor))]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
[TypeConverter(typeof(ThemeColorConverter))]
public Color ThemeColor
{
get { return themeColor; }
set { SetField(ref themeColor, value); }
}
}
As the Theme in my custom form uses DesignerSerializationVisibility.Content, this allows code to be generated for the contents of the Theme, meaning that the individual colors in the Theme are updated both design-time and run-time:
private Theme theme;
[DisplayName("Theme")]
[Category("Appearance")]
[Description("Specifies the Theme for this form.")]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
public Theme Theme
{
get { return theme; }
set
{
theme = value;
Invalidate();
}
}
I coulnd find a proper name and phrase for this to explain, so here's a picture:
I'd like to change the white area's as shown above in the red circle to a desired color. I used the code below to change the other colors:
In the form itself:
menuStrip1.Renderer = new ToolStripProfessionalRenderer(new MenuStripColorTable());
The class:
class MenuStripColorTable : ProfessionalColorTable
{
private Color backColor = (Color) new ColorConverter().ConvertFromString("#333333");
//menu item background en border
public override Color MenuItemBorder
{
get{ return Color.White; }
}
public override Color MenuStripGradientBegin
{
get { return backColor; }
}
....
Any idea what I should override, or change?
By adding the folowing code I succesfully made teh white squares transparant:
Render class for menustrip:
public override Color ImageMarginGradientBegin
{
get { return Color.Transparent; }
}
public override Color ImageMarginGradientMiddle
{
get { return Color.Transparent; }
}
public override Color ImageMarginGradientEnd
{
get { return Color.Transparent; }
}
Altho the text isn't aligned to the left. But that's not that much of a problem. Credit to Franck aswell!