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.