studio - label transparente c#
¿Cómo crear un control transparente que funcione cuando está por encima de otros controles? (7)
Algunas sugerencias (disculpas por el código VB).
Intenta evitar pintar el fondo:
Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message)
If m.Msg = &H14 Then
Return
End If
MyBase.WndProc(m)
End Sub
Protected Overrides Sub OnPaintBackground(ByVal pevent As System.Windows.Forms.PaintEventArgs)
Return
End Sub
No llame al método de pintura base de controles:
Protected Overrides Sub OnPaint(ByVal e As System.Windows.Forms.PaintEventArgs)
''MyBase.OnPaint(e) - comment out - do not call
End Sub
Tengo un control (derivado de System.Windows.Forms.Control) que debe ser transparente en algunas áreas. He implementado esto utilizando SetStyle ():
public TransparentControl()
{
SetStyle(ControlStyles.SupportsTransparentBackColor, true);
this.BackColor = Color.Transparent.
}
Ahora, esto funciona si no hay controles entre el formulario y el control transparente. Sin embargo, si sucede que hay otro control debajo del control transparente (que es el caso de uso aquí), no funciona. El control intermedio no es el sorteo, pero la siguiente forma se muestra a través. Puedo obtener el efecto que necesito anulando CreateParams y configurando el frasg WS_EX_TRANSPARENT de esta forma:
protected override CreateParams CreateParams
{
get
{
CreateParams cp = base.CreateParams;
cp.ExStyle |= 0x20; // WS_EX_TRANSPARENT
return cp;
}
}
El problema aquí es que realmente ralentiza la pintura del control. El control ya tiene doble buffer, así que no hay nada que hacer allí. El impacto en el rendimiento es tan malo que es inaceptable. ¿Alquien más se ha encontrado con este problema? Todos los recursos que puedo encontrar sugieren el uso del método # 1, pero nuevamente, eso no funciona en mi caso.
EDIT: debo tener en cuenta que tengo una solución. Los controles secundarios (transparentes) podrían simplemente dibujarse en el objeto de Gráficos del padre, pero es realmente desagradable y no me gusta la solución en absoluto (aunque puede ser todo lo que tengo).
EDIT2: Entonces, siguiendo los consejos que recibí sobre cómo funciona la transparencia en .NET, he implementado la interfaz IContainer en mi control de usuario que contiene los controles transparentes. He creado una clase que implementa ISite, agrego mis controles secundarios a la colección Componentes del UserControl, la propiedad del Contenedor se alinea correctamente en el depurador, pero todavía no tengo un efecto de transparencia. ¿Alguien tiene alguna idea?
Decidí simplemente pintar a los padres bajo los controles de mis hijos manualmente. Aquí hay un buen artículo.
Descubrí que las modificaciones a continuación hacen las cosas un poco más rápido:
if((this.BackColor == Color.Transparent) && (Parent != null)) {
Bitmap behind = new Bitmap(Parent.Width, Parent.Height);
foreach(Control c in Parent.Controls) {
if(c != this && c.Bounds.IntersectsWith(this.Bounds)) {
c.DrawToBitmap(behind, c.Bounds);
}
}
e.Graphics.DrawImage(behind, -Left, -Top);
behind.Dispose();
}
También creo que usar this.Width
/ this.Height
lugar de Parent.Width
/ Parent.Height
sería aún más rápido, pero no tuve tiempo para juguetear con eso.
Dibujar a los hermanos bajo el control es posible, pero es feo. El siguiente código funciona razonablemente bien para mí, se expande en el código que figura en el enlace en Ed S. '' contesta
Posibles trampas:
-
DrawToBitmap
se introdujo con .net 2.0, así que no espere que funcione con algo más antiguo. Pero incluso entonces algo como esto puede ser posible enviando WM_PRINT al control de hermanos; AFAIK eso es lo que DrawToBitmap hace internamente. - También puede tener problemas si tiene controles bajo su control que hacen uso de
WS_EX_TRANSPARENT
ya que según el estilo de la ventana, el estilo de la ventana se encuentra en orden. No tengo ningún control que use este estilo, así que no puedo decirlo. - Estoy ejecutando XP SP3 con VS2010, por lo tanto, este enfoque puede tener problemas adicionales en Vista o W7.
Aquí está el código:
if (Parent != null)
{
float
tx = -Left,
ty = -Top;
// make adjustments to tx and ty here if your control
// has a non-client area, borders or similar
e.Graphics.TranslateTransform(tx, ty);
using (PaintEventArgs pea = new PaintEventArgs(e.Graphics,e.ClipRectangle))
{
InvokePaintBackground(Parent, pea);
InvokePaint(Parent, pea);
}
e.Graphics.TranslateTransform(-tx, -ty);
// loop through children of parent which are under ourselves
int start = Parent.Controls.GetChildIndex(this);
Rectangle rect = new Rectangle(Left, Top, Width, Height);
for (int i = Parent.Controls.Count - 1; i > start; i--)
{
Control c = Parent.Controls[i];
// skip ...
// ... invisible controls
// ... or controls that have zero width/height (Autosize Labels without content!)
// ... or controls that don''t intersect with ourselves
if (!c.Visible || c.Width == 0 || c.Height == 0 || !rect.IntersectsWith(new Rectangle(c.Left, c.Top, c.Width, c.Height)))
continue;
using (Bitmap b = new Bitmap(c.Width, c.Height, e.Graphics))
{
c.DrawToBitmap(b, new Rectangle(0, 0, c.Width, c.Height));
tx = c.Left - Left;
ty = c.Top - Top;
// make adjustments to tx and ty here if your control
// has a non-client area, borders or similar
e.Graphics.TranslateTransform(tx, ty);
e.Graphics.DrawImageUnscaled(b, new Point(0, 0));
e.Graphics.TranslateTransform(-tx, -ty);
}
}
Esto es solo una cosa simple que cociné ... El único problema que encontré es que no se actualiza cuando se actualizan los controles de intersección ...
Funciona dibujando un control que está detrás / intersecta con el control actual a un mapa de bits, y luego dibujando ese mapa de bits al control actual.
protected override void OnPaint(PaintEventArgs e)
{
if (Parent != null)
{
Bitmap behind = new Bitmap(Parent.Width, Parent.Height);
foreach (Control c in Parent.Controls)
if (c.Bounds.IntersectsWith(this.Bounds) & c != this)
c.DrawToBitmap(behind, c.Bounds);
e.Graphics.DrawImage(behind, -Left, -Top);
behind.Dispose();
}
}
Esto hace el truco, al menos lo tiene para mí:
protected override void OnPaintBackground(PaintEventArgs e)
{
//base.OnPaintBackground(e);
this.CreateGraphics().DrawRectangle(new Pen(Color.Transparent, 1), new Rectangle(0, 0, this.Size.Width, this.Size.Height));
}
Los controles transparentes en DotNet se implementan haciendo que el contenedor del control transparente se dibuje en la ventana del control transparente y luego que el control transparente se dibuje a sí mismo. Este proceso no tiene en cuenta la posibilidad de controles superpuestos. Por lo tanto, tendrá que usar algún tipo de solución para que funcione.
En algunos casos, he tenido éxito con el anidamiento complejo, pero eso solo es bueno para la superposición rápida de mapas de bits, y no resuelve ningún problema con los controles parcialmente superpuestos.