Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Drawing a transparent button

Tags:

I'm trying to create a transparent button in C# (.NET 3.5 SP1) to use in my WinForms application. I've tried everything to get the button to be transparent (it should show the gradient background underneath the button) but it's just not working.

Here is the code I'm using:

public class ImageButton : ButtonBase, IButtonControl {     public ImageButton()     {         this.SetStyle(             ControlStyles.SupportsTransparentBackColor |              ControlStyles.OptimizedDoubleBuffer |              ControlStyles.AllPaintingInWmPaint |              ControlStyles.ResizeRedraw |              ControlStyles.UserPaint, true);         this.BackColor = Color.Transparent;     }      protected override void OnPaint(PaintEventArgs pevent)     {         Graphics g = pevent.Graphics;         g.FillRectangle(Brushes.Transparent, this.ClientRectangle);         g.DrawRectangle(Pens.Black, this.ClientRectangle);     }       // rest of class here...  } 

The problem is that the button seems to be grabbing random UI memory from somewhere and filling itself with some buffer from Visual Studio's UI (when in design mode). At runtime it's grabbing some zero'd buffer and is completely black.

My ultimate goal is to paint an image on an invisible button instead of the rectangle. The concept should stay the same however. When the user hovers over the button then a button-type shape is drawn.

Any ideas?

EDIT: Thanks everybody, the following worked for me:

public class ImageButton : Control, IButtonControl {     public ImageButton()     {         SetStyle(ControlStyles.SupportsTransparentBackColor, true);         SetStyle(ControlStyles.Opaque, true);         SetStyle(ControlStyles.ResizeRedraw, true);         this.BackColor = Color.Transparent;      }      protected override void OnPaint(PaintEventArgs pevent)     {         Graphics g = pevent.Graphics;         g.DrawRectangle(Pens.Black, this.ClientRectangle);     }       protected override void OnPaintBackground(PaintEventArgs pevent)     {         // don't call the base class         //base.OnPaintBackground(pevent);     }       protected override CreateParams CreateParams     {         get         {             const int WS_EX_TRANSPARENT = 0x20;             CreateParams cp = base.CreateParams;             cp.ExStyle |= WS_EX_TRANSPARENT;             return cp;         }     }      // rest of class here... } 
like image 309
rein Avatar asked Jul 06 '09 12:07

rein


People also ask

How do I create a transparent button?

The transparent button can be easily created by using HTML and CSS. In this article, we will use background-color: transparent; property to design the transparent background button. HTML Code: In this section, we will create a basic structure of button using the button Tag.

How do I make a button transparent in C#?

Click the button that you want to make transparent. Select FlatStyle from Properties and set it to popup Now change the BackColor property to Transparent . This will make the button transparent.


2 Answers

WinForms (and underlying User32) does not support transparency at all. WinForms however can simulate transparency by using control style you provide - SupportsTransparentBackColor, but in this case all that "transparent" control does, it to allow drawing parent its background.

ButtonBase uses some windows styles that prevent working this mechanism. I see two solutions: one is to derive your control from Control (instead of ButtonBase), and second is to use Parent's DrawToBitmap to get background under your button, and then draw this image in OnPaint.

like image 114
arbiter Avatar answered Oct 09 '22 10:10

arbiter


In winforms there are some tricks to allow a control having its background correctly painted when using transparency. You can add this code to the OnPaint or OnPaintBackground to get the controls you have in the background being painted:

if (this.Parent != null) {  GraphicsContainer cstate = pevent.Graphics.BeginContainer();  pevent.Graphics.TranslateTransform(-this.Left, -this.Top);  Rectangle clip = pevent.ClipRectangle;  clip.Offset(this.Left, this.Top);  PaintEventArgs pe = new PaintEventArgs(pevent.Graphics, clip);   //paint the container's bg  InvokePaintBackground(this.Parent, pe);  //paints the container fg  InvokePaint(this.Parent, pe);  //restores graphics to its original state  pevent.Graphics.EndContainer(cstate); } else   base.OnPaintBackground(pevent); // or base.OnPaint(pevent);... 
like image 30
jmservera Avatar answered Oct 09 '22 09:10

jmservera