Dibujando un botón transparente

Estoy intentando crear un botón transparente en C # (.NET 3.5 SP1) para usar en mi aplicación WinForms. He intentado todo para que el botón sea transparente (debe mostrar el fondo degradado debajo del botón) pero simplemente no funciona.

Aquí está el código que estoy usando:

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... } 

El problema es que parece que el botón está agarrando memoria UI aleatoria de algún lugar y llenándose con un búfer de la IU de Visual Studio (cuando está en modo de diseño). En tiempo de ejecución, está tomando un búfer de cero y es completamente negro.

Mi objective final es pintar una imagen en un botón invisible en lugar del rectángulo. El concepto debería seguir siendo el mismo sin embargo. Cuando el usuario pasa el cursor sobre el botón, se dibuja una forma de botón.

¿Algunas ideas?

EDITAR: Gracias a todos, lo siguiente funcionó para mí:

 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... } 

    WinForms (y User32 subyacente) no admite transparencia en absoluto. Sin embargo, WinForms puede simular la transparencia mediante el uso del estilo de control que usted proporciona: admiteTransparentBackColor, pero en este caso todo ese control “transparente” lo hace para permitir que el elemento primario se convierta en el fondo.

    ButtonBase utiliza algunos estilos de ventanas que impiden trabajar este mecanismo. Veo dos soluciones: una es derivar su control de Control (en lugar de ButtonBase), y la segunda es usar Parent’s DrawToBitmap para poner el fondo debajo de su botón, y luego dibujar esta imagen en OnPaint.

    En winforms hay algunos trucos para permitir que un control tenga su fondo correctamente pintado cuando usa transparencias. Puede agregar este código a OnPaint o OnPaintBackground para obtener los controles que tiene en el fondo que está pintando:

     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); //restres graphics to its original state pevent.Graphics.EndContainer(cstate); } else base.OnPaintBackground(pevent); // or base.OnPaint(pevent);... 

    No estoy seguro de que ButtonBase sea compatible con la transparencia … ¿lo has comprobado?

    He escrito una serie de controles transparentes, pero siempre he heredado de Control o UserControl.

    Cuando desee bloquear un control que pinta su fondo, debe anular OnPaintBackground en lugar de OnPaint y no invocar la clase base.

    Llenar un rectángulo con Brushes.Transparent es divertido, estás pintando con un color invisible sobre lo que hay allí. O para decirlo de otra manera: ¡no hace nada!

    Sé que esta pregunta es antigua, pero si alguien no quiere crear un control para hacer esto, se me ocurrió este código de un artículo diferente y lo cambié por un método de extensión.

     public static void ToTransparent(this System.Windows.Forms.Button Button, System.Drawing.Color TransparentColor) { Bitmap bmp = ((Bitmap)Button.Image); bmp.MakeTransparent(TransparentColor); int x = (Button.Width - bmp.Width) / 2; int y = (Button.Height - bmp.Height) / 2; Graphics gr = Button.CreateGraphics(); gr.DrawImage(bmp, x, y); } 

    Y la llamada como:

     buttonUpdate.ToTransparent(Color.Magenta);