I'm coloring a menustrip to match my apps theme. However, every time I attempt it, I get this strange visual anomaly to the left of panel separators (the white rectangle) There is also some odd positioning of check-boxes also (possibly related?).
What is causing this, and how do I remove it?
Thank you
Example code:
private Color MainColor = Color.FromArgb(39, 40, 34);
public class MenuStripRenderer : ToolStripProfessionalRenderer
{
protected override void OnRenderMenuItemBackground(ToolStripItemRenderEventArgs e)
{
Rectangle rect = new Rectangle(Point.Empty, e.Item.Size);
if (e.Item.Selected)
{
Color color = Color.FromArgb(24, 25, 19);
using (SolidBrush brush = new SolidBrush(color))
e.Graphics.FillRectangle(brush, rect);
}
else
{
using (SolidBrush brush = new SolidBrush(MainColor))
e.Graphics.FillRectangle(brush, rect);
}
}
protected override void OnRenderItemText(ToolStripItemTextRenderEventArgs e)
{
e.Item.ForeColor = Color.White;
base.OnRenderItemText(e);
}
protected override void OnRenderSeparator(ToolStripSeparatorRenderEventArgs e)
{
base.OnRenderSeparator(e);
}
public MenuStripRenderer() : base(new MenuStripColors()) { }
}
public class MenuStripColors : ProfessionalColorTable
{
public override Color ToolStripDropDownBackground
{
get { return MainColor; }
}
public override Color ToolStripContentPanelGradientBegin
{
get { return MainColor; }
}
public override Color ToolStripContentPanelGradientEnd
{
get { return MainColor; }
}
public override Color MenuItemSelected
{
get { return MainColor; }
}
public override Color MenuItemBorder
{
get { return MainColor; }
}
public override Color MenuItemSelectedGradientBegin
{
get { return MainColor; }
}
public override Color MenuItemSelectedGradientEnd
{
get { return MainColor; }
}
public override Color MenuBorder
{
get { return MainColor; }
}
}
// In the forms Load()
this.menuStrip1.Renderer = new MenuStripRenderer();
this.menuStrip1.BackColor = MainColor;
this.menuStrip1.ForeColor = Color.White;
I believe you have to override the ImageMargin drawing, too:
protected override void OnRenderImageMargin(ToolStripRenderEventArgs e) {
//base.OnRenderImageMargin(e);
using (SolidBrush brush = new SolidBrush(MainColor)) {
e.Graphics.FillRectangle(brush, e.AffectedBounds);
}
}
I don't know what is causing your check mark issue since I can't duplicate that issue on my machine. I'm guessing maybe that's a graphic DPI setting in your windows.
Related
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;
Please look carefully at the picture
How can I change the color of the white parts in the image below?
I used :
ToolStripManager - ProfessionalColorTable - ToolStripProfessionalRenderer
but they weren't useful.
I want my menu to look like the image below.No white parts.
I used the following method to solve this problem, but it didn't help.
First I created the class "MyProfessionalColors" and inherited from "ProfessionalColorTable".
then I Override all the Properties related to the MenuStrip.
class MyProfessionalColors : ProfessionalColorTable
{
public override Color MenuStripGradientBegin
{
get
{
return Color.FromArgb(35, 35, 35);
}
}
public override Color MenuStripGradientEnd
{
get
{
return Color.FromArgb(35, 35, 35);
}
}
public override Color MenuItemPressedGradientBegin
{
get
{
return Color.FromArgb(20, 20, 20);
}
}
public override Color MenuItemPressedGradientMiddle
{
get
{
return Color.FromArgb(20, 20, 20);
}
}
public override Color MenuItemPressedGradientEnd
{
get
{
return Color.FromArgb(20, 20, 20);
}
}
public override Color MenuBorder
{
get
{
return Color.FromArgb(20, 20, 20);
}
}
public override Color MenuItemSelected
{
get
{
return Color.FromArgb(50, 50, 50);
}
}
public override Color MenuItemSelectedGradientBegin
{
get
{
return Color.FromArgb(50, 50, 50);
}
}
public override Color MenuItemSelectedGradientEnd
{
get
{
return Color.FromArgb(50, 50, 50);
}
}
public override Color MenuItemBorder
{
get
{
return Color.FromArgb(35, 35, 35);
}
}
}
Then I used it
ToolStripManager.Renderer = new ToolStripProfessionalRenderer
(new MyProfessionalColors());
But part of the control didn't change color.
How can I change that part?
Do I need to create a custom control and use it?
I am creating a button with a gradient in Xamarin forms. I am successfully making it but when i later on in the code try to update its color, nothing happens in the UI.
This is how the project is setup:
XAML:
<controls:FullyColoredGradient x:Name = "SelectedBackground" StartColor = "Purple" EndColor="Yellow" />
If i then later on the code do a void and try to update these colors like this:
SelectedBackground.EndColor = Color.Red;
SelectedBackground.StartColor = Color.Blue;
Then nothing happens. They do not recolor.
This is how my shared code looks:
public class FullyColoredGradient : Button
{
public static readonly BindableProperty StartColorProperty =
BindableProperty.Create(nameof(StartColor),
typeof(Color), typeof(FullyColoredGradient),
Color.Default);
public Color StartColor
{
get { return (Color)GetValue(StartColorProperty); }
set { SetValue(StartColorProperty, value); }
}
public static readonly BindableProperty EndColorProperty =
BindableProperty.Create(nameof(EndColor),
typeof(Color), typeof(FullyColoredGradient),
Color.Default);
public Color EndColor
{
get { return (Color)GetValue(EndColorProperty); }
set { SetValue(EndColorProperty, value); }
}
}
And this is my iOS renderer:
public class TransparentGradientColor_iOS : ButtonRenderer
{
CGRect rect;
CAGradientLayer gradientLayer;
public TransparentGradientColor_iOS() { }
public override void Draw(CGRect rect)
{
base.Draw(rect);
this.rect = rect;
FullyColoredGradient rcv = (FullyColoredGradient)Element;
if (rcv == null)
return;
this.ClipsToBounds = true;
this.Layer.MasksToBounds = true;
FullyColoredGradient stack = (FullyColoredGradient)this.Element;
CGColor startColor = stack.StartColor.ToCGColor();
CGColor endColor = stack.EndColor.ToCGColor();
#region for Vertical Gradient
this.gradientLayer = new CAGradientLayer()
{
StartPoint = new CGPoint(0, 0.5),
EndPoint = new CGPoint(1, 0.5)
};
#endregion
gradientLayer.Frame = rect;
gradientLayer.Colors = new CGColor[] { startColor, endColor };
NativeView.Layer.InsertSublayer(gradientLayer, 0);
}
protected override void OnElementChanged(ElementChangedEventArgs<Button> e)
{
base.OnElementChanged(e);
if (e.OldElement == null)
{
UpdateColor();
}
}
protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
{
base.OnElementPropertyChanged(sender, e);
UpdateColor();
}
void UpdateColor()
{
if (gradientLayer != null)
{
FullyColoredGradient stack = (FullyColoredGradient)this.Element;
CGColor startColor = Xamarin.Forms.Color.White.ToCGColor();
CGColor endColor = Xamarin.Forms.Color.White.ToCGColor();
gradientLayer.Colors = new CGColor[] { startColor, endColor };
}
}
}
I have used this custom renderer, this will apply gradient to all buttons(you can create custom button if you want), you can try this out:
[assembly: ExportRenderer(typeof(Button), typeof(CustomButtonRendereriOS))]
namespace XYZ.iOS.Renderer
{
public class CustomButtonRendereriOS : ButtonRenderer
{
//To apply gradient background to button
public override CGRect Frame
{
get
{
return base.Frame;
}
set
{
if (value.Width > 0 && value.Height > 0)
{
foreach (var layer in Control?.Layer.Sublayers.Where(layer => layer is CAGradientLayer))
layer.Frame = new CGRect(0, 0, value.Width, value.Height);
}
base.Frame = value;
}
}
protected override void OnElementChanged(ElementChangedEventArgs<Button> e)
{
base.OnElementChanged(e);
if (e.OldElement == null)
{
try
{
var gradient = new CAGradientLayer();
gradient.CornerRadius = Control.Layer.CornerRadius = 5;
gradient.Colors = new CGColor[]
{
UIColor.FromRGB(243, 112, 33).CGColor,
UIColor.FromRGB(226, 64, 64).CGColor
};
var layer = Control?.Layer.Sublayers.LastOrDefault();
Control?.Layer.InsertSublayerBelow(gradient, layer);
}
catch (Exception ex)
{
}
}
}
}
You can also use a gradient stack layout/ Frame as described here with help of custom renderer and use Tap Gesture of it for clicked event.
Gradient Button in Xamarin Forms
Hope this may solve your issue.
I currently have a custom Render set up for a MenuStrip on a C# windows forms application:
private class HeaderMenuRender : ProfessionalColorTable
{
public override Color MenuItemSelectedGradientBegin
{
get
{
return Color.Gray;
}
}
public override Color MenuItemSelectedGradientEnd
{
get
{
return Color.Gray;
}
}
public override Color MenuItemPressedGradientBegin
{
get
{
return Color.Gray;
}
}
public override Color MenuItemPressedGradientEnd
{
get
{
return Color.Gray;
}
}
public override Color MenuItemBorder
{
get
{
return Color.Gray;
}
}
public override Color MenuBorder
{
get
{
return Color.Gray;
}
}
}
This is then applied to an existing MenuStrip control on a form to create a Custom render.
However when running the application and making a selection from the menu which is displayed, despite the Menu options being the correct colour, there is a small 'White' (arguably could be 'Control' colour) bar which spans the length of the selected MenuStrip option (indicated in the blue box below):
Is there a particular property of the custom Renderer that I am not including or something I am missing which is setting this specific part of the MenuStrip selected item? The examples I have seen elsewhere do not seem to have this issue.
In the above code, it seems you made items Gray using BackColor property.
You can use override ToolStripDropDownBackground to return Color.Gray, this removes that while line.
Also you can overriding ImageMarginGradientBegin, ImageMarginGradientMiddle and ImageMarginGradientEnd to make also image/checkbox area Gray.
Here is What I added to your codes to get the desired value:
public override Color ImageMarginGradientBegin
{
get { return Color.Gray; }
}
public override Color ImageMarginGradientMiddle
{
get { return Color.Gray; }
}
public override Color ImageMarginGradientEnd
{
get { return Color.Gray; }
}
public override Color ToolStripDropDownBackground
{
get { return Color.Gray; }
}
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; }
}
...
}