2009-07-06 14 views
19

Estoy tratando de 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.Dibujando un botón transparente

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 el botón parece estar agarrando la memoria de interfaz de usuario al azar de alguna parte y el llenado en sí con un poco de memoria intermedia de la interfaz de usuario de Visual Studio (en modo de diseño) En tiempo de ejecución, está tomando un búfer de cero y es completamente negro.

Mi objetivo 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.

¿Alguna idea?

EDIT: Gracias a todos, los siguientes trabajó 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... 
} 
+0

parece ser un duplicado de: http://stackoverflow.com/questions/201778/can-i-create-transparent-buttons-in-visual -studio-2005-with-c – Aamir

+0

Lo que se sugirió en ese hilo no funcionó para mí. – rein

+0

intente pintar con un nuevo color con 0 valor de opacidad en lugar de Color.Transparent – TheVillageIdiot

Respuesta

17

WinForms (y User32 subyacente) no admite la 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.

+0

+1 para obtener gran información @arbiter, pero algunos ejemplos de código ciertamente habrían recorrido un largo camino. – TheVillageIdiot

+0

Algo como esto es lo que tenía en mente, pero el botón en lugar de la etiqueta. (creo) http://christian-helle.blogspot.com/2008/01/transparent-controls-in-netcf.html – TEEKAY

1

No estoy seguro de ButtonBase apoya la transparencia ... ¿Usted ha comprobado que fuera?

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

Cuando se desea bloquear a cabo un control de la pintura él es el fondo - debe reemplazar OnPaintBackground en lugar de OnPaint y no llamar a la clase base.

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

10

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

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);... 
1

Sé que esta pregunta es viejo, 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); 
Cuestiones relacionadas