Click here to Skip to main content
Click here to Skip to main content

True Transparency support for the .NET CheckBox control

, 25 Sep 2004
Rate this:
Please Sign up or sign in to vote.
An article on adding true transparency support to the .NET CheckBox control, in C# or VB.NET.

Sample Image - customcheckbox.png

Introduction

There are several articles on the web bemoaning the failure of the .NET Tab control to Theme properly. Some of these mention that the CheckBox control, among others, does not draw its background correctly when used on the tab control. The core of the problem for the checkbox is that it does not properly support transparency.

This article addresses this issue and adds transparency support to the CheckBox control. Additionally, it makes the control draw in XP Style, when the FlatStyle is set to FlatStyle.Standard, even on older platforms that don't support themes.

Reproducing the problem

The problem itself is easy to reproduce. While there is no problem using transparency on the CheckBox in simple applications, as soon as you start to control painting of controls yourself, for example, to add a gradient fill to a form, the problems start! See for yourself.

Create a new Windows Application Project and drop the standard .NET CheckBox onto the Form1 that Visual Studio creates for you.

Now, add the following code to give the form a gradient filled background:

C#.NET

protected override void OnPaintBackground(
    System.Windows.Forms.PaintEventArgs e)
{
    base.OnPaintBackground(e);
    System.Drawing.Drawing2D.LinearGradientBrush brush 
        = new System.Drawing.Drawing2D.LinearGradientBrush(
        this.ClientRectangle, 
        System.Drawing.SystemColors.Highlight, 
        System.Drawing.SystemColors.Window, 
        System.Drawing.Drawing2D.LinearGradientMode.BackwardDiagonal);

    e.Graphics.FillRectangle(brush, this.ClientRectangle);
    brush.Dispose();
}

VB.NET

Protected Overrides Sub OnPaintBackground( _
    ByVal e As System.Windows.Forms.PaintEventArgs)
    MyBase.OnPaintBackground(e)

    Dim brush As New System.Drawing.Drawing2D.LinearGradientBrush( _
        Me.ClientRectangle, _
        System.Drawing.SystemColors.Highlight, _
        System.Drawing.SystemColors.Window, _
        System.Drawing.Drawing2D.LinearGradientMode.BackwardDiagonal)

    e.Graphics.FillRectangle(brush, Me.ClientRectangle)
    brush.Dispose()

End Sub

As you can see, the CheckBox picks up the BackColor of the control behind it, in this case the Form, and not the gradient fill you painted. You can't remedy this by setting the BackColor to Transparent as the control does not support it.

The Solution, Stage 1

At first, all seemed easy. If you subclass the CheckBox control and set the SupportsTransparentBackColor style bit to true, it becomes possible to set the BackColor to Transparent and all seems fine. The subclass looks like this:

C#.NET

public class MyCheckBox : CheckBox
{
    public MyCheckBox(): base()
    {
    this.SetStyle(ControlStyles.SupportsTransparentBackColor, true);
    }
}

VB.NET

Public Class MyCheckBox : Inherits CheckBox

    Public Sub New()
        MyBase.New()
        Me.SetStyle(ControlStyles.SupportsTransparentBackColor, True)
    End Sub

End Class

A few quick tests, changing the FlatStyle proves this to work fine for FlatStyle.Flat, FlatStyle.Popup and FlatStyle.Standard, but FlatStyle.System now displays a white background, even with themes enabled!

This may be sufficient for many of you, but the next stage deals with this problem as well.

The Final Solution

In the end, the only solution proved to lie in taking over the drawing of the check mark completely. It was necessary to hide the FlatStyle from the base class, and when it appears to be set to FlatStyle.System, set the base class property to FlatStyle.Standard and subvert the painting of the control. In fact, the standard check mark does draw underneath, but my custom check mark draws over the top.

In keeping with the way in which the .NET CheckBox control manages its drawing, I created a helper class to draw the check mark in a specified position. The colors are then provided by a third class that supplies the correct color set for the current theme by calling the Windows uxTheme.Dll to find out what the current theme is. If themes are not supported (Pre Windows XP), the color class returns the Blue theme colors, so you could use this to give your non themed apps the themed look and feel.

One side effect of calling the uxTheme.dll is that the UnManaged Code Access Security permission is required. Thankfully, I was able to avoid a stack walk at run time, however, the permission is required at JIT compile time. Normally, this is not an issue. However, you will find that you cannot use this control from a network share without fiddling with your .NET Security Configuration. However, this is the same problem you would have if you tried to use any other control set from a network share as all the decent ones call Unmanaged code at some point, and in fact, so many things are not possible in this configuration that it is advisable to run all .NET apps from a local drive.

On the plus side, my control actually themes better than the default .NET CheckBox control, as the color of the check mark border does not vary with the themes in the .NET control, whereas my control sets the check mark border to the same color as the font color used in the expander panel headers of the Explorer bar shown on the left of the My Computer view of Windows Explorer. I chose this as the colors match for the default (Blue) theme and I think it is an improvement.

Aside from defaulting the BackColor to Transparent, and the FlatStyle to FlatStyle.System, I have made no changes to the default action of this customization of the CheckBox control. In my personal version, I have defaulted the text to an empty string, forced the DataBindings to persist in the designer, and added a databinding between the checked state and the font style so that the text changes to bold font when the CheckBox is checked.

Please note that the control does not provide a view through to the windows behind when using the Form, TransparencyKey property. This is because I have had to set the AllPaintingInWMPaint style bit to true to ensure that the check mark draws correctly.

Using the control

The demo project and source code differ only in the inclusion of a Windows application project to demonstrate the difference between the CustomCheckBox and the default CheckBox. Both zip files contain the entire source code for the three classes required, packaged as Windows Control Projects in C#.NET and VB.NET so that you can copy the source code into your own projects.

If you wish to use the control as it is, build either Windows control project, C#.NET or VB.NET as your preference takes you, and add the control to your toolbox by selecting the resulting assembly from the Add/Remove Items dialog when customizing your Toolbox.

License

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

Share

About the Author

The Man from U.N.C.L.E.
Software Developer
United Kingdom United Kingdom
Unfortunately my real name was already in use as a code project login. For those of you who are wondering I am really Napoleon Solo. Sorry, I mean, Mark Jackson. Well, I do look a bit like him I think.

Comments and Discussions

 
GeneralThanks PinmemberLeonardo Daga1-Sep-08 7:21 
Questionmaking image transparent over other in vb.net Pinmembervikasmaderna29-Jul-07 8:48 
Generalvery nice! Pinmemberiamcoder10-Apr-06 17:51 
GeneralProblem with classic style Pinmemberrvdenden9-Feb-06 7:36 
QuestionRe: Problem with classic style PinmemberThe Man from U.N.C.L.E.9-Feb-06 22:52 
AnswerRe: Problem with classic style Pinmemberrvdenden9-Feb-06 23:31 
AnswerRe: Problem with classic style PinmemberThe Man from U.N.C.L.E.10-Feb-06 1:06 
GeneralUpdate to the Transparency and Theme Support Tale of Woe PinmemberThe Man from U.N.C.L.E.6-Feb-06 6:11 
GeneralRegular Transparency works for me. Pinmembermintguy29-Dec-05 21:01 
GeneralTransparent Labels Pinmemberfedeburin14-Aug-05 6:20 

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

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

| Advertise | Privacy | Mobile
Web04 | 2.8.140827.1 | Last Updated 25 Sep 2004
Article Copyright 2004 by The Man from U.N.C.L.E.
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid