Sunday, January 13, 2008

Transparent Controls in .NETCF

I work a lot with a graphic artist for developing solutions. The better the graphic artist you work with is, the harder it is to implement their designs to your application. One thing that my solutions have in common is that they all require transparent controls. My graphic artist loves having a image buttons on top of fancy background.

Here's some screen shots of what I've made with my graphic artist:

























In these screen shots I heavily use a transparent label control over a Form that has a background image. I normally set my controls to be designer visible so I can drag and drop while designing. Visual Studio 2005 and 2008 will automatically load all Custom Controls and UserControls

Implementing Transparent Controls

For creating transparent controls, I need the following:

1) IControlBackground interface - contains BackgroundImage { get; }
2) TransparentControlBase - draws the BackgroundImage of an IControlBackground form
3) Transparent Control - Inherits from TransparentControlBase
4) FormBase Form - implements IControlBackground and draws the background image to the form

Let's start off with the IControlBackground interface. Like I mentioned above, it only contains a property called BackgroundImage.

public interface IControlBackground
{
  Image BackgroundImage { get; }
}

Next we will need to create the TransparentControlBase. Let's create a class that inherits from Control. We then need to override the OnPaintBackground() event to draw the IControlBackground.BackgroundImage of the Parent control. To do this, we create an instance of IControlBackground from the Parent. Once we have the BackgroundImage, we draw part of the BackgroundImage where the transparent control is lying on.

We also override the OnTextChanged() and OnParentChanged() events to force a re-draw whenever the text or parent of the control is changed.

public class TransparentControlBase : Control
{
  protected bool HasBackground = false;

  protected override void OnPaintBackground(PaintEventArgs e)
  {
    IControlBackground form = Parent as IControlBackground;
    if (form == null) {
      base.OnPaintBackground(e);
      return;
    } else {
      HasBackground = true;
    }

    e.Graphics.DrawImage(
      form.BackgroundImage,
      0,
      0,
      Bounds,
      GraphicsUnit.Pixel);
  }

  protected override void OnTextChanged(EventArgs e)
  {
    base.OnTextChanged(e);
    Invalidate();
  }

  protected override void OnParentChanged(EventArgs e)
  {
    base.OnParentChanged(e);
    Invalidate();
  }
}

Now we need to create a control that inherits from TransparentControlBase. I'll create a simple TransparentLabel control for this example. The control will have the same behavior as the standard Label control, except that it can be transparent when used over a form or control that implements IControlBackground.

public class TransparentLabel : TransparentControlBase
{
  ContentAlignment alignment = ContentAlignment.TopLeft;
  StringFormat format = null;
  Bitmap off_screen = null;

  public TransparentLabel()
  {
    format = new StringFormat();
  }

  public ContentAlignment TextAlign
  {
    get { return alignment; }
    set
    {
      alignment = value;
      switch (alignment) {
        case ContentAlignment.TopCenter:
          format.Alignment = StringAlignment.Center;
          format.LineAlignment = StringAlignment.Center;
          break;
        case ContentAlignment.TopLeft:
          format.Alignment = StringAlignment.Near;
          format.LineAlignment = StringAlignment.Near;
          break;
        case ContentAlignment.TopRight:
          format.Alignment = StringAlignment.Far;
          format.LineAlignment = StringAlignment.Far;
          break;
      }
    }
  }

  protected override void OnPaint(PaintEventArgs e)
  {
    if (!base.HasBackground) {
      if (off_screen == null) {
        off_screen = new Bitmap(ClientSize.Width, ClientSize.Height);
      }
      using (Graphics g = Graphics.FromImage(off_screen)) {
        using (SolidBrush brush = new SolidBrush(Parent.BackColor)) {
          g.Clear(BackColor);
          g.FillRectangle(brush, ClientRectangle);
        }
      }
    } else {
      using (SolidBrush brush = new SolidBrush(ForeColor)) {
        e.Graphics.DrawString(
          Text,
          Font,
          brush,
          new Rectangle(0, 0, Width, Height),
          format);
      }
    }
  }
}

Now that we have our transparent controls, we need to create a Form that will contain these controls. First we need to create a base class that will implement IControlBackground and inherit from Form.

In this example, I added a background image to the solution and as an embedded resource. My default namespace is called TransparentSample and my background image is located at the root folder with the filename background.jpg

public class FormBase : Form, IControlBackground
{
  Bitmap background;

  public FormBase()
  {
    background = new Bitmap(
      Assembly.GetExecutingAssembly().GetManifestResourceStream(
      "TransparentSample.background.jpg"));
  }

  protected override void OnPaint(PaintEventArgs e)
  {
    e.Graphics.DrawImage(background, 0, 0);
  }

  public Image BackgroundImage
  {
    get { return background; }
  }
}

For the last step, we need to create a Form that will contain these transparent controls. To start, let's add a new Form to our project and let it inherit from FormBase instead of Form.

Now we can add our transparent controls to the main form.

public class MainForm : FormBase
{
  TransparentLabel label;

  public MainForm()
  {
    label = new TransparentLabel();
    label.Font = new Font("Arial", 16f, FontStyle.Bold);
    label.ForeColor = Color.White;
    label.Text = "Transparent Label";
    label.Bounds = new Rectangle(20, 60, 200, 50);
    Controls.Add(label);
  }
}

That wasn't very complicated, was it? Having a nice and intuitive UI offers a very good user experience. Being creative, imaginative, and learning to work with a graphic artist can really pay off.

81 comments:

Anonymous said...

Exactly what i was looking for !
Thank you.

Is it possible to do the same thing with a picturebox ? How ?

Anonymous said...

I don't know, but don't work this example on my PDA (WinMobile5).

Christian Resma Helle said...

Works fine on PPC 2003, WM 5, and WM 6 for me.

I can send you the Visual Studio solution to your email if you want to see how it looks in my projects.

Christian Resma Helle said...

Apparently there's a small bug in the TransparentControlBase() code, I overriden OnTextChanged() twice. Instead of overriding OnTextChanged() and OnParentChanged().

Sorry about that. It's fixed now.

Anonymous said...

This is really cool and works good. I'm still pretty new in this area, but I can't get it to work, if I want to make a transparent control containing e.g. two transparent labels. The transparent labels in the transparent control doesn't seem to recognize the parent

Anonymous said...

Hi,

I will test this with WM5, pleace send me ein VS sample juver@peru.com

Tausend Thanks,

Juver

Christian Resma Helle said...

you can download it from:
http://cid-ca531e7fb4762c70.skydrive.live.com/self.aspx/Public/TransparentSample.zip

Anonymous said...

Hi Christian,

it is a very nice article! Does it work also on .Net compact framework 2.0SP2?

Thanks Stephan

Christian Resma Helle said...

Yes I believe it does...

theDVUSone said...

Great article. Exactly what I need. I'm trying to convert it over to vb and am having some problems. You wouldn't already have it in vb by chance?

Christian Resma Helle said...

A few people asked me about this before. I just never pulled myself together to port it to VB.

If you manage to do it, I would really like to have a look at it :)

Anonymous said...

Hey man, thanks for this great code sample. It has helped me out ALOT. I had on problem though. I am creating an owner drawen list view and using you're class to make it's BG transparent. The issue is that when I interact with the listview it flickers. Usually you would just add a blank override for OnPaintBackground but I cannot do that in this case. Any suggestions? If you could email me at tjbishop -*@*- gmail dot com i would appreciate it. Tom

Anonymous said...

hi christian,
Transparent label is really great,

Based on your transparent label, I tried to create transparent panel and I want to place transparent label on top of it, transparent panel shows but I can able to see only white color on top of transparent label,

Can you suggest what could be the problem?

Here is source code for this:

public interface IControlBackground
{
Image BackgroundImage { get; }
}

public class TransparentControlBase : Control
{
protected bool HasBackground = false;

protected override void OnPaintBackground(PaintEventArgs e)
{
IControlBackground form = Parent as IControlBackground;
if (form == null)
{
base.OnPaintBackground(e);
return;
}
else
{
HasBackground = true;
}

e.Graphics.DrawImage(
form.BackgroundImage,
0,
0,
Bounds,
GraphicsUnit.Pixel);
}

protected override void OnTextChanged(EventArgs e)
{
base.OnTextChanged(e);
Invalidate();
}

protected override void OnParentChanged(EventArgs e)
{
base.OnParentChanged(e);
Invalidate();
}
}
public class TransparentPanelBase : Panel
{
protected bool HasBackground = false;

protected override void OnPaintBackground(PaintEventArgs e)
{
IControlBackground form = Parent as IControlBackground;
if (form == null)
{
base.OnPaintBackground(e);
return;
}
else
{
HasBackground = true;
}

e.Graphics.DrawImage(
form.BackgroundImage,
0,
0,
Bounds,
GraphicsUnit.Pixel);
}

protected override void OnTextChanged(EventArgs e)
{
base.OnTextChanged(e);
Invalidate();
}

protected override void OnParentChanged(EventArgs e)
{
base.OnParentChanged(e);
Invalidate();
}
}
public class TransparentLabel : TransparentControlBase
{
ContentAlignment alignment = ContentAlignment.TopLeft;
StringFormat format = null;
Bitmap off_screen = null;

public TransparentLabel()
{
format = new StringFormat();
}

public ContentAlignment TextAlign
{
get { return alignment; }
set
{
alignment = value;
switch (alignment)
{
case ContentAlignment.TopCenter:
format.Alignment = StringAlignment.Center;
format.LineAlignment = StringAlignment.Center;
break;
case ContentAlignment.TopLeft:
format.Alignment = StringAlignment.Near;
format.LineAlignment = StringAlignment.Near;
break;
case ContentAlignment.TopRight:
format.Alignment = StringAlignment.Far;
format.LineAlignment = StringAlignment.Far;
break;
}
}
}

protected override void OnPaint(PaintEventArgs e)
{
if (!base.HasBackground)
{
if (off_screen == null)
{
off_screen = new Bitmap(ClientSize.Width, ClientSize.Height);
}
using (Graphics g = Graphics.FromImage(off_screen))
{
using (SolidBrush brush = new SolidBrush(Parent.BackColor))
{
g.Clear(BackColor);
g.FillRectangle(brush, ClientRectangle);
}
}
}
else
{
using (SolidBrush brush = new SolidBrush(ForeColor))
{
e.Graphics.DrawString(
Text,
Font,
brush,
new Rectangle(0, 0, Width, Height),
format);
}
}
}
}
public class TransparentPanel : TransparentPanelBase
{
Bitmap off_screen = null;
protected override void OnPaint(PaintEventArgs e)
{
if (!base.HasBackground)
{
if (off_screen == null)
{
off_screen = new Bitmap(ClientSize.Width, ClientSize.Height);
}
using (Graphics g = Graphics.FromImage(off_screen))
{
using (SolidBrush brush = new SolidBrush(Parent.BackColor))
{
g.Clear(BackColor);
g.FillRectangle(brush, ClientRectangle);
}
}
}

}
}

-venkateshcs

Christian Resma Helle said...

Overriding OnPaint and OnPaintBackground for the Panel control will only work in .NETCF 3.5. If you want to create a transparent panel in .NETCF 2.0 then inherit from ScrollableControl instead of Panel.

Sonal said...

hey man.....
its really gr8...
but hav 1 query .. how to do it for listview control ???

can u plz tell..

Christian Resma Helle said...

You can make your owner drawn list view inherit from TransparentControlBase instead of Control or ScrollableControl.

When you add your owner drawn list view to a container that implements my IControlBackground it will draw part of the parent's backgorund image into the control.

Anonymous said...

Hello Christian!
Thank you very much for this tutorial! That's exactly what I need.

One question: How can I implement a "TransparentPictureBox"? I want to place a transparent PNG on a background image.

public class TransparentPictureBox : TransparentControlBase {

protected override void OnPaint(PaintEventArgs e) {
// code?
}

}

Christian Resma Helle said...

Hey Manfred,

You can use the SetColorKey() method of the ImageAttributes class to set your transparent color for drawing the image to your drawing surface.

e.Graphics.DrawImage(.....)

Anonymous said...

hi,

Im looking for transparent controls.In my application im having almost all controls.listview,label,textbox,datetime picker,combobox.Is this possible to get transparency for all the controls.If you guide in this regard it will be helpful for me. Will it affect the performance.because already in my application its taking time to load each form.

Anonymous said...

Christian, thank you very much for you fast reply! My TransparentPictureBox is working :-)

ImageAttributes imageAttr = new ImageAttributes();
imageAttr.SetColorKey(Color.White, Color.White);

e.Graphics.DrawImage(
image,
new Rectangle(0, 0, Width, Height),
0,
0,
Width,
Height,
GraphicsUnit.Pixel,
imageAttr);

Unknown said...

Hey Christian,

I have a question regarding transparent control on transparent form...(I created both custom controls and they work)
the problem is when I try to put the transparent picture box (transparency created with imageattributes) ober a form where I simply don't draw the background.

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

The problem is that picture box is instead of part where transparency should occur showing the custom forms default backcolor(control color ; grey)

Do you maybe know where is the problem?

Thanks
Grega

Anonymous said...

I want to have a picture box and a label both of which are transparent inside an usercontrol.
I tried ur code but still the backcolor of the usercontrol comes?
How do I fix that? If possible plz send me the sample code.

Christian Resma Helle said...

Hey guys, sorry for not replying immediately to your inquiries. I've been insanely busy these past few weeks.

Christian Resma Helle said...


I want to have a picture box and a label both of which are transparent inside an usercontrol.
I tried ur code but still the backcolor of the usercontrol comes?
How do I fix that? If possible plz send me the sample code.


Does your UserControl implement the IControlBackground interface that exposes the background image to the child controls?

If you haven't already did, you can download my visual studio solution from:
http://cid-ca531e7fb4762c70.skydrive.live.com/self.aspx/Public/TransparentSample.zip

If that doesn't help then send me your code and I'll look into it. Send it to christian.helle [at] yahoo dot com

Christian Resma Helle said...


Hey Christian,

I have a question regarding transparent control on transparent form...(I created both custom controls and they work)
the problem is when I try to put the transparent picture box (transparency created with imageattributes) ober a form where I simply don't draw the background.

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

The problem is that picture box is instead of part where transparency should occur showing the custom forms default backcolor(control color ; grey)

Do you maybe know where is the problem?

Thanks
Grega


Hey Grega,

I don't think I completely understand. You can send me your code and full details of the problem and I'll find time to take a look at it.

Send it to christian.helle [at] yahoo dot com

Unknown said...

Hey Christian,

Is it possible to have opacity? How?

thanks.

Christian Resma Helle said...

By opacity, you mean setting a certain percentage of opacity for the transparent control?

I guess if your control has a fixed background color, you could alpha blend that with the BackgroundImage of the parent.

You could also do all sorts of image maniuplation or "pixel fu(k1n9" between the parent and child controls background.

Unknown said...

Hi Christian,

Thanks.

Anonymous said...

Good code Christion, thak You.

Anonymous said...

Christian, Thank you for posting this!

Anonymous said...

The Link "http://cid-ca531e7fb4762c70.skydrive.live.com/self.aspx/Public/TransparentSample.zip" is not worked.
Can you send the sample project code to my email:oraone@yeah.net?Thank you.

Unknown said...

Hi,
thanks very much for this tutorial.
Your sample work like a charm on my WM6.
Could you advise how can I change that code so the datagrid Background would be Transparent?
Thanks in advance.

Unknown said...

Hi Chris,

really a good job!

I try to put a TransparentPictureBox over a PictureBox or another TransparentPictureBox but and the lower picturebox becomes white. ¿Do you know why?

A comment, Can you add all the comments and suggestions in one sample? TransparentSample only has label. I think put PictureBox, ListView, buttons and other controls all together can be very interesting.

Anonymous said...

many thx for this code and tutorial, but doesn't work for me. It compiles and doesn't run. I get an NullReferenceException at background= new Bitmap...in the FormBase.cs file.

I also tried the zipped solution from the links above, but doesn't run too.

Many thx in advance.

LC said...

hi,
this is great!

but the transparent will fail, when the 2 label control are overlapping...

Vaibhav said...

I am not able to do transparent picture box control, with the given above solution. Could you please post the code, to do transparent picture box control.

Christian Resma Helle said...

Currently I'm writing an article about Semi-Transparent controls, I am using a Transparent PictureBox control as a sample. It should be done any time now :)

Meets said...

I tried it out for a listview, but in vain, can u pls share ur code for the same.

primoe said...

this solution works fine if the screen resolution is 240x320, but if I want run the application on others resolutions (320x320 128 dpi, 480x640 192 dpi, etc) the background is displayed bad and the labels too...!!!
if I want a standar application and I want not include backgrounds for all the resolutions, how do you solve this problem?

Sorry for my english...!!!
=(

Christian Resma Helle said...

The code I provided was not meant to be production quality code, I just meant to demonstrate how to do transparency in .NETCF

But anyway, if you want support multiple resolutions you can either provide a background image that matches each screen resolution or stretch the background image

Siri said...

Hi,

The code doesn't seem to be working for me.
I am getting an 'NullException' at this part of the code
' background = new Bitmap(
Assembly.GetExecutingAssembly().GetManifestResourceStream(
"Transparent_test.blue1.bmp"));

I have been trying real hard to get past this. Don't know what is wrong. Please help

Christian Resma Helle said...

Did you try the source code for this article that I posted on:
http://cid-ca531e7fb4762c70.skydrive.live.com/browse.aspx/Code%20Samples

?

cromod said...

Siri said...
Hi,

The code doesn't seem to be working for me.
I am getting an 'NullException' at this part of the code
' background = new Bitmap(
Assembly.GetExecutingAssembly().GetManifestResourceStream(
"Transparent_test.blue1.bmp"));

I have been trying real hard to get past this. Don't know what is wrong. Please help

Hi,
Just be sure your image is in the root folder of your application and then click on it to see properties and set Build Action to Embedded Ressource.

Christian Resma Helle said...

Do you mean that you couldn't get the sample code from http://cid-ca531e7fb4762c70.skydrive.live.com/browse.aspx/Code%20Samples to work?

alma said...

wow nice blog. i liked it

Anonymous said...

Try http://tinyurl.com/m3t4yv - it allows also custom drawing!

Anonymous said...

Christian-great looking app. im working in vb.net with CF1.1 Im trying to figure out how to have a fully transparent "clickable" item on top of my form. My background is literally a png of many buttons, and i want to place several transparent clickable items on top of the background. any ideas?

Christian Resma Helle said...

If you just need transparent clickable controls without any text or anything then you can just use the TransparentControlBase that I posted

Anonymous said...

Hi,

Need to implement a transparent listview control, but having issues with how to create the custom list view control ? Checked the customlist view control from Microsoft and tried to use i but having issues.

Manrique said...

Hi,
I have downloaded your vb example and worked fine. I then added the files to my project. I inherited the FormBase to one of my Forms and when i tried to view the designer of my form i see a message displayed in the back that says "Visual Inheritance is currently disabled because the base class references a device-specific component or contains P/Invoke". I´m using the same files from your VB example (outside from my project worked fine) in my project. What am I doing wrong?

Christian Resma Helle said...

Hi Manrique,

What you need is to create a design time attributes (xmta) file and enable DesktopCompatible and DesignTimeVisible on the UI components.

Try looking into .NETCF design time attributes

Manrique said...

Hi Christian,
Thanks alot. Worked like a charm. Last question. I made a class for a transparent PictureBox. How can I implement the SizeMode property so the image can stretch?

Christian Resma Helle said...

Hi Manrique,

You can redraw the image on to the surface. I have a how to post on resizing an image in .NETCF that you might find interesting...

http://christian-helle.blogspot.com/2009/10/resizing-image-in-netcf.html

Hamid Mirzaei said...

It works perfect. Thanks for your great article.

Samy said...

Hy Christian,

the sample works great!

So the transparency only works for controls direct above the forms-backgroundimage?Right?

I have a picture box, where I draw a statusbar(like a volume char).
And i have 2 buttons(or labels), one minus and one plus, if the user presses the minus button, status bar goes down, pressing the plus button the status bar grows up.
That works fine, so far.

But i want to place the 2 buttons directly on the picturebox(minus-button in the left, plus-button in the right), the buttons have to be transparent, so that the user don´t see them and thinks, he presses the statusbar itself.

So is there a simple way to have transparent buttons(or labels) over a picturebox?

Any clue?

Christian Resma Helle said...

Why not have the +/- drawn on one control and do hit tests on user clicks and redraw the image accordingly to simulate a +/- button press. Just an idea...

Bacem said...

hi,
Thanks for this great article.
CAn you tell me if it's possible to create transparent forms ? if yes how ?
Thanks.

Anonymous said...

That is possible indeed. You need to take a screenshot of the screen when the form loads, then override the OnPaint and OnPaintBackground for the form and paint the screendump using alphablending.

Attila said...

I have just tested that transparent labels are supported by calling the e.Graphics.DrawString method from OnPaint. E.g.:

protected override void OnPaint(PaintEventArgs e){
e.Graphics.DrawImage(BackgroundImage, 0, 0);
e.Graphics.DrawString("Hello World!", ...);
}

Christian Resma Helle said...

Its true that drawing directly using Graphics.DrawString will give a transparent effect but manually drawing all text using DrawString would be a tedious task

Anonymous said...

Hi i want to place a transperent label into panel of each form tat panels contains different colors but tat label is of white color background,, i need only the colored text of label to be displayed on every panel not the background.. can u suggest me with the code?
i am using vb.net

Unknown said...

First - I have to say this is great. I've been trying to get something like this to work on my own for a while but this works way better. Just thought since we're talking about transparency and some advanced graphics we should use some double buffering. Only a few things need to be added and it avoids the "flicker effect" if you are creating some sort of list that needs to be scrolled or a control that is moved or refreshed very often.

Anyway, in the TransparentControlBase add

protected Bitmap offScreenBmp = null;
protected Graphics offScreenDC = null;
private Size _lastSize = new Size(0, 0);

Then in the OnPaintBackground override add some code that will check if the size of the control has changed - and if it has you regenerate the off screen graphics:

protected override void OnPaintBackground(PaintEventArgs e)
{
if (this.Size != _lastSize)
{
offScreenBmp = new Bitmap(this.Width, this.Height);
offScreenDC = Graphics.FromImage(offScreenBmp);
}

IControlBackground form = Parent as IControlBackground;
if (form == null) {
base.OnPaintBackground(e);
return;
} else {
HasBackground = true;
}
// We redraw to the off screen graphics instead of the e.Graphics
offScreenDC.DrawImage(
form.BackgroundImage,
0,
0,
Bounds,
GraphicsUnit.Pixel);
}

The only other thing that needs to be done is to draw your string to the off screen graphics and then draw the entire off screen image to the label control. So inside the TransparentLabel OnPaint override you use this:

using (SolidBrush brush = new SolidBrush(ForeColor))
{
base.offScreenDC.DrawString(
Text,
Font,
brush,
new Rectangle(0, 0, Width, Height),
format);

e.Graphics.DrawImage(base.offScreenBmp, 0, 0);
}

For Anyone that doesn't know - all this technique does is ensure that graphics are only drawn onto your label once per paint operation, instead of twice or more depending on what you're doing...

Anyway - Chris can probably explain it better if he wants - I just thought this might help someoue out down the line...

Unknown said...

Sorry - I forgot a line in the above post. The TransparentControlBase should actually have this in the OnPaintBackground override:

if (this.Size != _lastSize)
{
offScreenBmp = new Bitmap(this.Width, this.Height);
offScreenDC = Graphics.FromImage(offScreenBmp);
_lastSize = this.Size;
}

The last line there will set the lastSize to the current size. You need this so a new Bitmap wont be created on every paint operation - or else you'll get an out of memory error real fast!

Arnold said...

hi

this is great stuff. Yhank you very much for sharing.

I would like to ask how can we make those cool scrolling lists?
now if the content of the form is larger than the screen, the standard windows scrollbar appears. how can we change into a more stylish one?
to be able to scroll with finger-movements it is automatically built in in the win 6.5 OS, or it has to be programmed?

thank you in advance.
regards,
Arnold

Anonymous said...

Can we have the SizeMode.StrechImage functionality for the transparent picture box, since i cannot resize the images everytime due to large no of images being used on form.

Please do let me know the possible solutions.

David said...

great comment. thanks for sharing.

Anonymous said...

Hi,
I am using Transparent controls created from here.

I am having a Transparent Picture Box inside a Panel.
Now on Form Load event when i set Panel's AutoScrollPosition, it does not have any effect.

please do let me know the solution for this.

Unknown said...

HERE IS A PORTABILITY TO VB.NET (PART 1)

=======FORM BASE CLASS=========
Imports System.Reflection

Public Class FormBase
Inherits Form
Implements IControlBackground

Dim background As Bitmap

Public Sub New()
background = New Bitmap(Assembly.GetExecutingAssembly().GetManifestResourceStream("SmartDeviceProject1.EUflag_L.jpg"))
End Sub

Protected Overrides Sub OnPaint(ByVal e As PaintEventArgs)
e.Graphics.DrawImage(background, 0, 0)
End Sub

Public Property BackgroundImage() As Image Implements IControlBackground.BackgroundImage
Get
Return background
End Get
Set(ByVal value As Image)

End Set
End Property
End Class

=============IControlBackground interface
Public Interface IControlBackground
Property BackgroundImage() As Image
End Interface

==============TransparentControlBase class
Public Class TransparentControlBase
Inherits Control
Protected HasBackground As Boolean = False

Protected Overrides Sub OnPaintBackground(ByVal e As PaintEventArgs)
Dim Form As IControlBackground = Parent 'as IControlBackground
If Form Is Nothing Then
MyBase.OnPaintBackground(e)
Return
Else
HasBackground = True
End If

e.Graphics.DrawImage(Form.BackgroundImage, 0, 0, Bounds, GraphicsUnit.Pixel)
End Sub

Protected Overrides Sub OnTextChanged(ByVal e As EventArgs)
MyBase.OnTextChanged(e)
Invalidate()
End Sub

Protected Overrides Sub OnParentChanged(ByVal e As EventArgs)
MyBase.OnParentChanged(e)
Invalidate()
End Sub
End Class

Unknown said...

(PART 2)

=============TransparentLabel class
Public Class TransparentLabel
Inherits TransparentControlBase

Dim alignment As ContentAlignment = ContentAlignment.TopLeft
Dim format As StringFormat = Nothing
Dim off_screen As Bitmap = Nothing

Public Sub New()
format = New StringFormat()
End Sub

Public Property TextAlign() As ContentAlignment
Get
Return alignment
End Get
Set(ByVal value As ContentAlignment)
alignment = value
Select Case alignment
Case ContentAlignment.TopCenter
format.Alignment = StringAlignment.Center
format.LineAlignment = StringAlignment.Center
Case ContentAlignment.TopLeft
format.Alignment = StringAlignment.Near
format.LineAlignment = StringAlignment.Near
Case ContentAlignment.TopRight
format.Alignment = StringAlignment.Far
format.LineAlignment = StringAlignment.Far
End Select
End Set
End Property


Protected Overrides Sub OnPaint(ByVal e As PaintEventArgs)
If Not MyBase.HasBackground Then
If off_screen Is Nothing Then
off_screen = New Bitmap(ClientSize.Width, ClientSize.Height)
End If
Using g As Graphics = Graphics.FromImage(off_screen)
Using brush As SolidBrush = New SolidBrush(Parent.BackColor)
g.Clear(BackColor)
g.FillRectangle(brush, ClientRectangle)
End Using
End Using
Else
Using brush As SolidBrush = New SolidBrush(ForeColor)
e.Graphics.DrawString(Text, Font, brush, New Rectangle(0, 0, Width, Height), format)
End Using
End If
End Sub
End Class

========== USAGE
Dim label As TransparentLabel

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Dim label As New TransparentLabel()
label.Font = New Font("Arial", 16.0F, FontStyle.Bold)
label.ForeColor = Color.White
label.Text = "Transparent Label"
label.Bounds = New Rectangle(20, 60, 200, 50)
Controls.Add(label)
End Sub

Christian Resma Helle said...

Thank you very much for the VB.NET Port

Leandro Passarelli said...

Is it possible draw a semitranparent elipse in front a picture box? how to?
Tks!

Leandro Passarelli said...

Is it possible draw a semitranparent elipse in front a picture box? how to?
Tks!

Juan Oropeza said...

The sample works great. Anyone have code to make a transparent picturebox?

Anonymous said...

I used the ported code in vb.net and getting an error in the line,
Dim Form As IControlBackground = Parent
in OnPaintBackground in TransparentControlBase class. IT says 'InvalidCastException : When casting from a number, the value of the number must be less than infinity'.
How to get rid of this error?
Please guide me at the earliest.

Anonymous said...

Great opinion you public here. It would be great to find anything more concerning this topic. Thx you for giving that information. Ioan
Kiev escort

Anonymous said...

I have a done all the instructions and procedure. but still cannot run it in my wm6? please help.and also i have a warning

The designer could not be shown for this file because none of the classes within it can be designed. The designer inspected the following classes in the file:

TransparentLabel --- The base class 'my.Mobile.Apps.TransparentControlBase' could not be loaded. Ensure the assembly has been referenced and that all projects have been built. 0 0

Anonymous said...

I have done all procedures and classes, but still it doesn't work in my wm6 and also i have a WARNING: The designer could not be shown for this file because none of the classes within it can be designed. The designer inspected the following classes in the file:

TransparentLabel --- The base class 'EGIS.Mobile.Apps.TransparentControlBase' could not be loaded. Ensure the assembly has been referenced and that all projects have been built.

Gus said...

You mentioned that you were writing an article using a transparent PictureBox as an example. Did you ever get to it. I'm having some throuble creating the beast.

Android app development said...

This is one of the reliable and good post.Thanks for presenting this type of Information.This is one of the Important post.Your blog is playing a vital role In Internet marketing field.Android app developers

Anonymous said...

Hi
is possible use as class library for use with basic4ppc?
And How?
Thanks

Anonymous said...

build transparent label in .NET