Click here to Skip to main content
15,867,686 members
Articles / Multimedia / GDI

ToggleSwitch Winforms Control

Rate me:
Please Sign up or sign in to vote.
4.98/5 (76 votes)
11 Sep 2015CPOL7 min read 150.2K   21.6K   71   98
A ToggleSwitch that presents on/off values in a more interesting way than a standard CheckBox

Introduction

So, once again, I'm publishing an article about a custom painted Winforms control. I guess I ought to change my profile name to "Control Freak"... But what the heck: I love programming custom controls! Nothing to do about that.

This time, I needed a ToggleSwitch or ToggleButton - something that can show a binary On/Off Checked/Unchecked state in a more interesting way than the standard checkbox. As usual, I started checking out the existing controls, because who wants to spend a lot of time reinventing something that has already been invented??? The thing that normally happens to me also happened this time: I found existing controls that could have been so great, but was leaving me wanting in some way. The best I could find (and very good looking too at that) is this one by IKalai (here on Code Project of course). But I had some problems with Ikalai's control. The most important one was that it doesn't allow you to change the size of the control as you want, and I couldn't make it the size I needed for my application... :-( I really don't understand why he has chosen to impose such a strange limitation on his control!

I also found this one, which is even better looking - but alas, it is built for WPF/Silverlight, so I couldn't use it.

So I did what I so often do: I started rolling my own control. And as usual, I went completely overboard and made it much more advanced than I really needed. Instead of merely doing a control that looked as I wanted and behaved as I wanted, I was inspired by the above two articles to make a control that could be made to look in a lot of different ways. In the end, I wound up with TEN different styles plus the possibility to customize those styles further - AND create own renderers to add even more styles if one should feel the need to do that.

The articles didn't just inspire me, I must admit that I even stole some ideas from them... But the code is 100% mine!

In the end - after finishing the control - I got a completely different idea. So I'm not even sure I'm going to use my ToggleSwitch in the application I created it for. But here it is, nevertheless, for the benefit of y'all to use.

Control Feature Overview

1. Basic Control Goodies

The control is of course doublebuffered to minimize flicker. It is also derived from the Control class so it supports both the Anchor and Dock properties.

2. Different Styles

Image 1

I planked two styles from IKalai's control and seven from the WPF control. The style is changed by merely setting the Style property to the style you want.

3. Image and Text Support

You can customize the control pretty much as you like. A text or image can be inserted in each side of the control (if the selected renderer supports it). You can only have either text OR image. If you have set the image property, it will take precedence and the text property will not be used.

Image 2

You can also insert an image in the button itself (again if the selected renderer supports it). I didn't implement the text option for the slider button because my judgment was that the text that could fit in the button would be so small anyway that it is of no use.

4. Other Cool Properties

  • AllowUserChange - There may be situations where you don't want the user to be able to change the value of the control, but you don't want to disable it either. If you set AllowUserChange = false, the user cannot change the value, but you can still change it in code behind.

  • AnimationInterval, AnimationStep & UseAnimation - When the slider moves from one state to another, it can be animated. When UseAnimation = true, the two other values determine how fast the button moves. Generally, it is moved the number of pixels set in AnimationStep for each number of milliseconds set in AnimationInterval. If you want the button to change state immediately, just set UseAnimation = false.

  • GrayWhenDisabled - Determines if the control is painted in grayscale when it is disabled or retains the same look as when it is enabled.

    Image 3

  • ThresholdPercentage - Determines how far you have to drag the button before it snaps to the other side. Default is 50%, so if you pull the slider button more than halfways across the control, it will automatically snap to the other side. The percentage is always calculated from the side where the button currently resides.

  • ToggleOnButtonClick & ToggleOnSideClick - The user can of course always drag the slider button to change the value of the switch. But using these properties, you can also decide if the control should toggle if it is clicked by the user. If ToggleOnButtonClick = true, clicking the slider button will toggle the switch. If ToggleOnSideClick = true, you can even click the areas beside the button and get the switch to toggle. If both are true, clicking anywhere on the control will toggle it, and if both properties are false, clicking the control will have no effect at all.

5. Customizable Renderers

Each style has its own renderer. Some of the basic properties such as the image properties are so common that they can be found directly on the ToggleSwitch control. Not all renderes accept all these properties, though. But most of them do. Other properties such as colors, I've chosen to attach to the specific renderers. Because they all paint the controls in so different ways, it was hard to make general color properties in the ToggleSwitch control that would make sense in all the different scenarios.

Image 4

By making the color properties part of the renderers, it's possible to customize the look of a specific style much more than it would otherwise have been. The drawback is that in order to do that, you have to create a new instance of the renderer, change the properties and assign the new renderer to the control. But it's not that hard and the demo program shows exactly how to do that.

In version 1.1 of the control, I am passing the renderer instance in a BeforeRendering event so that the properties can be set directly without creating a new instance first.

Points of Interest

The look I originally wanted for my application was the one with the brushed metal knob. All the controls I have seen with brushed metal knobs before have done them in the same way: By embedding an image file created in PhotoShop in the resources and paint that on the surface of the control. I found a PhotoShop tutorial on how to create such an image...

But it disturbed me and my touch of Asperger. Embedding a file and painting that is not so "clean" as if you paint it directly on the control yourself.

Even with the PhotoShop tutorial, I didn't really know how to paint it in C#. I asked some people on Code Project, but I didn't really get much help there. Pete told me that I had to use a gradient brush - which I already knew, but I couldn't really see how i could do it anyway. So I Googled some more. I found a lot of examples on how to fill a circle with a radial gradient using a PathGradientBrush. But all of those examples showed how to make a gradient that went from the inner center of the circle to the outer border (or the other way around). And I of course needed to make a gradient that went around the inside of the circle.

It wasn't easy, but FINALLY, I found this example that does more or less what I needed:

So I started dividing the image of the metal knob into gradient pie slices and paint them one by one. That worked out, But strangely enough, I discovered that if I painted all the gradients using the actual center of the knob as center for the brushes, I didn't get the look I had expected. To get the correct look, I had to offset the center of each brush slightly. I don't know why, but I got it to work in the end, I think.

"My" painted brushed metal knob may not look EXACTLY as good as a PhotoShopped one, but I was quite pleased with the result anyway. More so that I didn't have to include resources in the control library to get it to work.

History

Version 1.1 (2019-02-20)

  • NEW: BeforeRendering event added to make it easier to customize the renderer properties
  • NEW: Style and Renderer added: PlainAndSimple
  • UPDATED: Demo app updated with the new features

Version 1.0 (2015-09-11)

  • Initial release

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior)
Sweden Sweden
Born in Copenhagen, Denmark
Have been living in Paris, France and L.A., The United States
Now live in Stockholm, Sweden

Started programming when I got my first VIC 20, and a few months later on Commodore 64. Those were the days!

Studied programming at the Copenhagen Engineering Academy

Professional console, winforms and webforms programming in Comal, x86 Assembler, Fortran, Pascal, Delphi, Visual Basic 3 through 6, Classic ASP, C# and VB.NET

I now work as Senior Microsoft Dynamics AX and .Net programmer, and have a number of projects in various states of progress to work on in the spare time...

Comments and Discussions

 
QuestionMultiple switch Color problem Pin
Member 1144335717-Aug-18 0:08
Member 1144335717-Aug-18 0:08 
AnswerRe: Multiple switch Color problem Pin
Johnny J.20-Feb-19 1:13
professionalJohnny J.20-Feb-19 1:13 
BugIncomplete Pin
Member 1391693718-Jul-18 8:00
Member 1391693718-Jul-18 8:00 
AnswerRe: Incomplete Pin
Johnny J.20-Feb-19 0:59
professionalJohnny J.20-Feb-19 0:59 
QuestionHow to add this file in my project of Visual Studio 2017? Pin
Member 1378575018-Apr-18 20:17
Member 1378575018-Apr-18 20:17 
AnswerRe: How to add this file in my project of Visual Studio 2017? Pin
Johnny J.20-Feb-19 0:53
professionalJohnny J.20-Feb-19 0:53 
GeneralVery well Pin
Yves16-Jan-18 12:00
Yves16-Jan-18 12:00 
QuestionAdd problem Pin
Member 108590213-Dec-17 23:08
Member 108590213-Dec-17 23:08 
<pre>this->switchRight->CheckedChanged += gcnew JCS::ToggleSwitch::CheckedChangedDelegate(this, &Form1::switchRight_CheckedChanged);



13  IntelliSense: function "JCS::ToggleSwitch::CheckedChanged::add" cannot be called with the given argument list
        argument types are: (JCS::ToggleSwitch::CheckedChangedDelegate ^)
        object type is: JCS::ToggleSwitch ^


After restart project
CheckedChanged
property is clear (no function to call)
AnswerRe: Add problem Pin
Johnny J.3-Dec-17 23:53
professionalJohnny J.3-Dec-17 23:53 
GeneralRe: Add problem Pin
Member 108590214-Dec-17 0:32
Member 108590214-Dec-17 0:32 
GeneralRe: Add problem Pin
Johnny J.4-Dec-17 0:40
professionalJohnny J.4-Dec-17 0:40 
GeneralRe: Add problem Pin
Member 108590214-Dec-17 0:58
Member 108590214-Dec-17 0:58 
QuestionREALLY HELP Pin
Khabibb Mubarakk15-Nov-17 5:57
Khabibb Mubarakk15-Nov-17 5:57 
QuestionToggleswitch in contextmenu Pin
Member 1136235828-Sep-17 9:03
Member 1136235828-Sep-17 9:03 
Questionhow do I add this winforms control to Visual Studio 2015?? Pin
prototype08155-Sep-17 2:57
prototype08155-Sep-17 2:57 
AnswerRe: how do I add this winforms control to Visual Studio 2015?? Pin
Member 134399432-Oct-17 3:51
Member 134399432-Oct-17 3:51 
QuestionNice! Where is the best place to add a OnBeforeCheckChanged cancelable event? Pin
Memetican6-Aug-17 18:40
Memetican6-Aug-17 18:40 
QuestionHaving Problems with download. Pin
Toadcode17-Jul-17 13:14
Toadcode17-Jul-17 13:14 
AnswerRe: Having Problems with download. Pin
Johnny J.18-Jul-17 0:54
professionalJohnny J.18-Jul-17 0:54 
QuestionGreat control - only localizablility was missing Pin
Heinz Kessler27-Jun-17 19:57
Heinz Kessler27-Jun-17 19:57 
AnswerRe: Great control - only localizablility was missing Pin
Johnny J.27-Jun-17 21:40
professionalJohnny J.27-Jun-17 21:40 
PraiseThank You!! Pin
Apopka_Pilot14-Jun-17 23:46
Apopka_Pilot14-Jun-17 23:46 
Questionhow to use them Pin
Member 1321839423-May-17 8:13
Member 1321839423-May-17 8:13 
QuestionHow to rotate these user controls in vertical direction Pin
guruece2413-Apr-17 1:28
guruece2413-Apr-17 1:28 
AnswerRe: How to rotate these user controls in vertical direction Pin
Johnny J.17-Apr-17 8:31
professionalJohnny J.17-Apr-17 8:31 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.