Click here to Skip to main content
Click here to Skip to main content
Go to top

Creating Transparent Controls in .NET Compact Framework

, 9 Oct 2009
Rate this:
Please Sign up or sign in to vote.
This article explains how to create transparent controls in .NET Compact Framework

Introduction

.NET Compact Framework doesn't provide out-of-box controls with transparent background. This article shows how to create user controls to overcome this issue.

Background

In a recent .NET compact framework application I was working on, I needed to add an image to the form's background. I did it by using the code from this video tutorial from Microsoft. However, the video also told us that the label control (and other controls) in .NET compact framework doesn't support transparent background. You will have to create your own user control. I found a good article Creating gradient background with transparent labels in .NET Compact Framework by Per Ola Sæther. It helped me to create my solution.

Using the Code

The basic ideas to create a transparent control is to override the OnPaintBackgound method of the control so it calls the parent form's OnPaintBackgound to draw the background and then draw content of the control on top of it.

In that article, the author showed how to create a transparent label control. But the code can be simplified. I also did some refactoring work so it extends to not just label control.

First, I created the same interface introduced in that article.

public interface IPaintControl
{
    // have the background painted
    void InvokePaintBackground(PaintEventArgs e);
}

Then I created a base form so I don't have to write the same code for each form.

public class CcForm : Form, IPaintControl
{
    public virtual void InvokePaintBackground(PaintEventArgs e)
    {
        OnPaintBackground(e);
    }
}

A base control is created so we can have not only the transparent label, but also other kinds of controls, such as radio button and checkbox. It has a property called TransparentBackground. If you don't want your control to be transparent for some reason, you can change this property. In the OnPaintBackground method, it calls its parent’s InvokePaintBackground to draw the background.

public class CcTransparentControl : Control
{
    private bool _transparentBackgound = true;
    public bool TransparentBackground
    {
        get
        {
            return _transparentBackgound;
        }
        set
        {
            _transparentBackgound = value;
        }
    }

    protected override void OnPaintBackground(PaintEventArgs e)
    {
        if (_transparentBackgound)
        {
            IPaintControl parent = Parent as IPaintControl;
            if (parent != null)
            {
                parent.InvokePaintBackground(e);
            }
        }
        else base.OnPaintBackground(e);
    }
}

Now we can create the transparent label control using the following code:

public class CcTransparentLabel : CcTransparentControl
{
    private ContentAlignment textAlign = ContentAlignment.TopLeft;
    public ContentAlignment TextAlign
    {
        get
        {
            return textAlign;
        }
        set
        {
            textAlign = value;
        }
    }

    public CcTransparentLabel()
    {

    }

    protected override void OnPaint(PaintEventArgs e)
    {
        Graphics gfx = e.Graphics;
        if (this.TextAlign == ContentAlignment.TopLeft)
        {
            gfx.DrawString(this.Text, this.Font,
            new SolidBrush(this.ForeColor), ClientRectangle);
        }
        else if (this.TextAlign == ContentAlignment.TopCenter)
        {
            SizeF size = gfx.MeasureString(this.Text, this.Font);
            int left = this.Width / 2 - (int)size.Width / 2;
            var rect = new Rectangle(ClientRectangle.Left + left,
            ClientRectangle.Top, (int)size.Width,
            ClientRectangle.Height);
            gfx.DrawString(this.Text, this.Font,
            new SolidBrush(this.ForeColor), rect);
        }
        else if (this.TextAlign == ContentAlignment.TopRight)
        {
            SizeF size = gfx.MeasureString(this.Text, this.Font);
            int left = this.Width - (int)size.Width + this.Left;
            var rect = new Rectangle(ClientRectangle.Left + left,
            ClientRectangle.Top, (int)size.Width,
            ClientRectangle.Height);
            gfx.DrawString(this.Text, this.Font,
            new SolidBrush(this.ForeColor), rect);
        }
    }
}

In our form, we change the form to inherit from CcForm and drag/drop a CcTransparentLabel onto it.

public partial class FormWithSolidColorBackground : CcForm

Here is the screen shot. As you can see, the label has transparent background now.

However, when I tried to add image background with gradient color, my label doesn't look right anymore.

To understand the issue, we need to first take a look at how we display background image on a form.

public partial class FormWithImageBackground : CcForm
{
    private Rectangle _backgroundRect;
    private Bitmap _background;
    private string currentPath = Path.GetDirectoryName
	(Assembly.GetExecutingAssembly().GetName().CodeBase.ToString());

    public FormWithImageBackground()
    {
        InitializeComponent();

        _background = new Bitmap(currentPath + @"\ImageBackground.jpg");
        _backgroundRect = new Rectangle(0, 0, _background.Width, _background.Height);
    }

    protected override void OnPaintBackground(PaintEventArgs e)
    {
        Graphics g = e.Graphics;
        g.DrawImage(_background, this.ClientRectangle, 
			_backgroundRect, GraphicsUnit.Pixel);
    }
}

What happened is when the OnPaintBackground was called by the transparent label control, it re-draws the image inside of the label control. So it shows the top-left corner of the image on the label’s background. To fix this issue, I pass in the location of the label control to the form and use it to re-draw the image. For example, if the label is located at (10, 20), the image background would be displayed at (-10, –20). This may not be the best solution, but it is simple and it worked. Here is the revised interface and controls.

public interface IPaintControl
{
    // have the background painted
    void InvokePaintBackground(PaintEventArgs e, Point location);
}
 
public class CcForm : Form, IPaintControl
{
    public virtual void InvokePaintBackground(PaintEventArgs e, Point location)
    {
        OnPaintBackground(e);
    }
}
 
public class CcTransparentControl : Control
{
    ....
    protected override void OnPaintBackground(PaintEventArgs e)
    {
        if (_transparentBackgound)
        {
            IPaintControl parent = Parent as IPaintControl;
            if (parent != null)            
            {
                parent.InvokePaintBackground(e, this.Location);
            }
        }
        else base.OnPaintBackground(e);
    }
}

In the form, I then override the InvokePaintBackground method to draw the image at the desired location.

public override void InvokePaintBackground
	(System.Windows.Forms.PaintEventArgs e, System.Drawing.Point location)
{
    Graphics g = e.Graphics;
    Rectangle destRect = new Rectangle(-1 * location.X, -1 * location.Y, 
			ClientRectangle.Width, ClientRectangle.Height);
    g.DrawImage(_background, destRect, _backgroundRect, GraphicsUnit.Pixel);
}

Now we have a transparent label over image background.

I also created a transparent radio button and checkbox controls. These are the controls commonly used in a form and so is the Panel control. The following example showed the transparent radio button and checkbox on a transparent panel.

Happy programming!

History

  • 8th October, 2009: Initial post
  • 9th October, 2009: Article updated

License

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

Share

About the Author

DotNetIdeas
Team Leader www.dotnetideas.com
United States United States
No Biography provided

Comments and Discussions

 
Questioni want to create tabcontrol Pinmembersherif4c_sharp25-Apr-11 4:35 

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
Web01 | 2.8.140926.1 | Last Updated 9 Oct 2009
Article Copyright 2009 by DotNetIdeas
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid