Estoy tratando de crear un botón transparente en C# (.NET 3.5 SP1) para el uso en mi aplicación de WinForms. He intentado todo para conseguir que el botón esté transparente (debe mostrar el gradiente de fondo debajo del botón), pero no de trabajo.

Este es 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 que parece ser el acaparamiento de azar de interfaz de usuario de la memoria de algún lugar y llenar con algunos de búfer de Visual Studio interfaz de usuario (cuando está en modo de diseño). En tiempo de ejecución es agarrar un poco de cero había búfer y es completamente negro.

Mi objetivo final es la pintura de una imagen en un botón invisible en lugar de la del rectángulo. El concepto debe permanecer en el mismo sin embargo. Cuando el usuario pasa el ratón sobre el botón, a continuación, un botón de tipo de forma se dibuja.

Alguna idea?

EDIT: Gracias a todos, la siguiente 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...
}
  • Parece ser un duplicado de: stackoverflow.com/questions/201778/…
  • Lo que se sugirió que en ese hilo no funciona para mí.
  • probar a pintar con el color nuevo con 0 valor de opacidad en lugar de Color.Transparente
InformationsquelleAutor rein | 2009-07-06

4 Comentarios

  1. 16

    WinForms (y subyacente User32) no admite transparencia a todos. Los formularios windows forms sin embargo, puede simular la transparencia mediante el uso de estilo de control que proporcionan – SupportsTransparentBackColor, pero en este caso todo lo que «transparente» que hace el control, para permitir el dibujo de los padres de su fondo.

    ButtonBase utiliza algunos estilos de ventanas que impiden el trabajo de este mecanismo. Veo dos soluciones: una es la de derivar de su control, de Control (en lugar de ButtonBase), y la segunda es para uso de los Padres de DrawToBitmap para obtener el fondo bajo el botón y, a continuación, dibujar esta imagen en OnPaint.

    • +1 para la gran información @árbitro pero algo de código de ejemplo sería, sin duda, han recorrido un largo camino desde más lejos.
    • Algo como esto es lo que tenía en mente, pero el botón en lugar de la etiqueta. (creo que) christian-helle.blogspot.com/2008/01/…
  2. 10

    En winforms, hay algunos trucos para permitir un control que tiene su fondo se pinta correctamente cuando se utiliza la transparencia. Usted puede añadir este código a la OnPaint o OnPaintBackground para obtener los controles que se tienen en el fondo está pintado:

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

    No estoy seguro de ButtonBase apoya la transparencia… has comprobado eso?

    He escrito un número de controles transparentes, pero siempre he heredado de Control o control de usuario.

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

    Llenado de un rectángulo con los Pinceles.Transparente es gracioso, aunque – usted está pintando con un invisible de color más de lo que apreparadas allí. O para decirlo de otra manera: no hace nada!

  4. 1

    Sé que esta pregunta es viejo, pero si alguien no quiere crear un control para hacer esto se me ocurrió con este código de un artículo diferente y cambió 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);

Dejar respuesta

Please enter your comment!
Please enter your name here