Disable ToolStripMenuItem highlight? - c#

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();

Related

Is there any way to avoid listView flickering when updating the items?

private void downloader_Succeeded(object sender, EventArgs e)
{
FileDownloader.FileInfo fi = downloader.CurrentFile;
string name = fi.Path;
foreach (ListViewItem lvw in listView1.Items)
{
if (lvw.Text == name)
lvw.ForeColor = Color.Green;
}
label6.Text = countFilesDownloaded++.ToString();
}
Each time when it's coloring the item it's flickering.
I saw some answers but none of them is working.
I saw this answer:
Flickering answer
And this one
Flickering answer
Maybe i didn't use them right. But they didn't work.
Tried to add this to the form1 at the bottom:
protected override CreateParams CreateParams {
get {
var parms = base.CreateParams;
parms.Style &= ~0x02000000; // Turn off WS_CLIPCHILDREN
return parms;
}
}
Then tried to create instance of this each time a item was coloring inside the event.
I had your problem and after doing some research it appears that the ListView control repaints its entire area whenever you modify a single item. The solution is to subclass the ListView and filter out the WM_ERASEBKGND message. This did the trick for me.
For more information see here:
c# flickering Listview on update
public partial class ListViewNF : ListView
{
public ListViewNF()
{
}
public ListViewNF(IContainer container)
{
container.Add(this);
InitializeComponent();
//Activate double buffering
this.SetStyle(ControlStyles.OptimizedDoubleBuffer |
ControlStyles.AllPaintingInWmPaint, true);
//Enable the OnNotifyMessage event so we get a chance to filter out
// Windows messages before they get to the form's WndProc
this.SetStyle(ControlStyles.EnableNotifyMessage, true);
}
protected override void OnNotifyMessage(Message m)
{
//Filter out the WM_ERASEBKGND message
if (m.Msg != 0x14)
{
base.OnNotifyMessage(m);
}
}
}

Change WinForms button highlight color

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.

Linklabel dotted focus area not appear when got focus with hotkey

I have LinkLabel. If i press hotkey, linklable got focus, but dotted area are not appear!
When it got focus by 'Tab', he have dotted focus area:
Next, if press hotkey, dotted area always appear.
How do I get the dotted area immediately appeared with the help of hotkeys?
I found the problem. All the matter in the protected property ShowFocusCues. It is set to the false by default. When you focus control by the "Tab", ShowFocusCues set to the true.
It is an example how to set ShowFocusCues to true:
public class UGLinkLabel : LinkLabel
{
private bool _displayFocusCues = true;
protected override bool ShowFocusCues
{
get
{
return _displayFocusCues;
}
}
public bool DisplayFocusCues
{
get
{
return _displayFocusCues;
}
set
{
_displayFocusCues = value;
}
}
}

Read-only (visually) CheckBox

I need to have 2 groups of controls on the screen: inputs and outputs (so they have 2 states: On or Off). Thus CheckBox seems to be a good choice. Checking any output will set it.
However, when displaying inputs there will be no user interaction with it. User is only allowed to see its value, not to change it.
Question: how to make checkbos visually appears as read-only ?
Could think about possible solutions:
Make CheckBox disabled. Bad: there will be no tooltip (possible to solve it? by fake panel on top?) and visually disabled CheckBox is not nice (and I don't want to make user think it is disabled).
Use different control. Which one? Label doesn't have nice placeholder for the On/Off value. RadioButton look differently, but they usually means there is a single choice out of many, while values of inputs are independent.
Making own component. Drawing the whole CheckBox is a bit overkill (and honestly, I don't know how to do it to have Win7 appearance). Would it be possible to add only ReadOnly appearance to the box part easily?
What do you guys think?
There is a solution that is combination of the existing answers.
checkBox.ForeColor = Color.Gray; // Read-only appearance
checkBox.AutoCheck = false; // Read-only behavior
// Tooltip is possible because the checkbox is Enabled
var toolTip = new ToolTip();
toolTip.SetToolTip(checkBox, "This checkbox is read-only.");
The result is a CheckBox that
appears disabled with gray text
prevents the Checked value from changing when clicked
supports a Tooltip
You have to draw everything yourself. I think you should use some controls with correct layout to mimic it. Here is the demo code for you, note that it does not support AutoSize correctly. Because the drawn stuff is always wider than the default stuff (which the AutoSize works with), implementing the AutoSize is not easy, If you don't care too much about AutoSize, this would be the great control for you:
public class XCheckBox : CheckBox
{
public XCheckBox()
{
SetStyle(ControlStyles.Opaque, false);
ReadOnlyCheckedColor = Color.Green;
ReadOnlyUncheckedColor = Color.Gray;
}
public bool ReadOnly { get; set; }
public bool AlwaysShowCheck { get; set; }
public Color ReadOnlyCheckedColor { get; set; }
public Color ReadOnlyUncheckedColor { get; set; }
protected override void OnPaint(PaintEventArgs pevent)
{
if (ReadOnly)
{
pevent.Graphics.SmoothingMode = SmoothingMode.HighQuality;
pevent.Graphics.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAlias;
if (AlwaysShowCheck || Checked)
{
RenderCheck(pevent.Graphics);
}
RenderText(pevent.Graphics);
}
else base.OnPaint(pevent);
}
private void RenderCheck(Graphics g)
{
float fontScale = Font.Size / 8.25f;
Size glyphSize = CheckBoxRenderer.GetGlyphSize(g, System.Windows.Forms.VisualStyles.CheckBoxState.CheckedNormal);
glyphSize.Width = (int) (glyphSize.Width * fontScale);
glyphSize.Height = (int)(glyphSize.Height * fontScale);
string checkAlign = CheckAlign.ToString();
using (GraphicsPath gp = new GraphicsPath())
using (Pen pen = new Pen(Checked ? ReadOnlyCheckedColor : ReadOnlyUncheckedColor, 1.5f)
{
LineJoin = LineJoin.Round,
EndCap = LineCap.Round,
StartCap = LineCap.Round
})
{
gp.AddLine(new Point(3, 7), new Point(5, 10));
gp.AddLine(new Point(5, 10), new Point(8, 3));
float dx = checkAlign.EndsWith("Right") ? Math.Max(-4*fontScale, ClientSize.Width - glyphSize.Width - 4 * fontScale) :
checkAlign.EndsWith("Center") ? Math.Max(-4*fontScale, (ClientSize.Width - glyphSize.Width) / 2 - 4 * fontScale) : -4;
float dy = checkAlign.StartsWith("Bottom") ? Math.Max(-4*fontScale, ClientSize.Height - glyphSize.Height - 4*fontScale) :
checkAlign.StartsWith("Middle") ? Math.Max(-4*fontScale, (ClientSize.Height - glyphSize.Height) / 2 - 4*fontScale) : 0;
g.TranslateTransform(dx, dy);
g.ScaleTransform(1.5f*fontScale, 1.5f*fontScale);
g.DrawPath(pen, gp);
g.ResetTransform();
}
}
private void RenderText(Graphics g)
{
Size glyphSize = CheckBoxRenderer.GetGlyphSize(g, System.Windows.Forms.VisualStyles.CheckBoxState.CheckedNormal);
float fontScale = Font.Size / 8.25f;
glyphSize.Width = (int)(glyphSize.Width * fontScale);
glyphSize.Height = (int)(glyphSize.Height * fontScale);
string checkAlign = CheckAlign.ToString();
using (StringFormat sf = new StringFormat())
{
string alignment = TextAlign.ToString();
sf.LineAlignment = alignment.StartsWith("Top") ? StringAlignment.Near :
alignment.StartsWith("Middle") ? StringAlignment.Center : StringAlignment.Far;
sf.Alignment = alignment.EndsWith("Left") ? StringAlignment.Near :
alignment.EndsWith("Center") ? StringAlignment.Center : StringAlignment.Far;
sf.FormatFlags = StringFormatFlags.NoWrap | StringFormatFlags.NoClip;
Rectangle textRectangle = ClientRectangle;
if (checkAlign.EndsWith("Left"))
{
textRectangle.Width -= glyphSize.Width;
textRectangle.Offset(glyphSize.Width, 0);
}
else if (checkAlign.EndsWith("Right"))
{
textRectangle.Width -= glyphSize.Width;
textRectangle.X = 0;
}
g.DrawString(Text, Font, new SolidBrush(ForeColor), textRectangle, sf);
}
}
bool suppressCheckedChanged;
protected override void OnClick(EventArgs e)
{
if (ReadOnly) {
suppressCheckedChanged = true;
Checked = !Checked;
suppressCheckedChanged = false;
}
base.OnClick(e);
}
protected override void OnCheckedChanged(EventArgs e)
{
if (suppressCheckedChanged) return;
base.OnCheckedChanged(e);
}
}
NOTE: The code is not fully implemented, everything is kept as simple as possible. You can change the AlwaysShowCheck property to choose the ReadOnly unchecked state, it can be a gray tick mark or nothing. You can set the ReadOnly to true to make it Read-only visual.
AlwaysShowCheck is set to true (the ReadOnly unchecked state is indicated by a gray tick mark)
AlwaysShowCheck is set to false (the ReadOnly unchecked state is indicated by nothing)
This is an old post but still can be usefull so here is my solution.
In order to make a read-only behavior:
Disable highlight when the cursor is over the CheckBox
Disable reacting (logically or visibly) to a mouse click
Have tooltips enabled
We can inherit the CheckBox class and disable mouse and keyboard interaction:
public class ReadOnlyCheckBox : CheckBox
{
[System.ComponentModel.Category("Behavior")]
[System.ComponentModel.DefaultValue(false)]
public bool ReadOnly { get; set; } = false;
protected override void OnMouseEnter(EventArgs e)
{
// Disable highlight when the cursor is over the CheckBox
if (!ReadOnly) base.OnMouseEnter(e);
}
protected override void OnMouseDown(MouseEventArgs e)
{
// Disable reacting (logically or visibly) to a mouse click
if (!ReadOnly) base.OnMouseDown(e);
}
protected override void OnKeyDown(KeyEventArgs e)
{
// Suppress space key to disable checking/unchecking
if (!ReadOnly || e.KeyData != Keys.Space) base.OnKeyDown(e);
}
}
In order to make it visually apparent that the CheckBox is read-only, we can change the ForColor according to the ReadOnly property.
Note: changing the ForColor only changes the text color, the colors of the checkmark can only be changed by overriding the OnPaint method and repainting the CheckBox (as far as I know).
Here is an extended version of the previous code that changes the ForColor according to the ReadOnly property:
public class ReadOnlyCheckBox : CheckBox
{
private bool _readOnly = false;
private Color _readOnlyForeColor = Color.Gray;
private Color _normalForeColor = Color.Black;
[System.ComponentModel.Category("Behavior")]
[System.ComponentModel.DefaultValue(false)]
public bool ReadOnly
{
get => _readOnly;
set
{
if (_readOnly != value)
{
_readOnly = value;
UpdateForColor();
}
}
}
[System.ComponentModel.Category("Appearance")]
[System.ComponentModel.DefaultValue(typeof(Color), "Black")]
public Color NormalForeColor
{
get => _normalForeColor;
set
{
if (_normalForeColor != value)
{
_normalForeColor = value;
UpdateForColor();
}
}
}
[System.ComponentModel.Category("Appearance")]
[System.ComponentModel.DefaultValue(typeof(Color), "Gray")]
public Color ReadOnlyForeColor
{
get => _readOnlyForeColor;
set
{
if (_readOnlyForeColor != value)
{
_readOnlyForeColor = value;
UpdateForColor();
}
}
}
// Hide ForeColor from the editor
[System.ComponentModel.Browsable(false)]
[System.ComponentModel.EditorBrowsable(
System.ComponentModel.EditorBrowsableState.Never)]
public override Color ForeColor
{
get => base.ForeColor;
set => base.ForeColor = value;
}
public ReadOnlyCheckBox()
{
UpdateForColor();
}
private void UpdateForColor()
{
ForeColor = ReadOnly ? ReadOnlyForeColor : NormalForeColor;
}
protected override void OnMouseEnter(EventArgs e)
{
// Disable highlight when the cursor is over the CheckBox
if (!ReadOnly) base.OnMouseEnter(e);
}
protected override void OnMouseDown(MouseEventArgs e)
{
// Disable reacting (logically or visibly) to a mouse click
if (!ReadOnly) base.OnMouseDown(e);
}
protected override void OnKeyDown(KeyEventArgs e)
{
// Suppress space key to disable checking/unchecking
if (!ReadOnly || e.KeyData != Keys.Space) base.OnKeyDown(e);
}
}
So far the easiest solution (credits go to ShadowWizard) is to set ForeColor = Color.Gray, this makes user think, what CheckBox is disabled.
Compared to Enabled = false, pluses are:
ToolTip is working;
box part looks pretty (it react on mouse hovering and is very clearly seen whenever is checked or unchecked).
No minuses.
It is not necessary to write the entire control, just write a derivative of Checkbox.
A ReadOnly property is added to the control, this causes the control to handle when it can change its value.
public class CheckBoxReadOnly : CheckBox
{
private bool _readOnly = false;
[DefaultValue(false)]
public bool ReadOnly
{
get { return _readOnly; }
set
{
if (_readOnly != value)
{
_readOnly = value;
OnReadOnlyChanged(new EventArgs());
}
}
}
int _flag = 0;
public event EventHandler ReadOnlyChanged;
protected void OnReadOnlyChanged(EventArgs e)
{
ReadOnlyChanged?.Invoke(this, e);
}
protected override void OnCheckedChanged(EventArgs e)
{
if (ReadOnly)
{
_flag++;
if (_flag == 1)
Checked = !Checked;
}
else
{
base.OnCheckedChanged(e);
}
_flag = 0;
}
}
You may provide a listener for an event of clicking on CheckBox, as there's ability to cancel its usual flow at runtime.
In the Property table just make selection mode to none.
Visual studio has now it available under:
Properties -> Properties -> ReadOnly :)

Simulate flat button mouse MouseDown and MouseOver

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.

Categories

Resources