c# - rectangle - Dibujando un botón transparente
winforms draw line (4)
En Winforms hay algunos trucos para permitir que un control que tiene su fondo pintado correctamente cuando se usa la transparencia. Puede agregar este código a OnPaint o OnPaintBackground para obtener los controles que tiene en el fondo que se 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);
//restores graphics to its original state
pevent.Graphics.EndContainer(cstate);
}
else
base.OnPaintBackground(pevent); // or base.OnPaint(pevent);...
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 (debería 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 el botón parece estar tomando memoria de la interfaz de usuario aleatoria de algún lugar y llenándose con un búfer de la interfaz de usuario de Visual Studio (cuando está en modo de diseño). En el tiempo de ejecución, está agarrando 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. Sin embargo, el concepto debería permanecer igual. Cuando el usuario se desplaza sobre el botón, se dibuja una forma de tipo botón.
¿Algunas ideas?
EDITAR: Gracias a todos, lo 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...
}
No estoy seguro de que ButtonBase admita la transparencia ... ¿has comprobado eso?
He escrito varios controles transparentes, pero siempre he heredado de Control o UserControl.
Cuando quiera bloquear una pintura de control, se trata de un fondo: debe anular OnPaintBackground en lugar de OnPaint y no llamar a la clase base.
Rellenar un rectángulo con pinceles. Sin embargo, aunque parezca 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);
WinForms (y User32 subyacente) no admite transparencia en absoluto. Sin embargo, WinForms puede simular la transparencia usando el estilo de control que proporcionas - SupportsTransparentBackColor, pero en este caso todo el control "transparente" lo hace para permitir que el padre dibuje su fondo.
ButtonBase usa algunos estilos de ventanas que impiden el funcionamiento de este mecanismo. Veo dos soluciones: una es derivar su control de Control (en lugar de ButtonBase), y la segunda es usar DrawToBitmap de Parent para obtener fondo debajo de su botón, y luego dibujar esta imagen en OnPaint.