Reputation: 339
I have created a custom button (a CloseButton) that looks like this:
When I move my mouse over the button it changes colour to red, like this:
I want to redraw the "X" on the button in white when the mouse is over the button, to look something like this (I've doctored the image above in paint to show how I want it to look):
I'm not sure how to go about doing this.
My custom button basically inherits from the regular Button control, with a few custom settings. Code is as follows:
public class CloseButton : Button
{
public CloseButton()
{
this.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
this.FlatAppearance.BorderSize = 0;
this.FlatAppearance.MouseDownBackColor = System.Drawing.Color.IndianRed;
this.FlatAppearance.MouseOverBackColor = System.Drawing.Color.DarkRed;
this.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
this.Size = new System.Drawing.Size(50, 30);
this.UseVisualStyleBackColor = true;
}
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
GraphicsPath gPath;
Pen gPen;
gPen = new Pen(System.Drawing.SystemColors.ControlText);
gPath = new GraphicsPath();
gPath.AddLine(20, 10, 30, 20);
gPath.CloseFigure();
gPath.AddLine(20, 20, 30, 10);
gPath.CloseFigure();
e.Graphics.DrawPath(gPen, gPath);
}
}
I've tried changing the OnPaint() method so that the pen colour is determined by the backcolour of the control, as follows:
if ((this.BackColor.Equals(System.Drawing.Color.DarkRed) || this.BackColor.Equals(System.Drawing.Color.IndianRed))
{
gPen = new Pen(System.Drawing.SystemColors.ControlLightLight;
}
else
{
gPen = new Pen(System.Drawing.SystemColors.ControlText;
}
Then in my MouseEnter and Click handlers I invalidate and refresh the control as follows:
_BtnClose.Invalidate();
_BtnClose.Refresh();
This doesn't do anything. How can I achieve what I am trying to do? If I'm stuck I can always just create another custom button with a white X drawn on it, and just show/hide this button as required, but I'd like to avoid doing that if possible
Upvotes: 2
Views: 801
Reputation: 125257
Another easy option to draw the cross and change the cross color:
✕
character for drawing the cross. You can easily change its size by Font size.✕
color, it's enough to handle MouseEnter
and MouseLeave
and assign ForeColor
. It will redraw the button.☐
character for Maximize, ❐
for Restore and ━
for Minimize:using System;
using System.Drawing;
using System.Windows.Forms;
public class MyCloseButton : Button
{
public MyCloseButton()
{
Anchor = AnchorStyles.Top | AnchorStyles.Right;
FlatAppearance.BorderSize = 0;
FlatAppearance.MouseDownBackColor = Color.IndianRed;
FlatAppearance.MouseOverBackColor = Color.DarkRed;
FlatStyle = FlatStyle.Flat;
Font = new Font(Font.FontFamily, 13);
Size = new Size(56, 36);
UseVisualStyleBackColor = false;
MouseLeave += (s, e) => ForeColor = Color.Black;
MouseEnter += (s, e) => ForeColor = Color.White;
}
public override string Text { get => ""; set => base.Text = ""; }
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
TextRenderer.DrawText(e.Graphics, "✕", Font, ClientRectangle, ForeColor);
}
}
You can make the button non-selectable to prevent getting selected by mouse or keyboard by adding the following line to constructor:
SetStyle(ControlStyles.Selectable, false);
You can add the close behavior to the button ForeColor
by adding the following code:
protected override void OnClick(EventArgs e)
{
base.OnClick(e);
FindForm()?.Close();
}
If you want a bigger button with a bigger cross, change the button size and its font size:
Upvotes: 1
Reputation: 39142
I'd write it like this, then:
public class CloseButton : Button
{
GraphicsPath gPath;
public CloseButton()
{
this.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
this.FlatAppearance.BorderSize = 0;
this.FlatAppearance.MouseDownBackColor = System.Drawing.Color.IndianRed;
this.FlatAppearance.MouseOverBackColor = System.Drawing.Color.DarkRed;
this.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
this.Size = new System.Drawing.Size(50, 30);
this.UseVisualStyleBackColor = true;
gPath = new GraphicsPath();
gPath.AddLine(20, 10, 30, 20);
gPath.CloseFigure();
gPath.AddLine(20, 20, 30, 10);
gPath.CloseFigure();
}
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
bool cursorInControl = this.ClientRectangle.Contains(this.PointToClient(Cursor.Position));
using (Pen gPen = new Pen(cursorInControl ? System.Drawing.SystemColors.ControlLightLight : System.Drawing.SystemColors.ControlText))
{
e.Graphics.DrawPath(gPen, gPath);
}
}
}
The GraphicsPath never changes, so it is declared at control level and kept for future use instead of re-creating it each time. Also, whenever you create a Pen, you must also dispose of it, thus the using
block. Finally, we convert the current Cursor.Position to client coordinates so we can determine whether it is within the control. This is used to switch the colors when we draw the GraphicsPath.
Upvotes: 2