I found this page, which outlines how to change the rendering for a MenuStrip and its items.
I want to use this, but the problem is that the highlight color when you hover over a button doesn't match it.
Is there any way to change the highlight color from blue to yellow? I've tried using the MouseHover and MouseLeave events, but for some reason they're really slow, and they change the button to a solid color, which looks bad, but leaves a border on the edge of the button that doesn't change.
In the designer:
this.ButtonName.MouseHover += new System.EventHandler(button_mousehover);
And then in the Code:
private void button_mousehover(object sender, EventArgs e)
{
Button btn = sender as Button;
btn.BackColor = Color.Yellow;
}
Is there anything as easy as in the link I posted above to change the highlight color from blue to something else?
Here's the code for changing the rendering of the menu strip:
private void myForm Load(object sender, EventArgs e)
{
myMenuStrip.Renderer = new MenuRenderer();
{
private class MenuRenderer : ToolStripProfessionalRenderer
{
public MenuRenderer() : base(new MyColors()) { }
}
private class MyColors : ProfessionalColorTable
{
public override Color MenuItemSelectedGradientBegin
{
get { return Color.Orange; }
}
public override Color MenuItemSelectedGradientEnd
{
get { return Color.Yellow; }
}
public override Color MenuItemPressedGradientBegin
{
get{ return Color.Yellow; }
}
public override Color MenuItemPressedGradientEnd
{
get { return Color.Orange; }
}
public override Color MenuItemSelected
{
get { return Color.Gold; }
}
}
So it'll change the background of a hovered-over menu item to an orange-yellow gradient, change it to a yellow-orange gradient on click, and any item in the menu will have a gold highlight on hovering.
What I'm trying to do is do that last part (change the highlight to gold/yellow) for the buttons in my form.
In the properties of the button:
under FlatStyle, select Flat.
Then, expand FlatAppearance and under MouseOverBackColor, select the highlight color you want. Alternatively, you can also enter the RGB color you want, under the MouseOverBackColor.
You can take a look at the Button Renderer.
Why do you want to override the renderer when you can simply subscribe to the MouseHover event like so:
this.someButtonName.MouseHover += (s,e) =>
{
this.someButtonName.BackColor = Color.Yellow;
};
I recommend you use a mouse leave too in order to reset the button to it's initial color when your mouse isn't on it anymore.
Related
Basically I'm creating my own form
public class CryForm : System.Windows.Forms.Form
for several reasons, one of which is a very specific style.
Therefore I want the Form.BackColor property to be 'locked' to Black, so that it cannot be changed from 'outside'
CryForm1.BackColor = Color.whatevercolorulike
should not be possible anymore.
Is there any way to achieve this or should I come up with a completely different solution?
This should work, although you won't get a compile time error when trying to set the property.
public override Color BackColor
{
get { return Color.Black; }
set { }
}
You can make it explicit that changing the BackColor is not supported. It will result in a runtime exception if anything is trying to change it:
public override Color BackColor
{
get { return Color.Black; }
set { throw new NotSupportedException("CryForm doesn't support changing the BackColor"); }
}
If your need to is to 'lock' the background color of the form at design-time, probably the most efficient and least error-prone solution would be to override the BackColor property and mark with an attribute, then inherit from the form in the designer.
You could declare:
public class FixedBackgroundForm : Form
{
protected new static readonly Color DefaultBackColor = Color.Black;
[Browsable(false),
DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public override Color BackColor
{
get { return base.BackColor; }
set { base.BackColor = value; }
}
public FixedBackgroundForm()
{
this.BackColor = DefaultBackColor
}
}
Which would both set your form background color to Black automatically, and prevent changing of the background color from within the designer.
When you add new forms to your project, inherit from FixedBackgroundForm:
public partial class Form1 : FixedBackgroundForm
{
...
}
If you needed to "fix" the background color to black no matter what, simply use this line for the BackColor setter:
set { base.BackColor = DefaultBackColor; }
Another option is to add this to the form load event:
this.BackColorChanged += (s, e2) =>
{
if (this.BackColor != Color.Black)
this.BackColor = Color.Black;
};
Just add
public new Color BackColor
{
get { return Color.Black; }
}
to your code!
I have an application with a MenuStrip and every time I hover my mouse over a MenuItem, it highlights blue.
I have tried to change the BackColor and ForeColor but that wasn't the problem.
Is there a way to disable this?
This would be incredibly un-useful to the end user:
internal class NoHighlightRenderer : ToolStripProfessionalRenderer {
protected override void OnRenderMenuItemBackground(ToolStripItemRenderEventArgs e) {
if (e.Item.OwnerItem == null) {
base.OnRenderMenuItemBackground(e);
}
}
}
Then apply it to your MenuStrip:
menuStrip1.Renderer = new NoHighlightRenderer();
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!
I've got a usercontrol (derived from ContainerControl) which I'm filling using a gradient. The first gradient color may or may not be a system color, like SystemColors.Highlight.
The second gradient color is derived from the first one, by means of ControlPaint.Light(firstColor) or something similar.
I can easily handle changing system colors at runtime by overriding OnSystemColorsChanged, and it works without any trouble. But if the control is placed on a form at design time, and then the system colors are changed, the second color stays the same, probably due to OnSystemColorsChanged not being called at design time.
I can reset the second color manually since I provide ShouldSerialize- and Reset- methods for the second color property, and therefore the default value for that property changes accordingly when the system color changes.
So, is there any way to catch a system color change at design time?
Edit:
Here's a minimized code sample:
public class Test : ContainerControl
{
public Test()
{
ResetColor1();
ResetColor2();
}
private bool _resetColor2;
// Color 1 stuff
private Color _color1 = Color.Empty;
public System.Drawing.Color Color1
{
get { return _color1; }
set
{
_resetColor2 = !ShouldSerializeColor2();
_color1 = value;
if (_resetColor2)
ResetColor2();
Invalidate();
}
}
// Defaults Color 1
private Color DefaultColor1 { get { return SystemColors.Highlight; } }
public bool ShouldSerializeColor1()
{
return !Color1.Equals(Color.Empty) && !Color1.Equals(DefaultColor1);
}
public void ResetColor1()
{
Color1 = DefaultColor1;
}
// Color 2 stuff
private Color _color2 = Color.Empty;
public System.Drawing.Color Color2
{
get { return _color2; }
set
{
_color2 = value;
Invalidate();
}
}
private Color DefaultColor2 { get { return ControlPaint.Light(Color1); } }
public bool ShouldSerializeColor2()
{
return !Color2.Equals(DefaultColor2);
}
public void ResetColor2()
{
Color2 = DefaultColor2;
}
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
using (LinearGradientBrush b = new LinearGradientBrush(ClientRectangle, Color1, Color2, LinearGradientMode.ForwardDiagonal))
e.Graphics.FillRectangle(b, this.ClientRectangle);
}
protected override void OnSystemColorsChanged(EventArgs e)
{
base.OnSystemColorsChanged(e);
if (_resetColor2)
ResetColor2();
}
}
If you put this control onto a form, this code will do the following:
Default Color1 to SystemColors.Highlight
Default Color2 to a lighter color
If Color2 is not changed manually, it will automatically derive from Color1
If system colors change at runtime, Color1 and Color2 will both change
If system colors change at design time, only Color1 will change
I wouldn't be too surprised if the event is suppressed in design mode, SystemEvents are tricky because they are static events. Solve your problem by setting a bool flag in the property setter for Color2 to indicate that it matches the default color. Always use ControlPaint.Light() when the flag is set.
You can subscribe to the SystemEvents.DisplaySettingsChanged event, I believe.
I have a Windows Forms application with some buttons for the F keys. When you place the mouse over the buttons the get grey, and when you click they get a slightly lighyer grey. I would like to mimic that behaviour with F key keystrokes... how would you do it?
Set the Form's KeyPreview property to true, handle the KeyDown and KeyUp events, track which function key(s) are pressed, and call the Invalidate method on the button for each key the went down or up.
Then, handle the button's Paint event, and, if its key is down, use the ButtonRenderer class to draw the button as if it were pressed.
Use Button.PerformClick().
Finally I implemented the button changing the background:
class FunctionButton : Button
{
private Color m_colorOver;
private bool m_isPressed;
public FunctionButton() : base()
{
m_isPressed = false;
}
protected override void OnGotFocus(EventArgs e)
{
OnMouseEnter(null);
base.OnGotFocus(e);
}
protected override void OnLostFocus(EventArgs e)
{
if (!m_isPressed)
{
OnMouseLeave(null);
}
base.OnLostFocus(e);
}
protected override void OnMouseLeave(EventArgs e)
{
if (!Focused && !m_isPressed)
{
base.OnMouseLeave(e);
}
}
public void FunctionKeyPressed()
{
// Handle just the first event
if (!m_isPressed)
{
m_isPressed = true;
m_colorOver = FlatAppearance.MouseOverBackColor;
FlatAppearance.MouseOverBackColor = FlatAppearance.MouseDownBackColor;
OnMouseEnter(null);
PerformClick();
}
}
public void FunctionKeyReleased()
{
m_isPressed = false;
FlatAppearance.MouseOverBackColor = m_colorOver;
if (Focused)
{
OnMouseEnter(null);
}
else
{
base.OnMouseLeave(null);
}
}
}
It is not the most clean way but it works fine. I would like more examples doing this with a cleaner and more elegant style.
SetCapture and ReleaseCapture might work.