Faça login ou registe-se
Novidades: torne-se nosso parceiro. Pode agora também submeter os seus artigos!

Como usar Imagens e Labels com transparência em .NET Windows

.NET, C#

por nunof, 00:15 13-03-2008 (actualizado em 03:28 20-04-2008)

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.

Windows Forms não suporta verdadeiramente transparência

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):

  1. Usando um Panel, definindo a propriedade BackgroundImage e colocando Label(s) dentro do painel
  2. 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.

Como definir transparência para as labels

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.

Label com transparência

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.

Windows Forms com transparência completa em imagens e texto

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

 

Comentários

Não existem comentários.

Adicionar comentário

RSS article feed RSS feed de artigos

© 2007-2009 Coconuts. Contacte-nos.