Como usar Imagens e Labels com transparência em .NET Windows
Os controlos em Windows Forms (.NET) não suportam verdadeiramente transparência. Neste artigo mostramos como usar transparência em Labels e em imagens.
Introdução - Windows Forms não tem transparência!
Se já tentou trabalhar com formulários mais complexos que incluíssem imagens e labels provavelmente deparou-se com o facto de que o Windows Forms não suporta verdadeiramente transparência. Provavelmente já arrancou bastantes cabelos a tentar - não desespere!
Mesmo que use o valor Transparent para a propriedade BackColor do controlo, não obterá transparência. O que acontece é que o controlo usará o fundo do seu "pai". Este comportamento é visível na próxima imagem.

Neste artigo mostraremos uma forma simples de obter labels com imagens como fundo e também como podemos desenhar imagens e texto com a correcta transparência.
Como fazer labels transparentes
É fácil usar uma imagem como fundo e texto ou labels à frente com verdadeira transparência. Neste capítulo mostraremos como tornar o fundo de uma label transparente.
Podemos fazer com que uma label trate da transparência correctamente de 2 formas (existem mais, mas apenas falaremos das formas mais directas e simples):
- Usando um Panel, definindo a propriedade BackgroundImage e colocando Label(s) dentro do painel
- Definindo o pai da Label como sendo a PictureBox (label.Parent = pictureBox;)
Usaremos a primeira abordagem, visto que não requer nenhuma linha de código e podemos ver o resultado imediatamente no designer.

Primeiro, começamos por arrastar um Panel para o formulário. Depois definimos a propriedade BackgroundImage para a imagem que queremos usar como fundo (podemos usar a propriedade BackgroundImageLayout para controlar o seu comportamento).
Por fim, adicionamos uma Label e definimos a propriedade BackColor com o valor Transparent (a primeira opção na divisão Web). O resultado deverá ser semelhante ao da imagem seguinte.

Isto permite-nos usar labels com transparência, mas as imagens continuam a não ter o resultado esperado (não há transparência nas imagens)! Não se preocupem, no próximo capítulo apresentaremos uma solução para usar imagens com verdadeira transparência.
Desenhar imagens com transparência usando GDI+
Desenhar imagens correctamente com transparência dá um pouco mais de trabalho, porque não podemos usar os controlos que vêm com o WindowsForms e .NET.
Para um uso mais complexo de imagens e gráficos podemos usar GDI+, que significa Graphics Device Interface (encontra-se no namespace System.Drawing).
O que vamos fazer é criar um controlo genérico que nos permitirá desenhar arbitrariamente imagens e texto. Isto pode ser encontrado no código fonte do projecto, mas se quiserem perceber como funciona e como o usar então continuem a ler.
Controlo genérico para desenhar imagens
Comecemos por criar uma nova classe descendente de Panel - chamemos-lhe DrawingArea. Esta classe terá um método abstracto OnDraw que será sobrecarregado pelas subclasses, por isso também precisamos de declarar a classe como abstracta.
Também adicionaremos um objecto Graphics onde terá lugar toda a actividade de desenho. Até este momento deveremos ter algo como o seguinte:
using System; using System.Drawing; using System.Windows.Forms; using System.Drawing.Drawing2D; /// <summary> /// Use this for drawing custom graphics and text with transparency. /// Inherit from DrawingArea and override the OnDraw method. /// </summary> abstract public class DrawingArea : Panel { /// <summary> /// Drawing surface where graphics should be drawn. /// Use this member in the OnDraw method. /// </summary> protected Graphics graphics; /// <summary> /// Override this method in subclasses for drawing purposes. /// </summary> abstract protected void OnDraw(); }
Precisamos de nos certificar que a transparência do fundo do controlo será tratada correctamente. Para isto precisamos de sobrecarregar a propriedade CreateParams para que o estilo correcto seja incluido quando o controlo for instanciado (agradecimentos ao Bob Powell pela dica).
protected override CreateParams CreateParams
{
get
{
CreateParams cp = base.CreateParams;
cp.ExStyle |= 0x00000020; //WS_EX_TRANSPARENT
return cp;
}
}
Precisamos ainda de mais duas coisas. Primeiro temos de nos certificar que o fundo não é desenhado. Fazemos isto sobrecarregando o método OnPaintBackground e deixando-o vazio.
A segunda coisa que precisamos é de sobrecarregar o método OnPaint. Isto permite-nos definir a rotina que será chamada quando for necessário desenhar o controlo.
protected override void OnPaintBackground(PaintEventArgs pevent)
{
// Don't paint background
}
protected override void OnPaint(PaintEventArgs e)
{
// Update the private member so we can use it in the OnDraw method
this.graphics = e.Graphics;
// Set the best settings possible (quality-wise)
this.graphics.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAlias;
this.graphics.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBilinear;
this.graphics.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.HighQuality;
this.graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
// Calls the OnDraw subclass method
OnDraw();
}
Também defini um método DrawText e algumas variações para que fosse mais fácil escrever texto. Como são relativamente extensos deixei esses métodos fora do tutorial, mas podem encontrá-los no código fonte do projecto.
Usar o controlo para desenhar imagens e texto com transparência
Agora como podemos usar este controlo? Precisamos de criar uma subclasse de DrawingArea. Isto é bastante simples e fácil de fazer. Forneço aqui um exemplo:
class BroculosDrawing : DrawingArea { protected override void OnDraw() { // Gets the image from the global resources Image broculoImage = global::WindowsApplication1.Properties.Resources.broculo; // Sets the images' sizes and positions int width = broculoImage.Size.Width; int height = broculoImage.Size.Height; Rectangle big = new Rectangle(0, 0, width, height); Rectangle small = new Rectangle(50, 50, (int)(0.75 * width), (int)(0.75 * height)); // Draws the two images this.graphics.DrawImage(broculoImage, big); this.graphics.DrawImage(broculoImage, small); // Sets the text's font and style and draws it float fontSize = 8.25f; Point textPosition = new Point(50, 100); DrawText("http://www.broculos.net", "Microsoft Sans Serif", fontSize , FontStyle.Underline, Brushes.Blue, textPosition); } }
Neste exemplo são desenhadas duas imagens e uma linha de texto (parecido com as imagens anteriores), mas agora com verdadeira transparência!
Podemos usar este controlo como um controlo normal. Compile a solução. Crie um novo formulário. O novo controlo deverá aparecer na toolbox. Arraste o controlo para o formulário e voila! Podem ver o resultado final na imagem seguinte.

Conclusão
Agora já sabem como desenhar imagens com transparência. A grande desvantagem é que não é tão fácil de usar como os controlos que vêm de "fábrica" com o Windows Forms. Os controlos por omissão são muito limitados para um uso mais avançado de imagem, por isso usamos GDI+ para ultrapassar isto.
Com este conhecimento e um pouco mais de trabalho deverá ser possível fazer uma TransparentPictureBox. Espero que tenha achado este artigo útil.
Recursos
- Transparent Labels On Windows Forms
- Windows Forms FAQ
- Creating transparent Windows Forms controls
- GDI+ Tutorial for Beginners



