Shaped Button
Microsoft .NET Framework, ASP.NET, Visual C# (CSharp, C Sharp, C-Sharp) Developer Training, Visual Studio
Although this is not part of the exam, this section shows what can be achieved by extending the Button class. The following image displays an application that has four shaped buttons within it.
To demonstrate how this was achieved, follow the steps below:
- Add a new
UserControlto your application. - View the code and change the inherited type from
UserControltoButton.public partial class simonButton : Button { public simonButton() { InitializeComponent(); } }
- The shape of the button is achieved through the use of two
GraphicsPathobjects. Declare these in the top of the button class.public partial class simonButton : Button { private GraphicsPath path; private GraphicsPath innerPath; ...
Thepathdenotes the outline of the button, while theinnerPathdenotes the shape of the flat surface of the button. - Now override the
OnPaintmethod of the button, to take care of the drawing, so that is looks like the following code.protected override void OnPaint(PaintEventArgs pevent) { Graphics g = pevent.Graphics; g.SmoothingMode = SmoothingMode.AntiAlias; }
So that we do not get jagged curves, set theSmoothingModetoAntiAlias. - The
pathobject is filled with aLinearGradientBrush. This is simple to achieve by supplying a rectangle and a newLinearGradientBrush.// Create Rectangle To Limit brush area. Rectangle rect = new Rectangle(0, 0, 150, 150); LinearGradientBrush linearBrush = new LinearGradientBrush(rect, Color.FromArgb(40,40,40), this.ForeColor, 225);
Next we instantiate the
pathobject.path = new GraphicsPath();
Add items to the
pathobject to create the required shapepath.AddArc(0, 0, 270, 270, 180, 90); path.AddArc(120, 0, 30, 30, 270, 90); path.AddLine(150, 0, 150, 85); path.AddArc(100, 100, 100, 100, -90, -90); path.AddLine(100, 150, 0, 150); path.AddArc(0, 120, 30, 30, 90, 90); path.AddArc(0, 0, 270, 270, 180, 90);
Fill the
pathg.FillPath(linearBrush, path);
Finally, dispose of the brush to free memory
linearBrush.Dispose();
- The
innerPathobject is filled with aSolidBrush.Brush b = new SolidBrush(this.ForeColor);
Next we instantiate the
innerPathobject.innerPath = new GraphicsPath();
Add items to the
innerPathobject to create the required shapeinnerPath.AddArc(10, 10, 250, 250, 180, 90); innerPath.AddArc(130, 10, 10, 10, 270, 90); innerPath.AddLine(140, 0, 140, 90); innerPath.AddArc(90, 90, 100, 100, -90, -90); innerPath.AddLine(90, 140, 10, 140); innerPath.AddArc(10, 130, 10, 10, 90, 90);
Fill the
innerPathg.FillPath(b, innerPath);
Finally, dispose of the brush to free memory
b.Dispose();
- So far, this draws our shaped button, but you can click anywhere in the associated rectangle, so to stop this, simply set the
Regionproperty of the button topath.this.Region = new Region(path);
The button will now only accept clicks within the region of the shape. - So that the user has some feedback that they are over a button, changing the cursor is a simple thing to do. Override the
OnMouseEnterandOnMouseLeavemethods and change the cursor within them:protected override void OnMouseEnter(EventArgs e) { this.Cursor = Cursors.Hand; base.OnMouseEnter(e); } protected override void OnMouseLeave(EventArgs e) { this.Cursor = Cursors.Arrow; base.OnMouseLeave(e); }
- The button also needs visual feedback that it has been pressed. In this case, the button wants to appear as if a light has come on behind it. This requires several new items and some changes to the code. First off, a boolean value is required to store if the click has happened so that it can be drawn in the correct state.
private bool _clicked = false; public bool Clicked { get { return _clicked; } set { _clicked = value; Invalidate(); } }
Now override the
OnMouseDownandOnMouseUpto set theClickedstate accordingly.protected override void OnMouseDown(MouseEventArgs mevent) { _clicked = true; base.OnMouseDown(mevent); } protected override void OnMouseUp(MouseEventArgs mevent) { _clicked = false; base.OnMouseUp(mevent); }
Add a new brush.
PathGradientBrush pgbrush = new PathGradientBrush(innerPath); pgbrush.CenterPoint = new Point(75, 75); pgbrush.CenterColor = Color.White; pgbrush.SurroundColors = new Color[] { this.ForeColor };
Redraw the button according to the
Clickedstate.if (_clicked == false) { g.FillPath(linearBrush, path); g.FillPath(b, innerPath); } else { g.FillPath(linearBrush, path); g.FillPath(pgbrush, innerPath); }
Remember to dispose of the brush correctly. - For a full code listing click here.
