昨天一朋友问到Windows窗体中图片透明的问题,刚上网看看了,在CodeProject上看到了这篇文章,觉得写的不错,再者自己一直想学学翻译技术文章,所以就将其翻译成了中文,希望能给大家带来点帮助。
申明:初次翻译此类文章,属处女作,难免有不对之处,欢迎大家拍砖指教!^_^ OK,开始正文……
引言——没有透明度的Windows窗体如果你制作一些包括图片和标签的复杂的窗体,你可能会发现:Windows窗体不支持真正的透明。你可能撕裂了你的头皮了——但仍没有解决!
即使,你在图片或标签的BackColor属性上使用了透明值来控制,但结果是:你仍然发现不能使其透明。那么,这是为什么呢?为什么明明设置成透明了,却没有透明呢?到底都发生了些什么呢?
实际上,当你在BackColor属性上设置透明值来控制的时候,只是将其背景设置成与父窗体——Windows窗体一样的背景而已,并没有真正的透明!所以当它们重叠放在一起的时候你仍然会发现它们相互之间并没有透明,如下图所示:
在本文中,我们将向你展示一个简单的方法来使得标签的后面图片作为背景,并如何使图片和文字真正的变成透明。
如何制作透明标签使图片作为背景而标签或文字在其前面进行显示是否真的很容易?
在下面,我们将讲解如何使标签的背景透明。
有二种方法,你可以使用它来很标签的背景透明(其实有更多的方法可以做到这一点,但是我们只去谈论较为简单些的):1. 通过设置Panel的BackGroundImage属性,并且将标签Lable放到它的里面2. 将Lable的父窗体设置成PictureBox(label.Parent = pictureBox)
这样,我们将不需要编写任何的代码,并且我们可以在设计器里马上看到其透明的效果:
首先,拖一个Panel控件到窗体中,并将其BackgroundImage属性设置成一张你希望看到的图片来作为背景(你可以使用其BackgroundImageLayout来控制其排列的方式)。
最后,添加一个Lable标签,并将其BackColor属性设置成透明的(Web选项卡的第一个选项)。最终的结果应该是类似下面的图片:
这样,我们就可以将标签设成透明了,但图片仍然没有透明(上面的二张图片之间仍然没有实现相互透明)!不要担心,下面我们就来讨论它们透明的问题。
使用GDI+来绘制图片的透明度
使绘制的图像真正的透明有一点麻烦,因为我们不能使用默认的控件来配置.NET中的 Windows窗体。
对于更为复杂的图像和图形处理,我们可以使用GDI + ,它是一个图形设备接口(你可以在System.Drawing命名空间中找到它)。
我们会做的是建立一个通用的控件,我们就可以任意继承它并提取图片和文字了。这可以在本项目的源代码中看到,但如果你想了解它如何工作,请继续住下阅读。
绘制通用图像控件
首先,创建一个继承于Panel的新类,称其为DrawingArea 。这个类有一个抽象的OnDraw方法并且我们在子类中要对此方法进行重写,所以我们还需要将DrawingArea类声名为抽象类。
此外,我们还会添加一个Graphics图形对象来绘制图片。你应该像这样:
Code
using System;
using System.Drawing;
using System.Windows.Forms;
using System.Drawing.Drawing2D;
/**//// <summary>
///自定义绘制图形和文字的透明度
///继承DrawingArea和覆盖OnDraw方法。
/// </summary>
abstract public class DrawingArea : Panel
{
/**//// <summary>
/// 在OnDraw方法中使用此对象
/// </summary>
protected Graphics graphics;
/**//// <summary>
/// 在子类中应该要重写此方法
/// </summary>
abstract protected void OnDraw();
}
我们需要确保我们的控件背景透明度进行正确的处理。为此,我们需要重写CreateParams属性,以确保其风格与控件实例的正确(感谢Bob Powell的提示)。
Code
protected override CreateParams CreateParams
{
get
{
CreateParams cp = base.CreateParams;
cp.ExStyle |= 0x00000020; //WS_EX_TRANSPARENT
return cp;
}
}
现在,只有两件事情是必须的。
首先,我们必须确保背景不会被绘制出来。我们要做到这一点,
首先要重写OnPaintBackground方法。
第二件事是需重写OnPaint方法。这使我们能够确定程序在将我们的控制下进行绘制。
Code
protected override void OnPaintBackground(PaintEventArgs pevent)
{
// 不要绘制背景
}
protected override void OnPaint(PaintEventArgs e)
{
this.graphics = e.Graphics;
// 设置显示的效果质量属性
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;
OnDraw();
}
我还定义了一个DrawText方法以及一些变量,以便更容易的写文字。我在这里不进行讲解,但你可以在项目的源代码中找到它。
使用控制绘制图片和文字与透明
现在,我们如何使用这个控件吗?我们需要一个新的类来继承DrawingArea 。这是非常简单容易的事情。在这里,我提供了一个例子:
Code
class BroculosDrawing : DrawingArea
{
protected override void OnDraw()
{
// 获取资源
Image broculoImage = global::WindowsApplication1.Properties.Resources.broculo;
// 设置图片的属性
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));
// 绘制二张图片
this.graphics.DrawImage(broculoImage, big);
this.graphics.DrawImage(broculoImage, small);
// 设置文字的属性,并将其绘制出来
float fontSize = 8.25f;
Point textPosition = new Point(50, 100);
DrawText("http://www.broculos.net", "Microsoft Sans Serif", fontSize
, FontStyle.Underline, Brushes.Blue, textPosition);
}
}
这将使用两个图片和一些文字(类似于之前的) ,但现在是真正透明度!
我们可以像其它控件一样使用这个控件。对其进行编译,这个新的控件应该会出现在工具箱中。拖动它到新的窗体中!你便可以看到如下图所示的结果:
结论
现在你知道如何利用图像的透明度了吧。最大的缺点是它在.NET中内置的Windows窗体控件上不太容易使用。默认的控件在使用更先进的图像操作时是非常有限的,
所以我们使用GDI +来克服这一点。
应用这方面的知识并做更多一点的工作,应该有可能做出TransparentPictureBox 。希望它能给你带来帮助。