12

I am designing a toggle switch control using CheckBox, but currently my control only draws a circle. How can I draw round shapes like the below image and how can I change the location of the circle based on the value of the control to represent checked and unchecked states like the below image?

Enter image description here

Here is my code:

public class MyCheckBox:CheckBox
{
    public MyCheckBox()
    {
        this.Appearance = System.Windows.Forms.Appearance.Button;
        this.BackColor = Color.Transparent;
        this.TextAlign = ContentAlignment.MiddleCenter;
        this.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
        this.FlatAppearance.BorderColor = Color.RoyalBlue;
        this.FlatAppearance.BorderSize = 2;
    }

    protected override void OnPaint(PaintEventArgs e)
    {
        this.OnPaintBackground(e);
        using (var path = new GraphicsPath())
        {
            var c = e.Graphics.ClipBounds;
            var r = this.ClientRectangle;
            r.Inflate(-FlatAppearance.BorderSize, -FlatAppearance.BorderSize);
            path.AddEllipse(r);
            e.Graphics.SetClip(path);
            base.OnPaint(e);
            e.Graphics.SetClip(c);
            e.Graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
            if (this.Checked)
            {
                using (var p = new Pen(FlatAppearance.BorderColor,
                                       FlatAppearance.BorderSize))
                {
                    e.Graphics.DrawEllipse(p, r);
                }
            }
        }
    }
}
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
GOPAL YADAV
  • 1,181
  • 2
  • 9
  • 18
  • hi @SurvivalMachine, why u are downvoting my question.if u have any doubt,just let me know. – GOPAL YADAV Jul 18 '16 at 08:17
  • "Where is the error in my code?" <-- It would be nice to get more information like how it's broken now and where do you think the error could be. – SurvivalMachine Jul 18 '16 at 08:19
  • The question now contains enough information with a clear problem statement and codes. The question and the answer is a good example for WinForms developers to show how they can customize rendering of a check box to have such appearance. Now the question is more clear. I believe it can be reopened even voted. This way, both question and answer will be more useful for future readers. – Reza Aghaei Jul 19 '16 at 16:35

1 Answers1

24

I know this is a Windows Forms question. But you may want to take a look at Toggle Switches or read more about Universal Windows App Components.

Anyway, here is an answer for Windows Forms developers. It shows how we can customize rendering of a checkbox to have such appearance.

Currently you are drawing only an ellipse, and it's quite a toggle button. But if you want to show it like the below image, you should first draw a round shape for background, and then based on the Checked value, draw the check circle. Using the code in Example part of the answer you can have a CheckBox with such a UI:

Enter image description here

Example

The important thing about this sample is it's completely a CheckBox control and supports check using mouse and keyboard. It also supports data-binding and all other standard features of CheckBox. The code is not perfect, but it is a good start point to have a yes/no toggle switch:

using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;

public class MyCheckBox : CheckBox
{
    public MyCheckBox()
    {
        SetStyle(ControlStyles.UserPaint | ControlStyles.AllPaintingInWmPaint, true);
        Padding = new Padding(6);
    }
    protected override void OnPaint(PaintEventArgs e)
    {
        this.OnPaintBackground(e);
        e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
        using (var path = new GraphicsPath())
        {
            var d = Padding.All;
            var r = this.Height - 2 * d;
            path.AddArc(d, d, r, r, 90, 180);
            path.AddArc(this.Width - r - d, d, r, r, -90, 180);
            path.CloseFigure();
            e.Graphics.FillPath(Checked ? Brushes.DarkGray : Brushes.LightGray, path);
            r = Height - 1;
            var rect = Checked ? new Rectangle(Width - r - 1, 0, r, r)
                               : new Rectangle(0, 0, r, r);
            e.Graphics.FillEllipse(Checked ? Brushes.Green : Brushes.WhiteSmoke, rect);
        }
    }
}
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Reza Aghaei
  • 120,393
  • 18
  • 203
  • 398