在开发.NET Compact Framework应用程序时,经常需要在表单背景上添加图像。然而,标准的标签控件和其他控件并不支持透明背景。为了解决这个问题,需要创建自定义的用户控件。本文将介绍如何实现这一功能。
在最近的一个.NET Compact Framework项目中,需要在表单背景上添加一张图片。通过观看微软的视频教程实现了这一点。但是,视频也告诉.NET Compact Framework中的标签控件不支持透明背景。因此,需要创建自己的用户控件。找到了一篇很好的文章,由Per Ola Sæther撰写的《在.NET Compact Framework中创建具有透明标签的渐变背景》,它帮助找到了解决方案。
创建透明控件的基本思想是重写控件的OnPaintBackgound方法,使其调用父表单的OnPaintBackgound来绘制背景,然后在其上绘制控件的内容。
首先,创建了与文章中介绍的相同的接口。
public interface IPaintControl
{
void InvokePaintBackground(PaintEventArgs e);
}
然后,创建了一个基表单,这样就不必为每个表单编写相同的代码。
public class CcForm : Form, IPaintControl
{
public virtual void InvokePaintBackground(PaintEventArgs e)
{
OnPaintBackground(e);
}
}
创建一个基控件,这样不仅可以有透明标签,还可以有其他类型的控件,如单选按钮和复选框。它有一个名为TransparentBackground的属性。如果出于某种原因不希望控件透明,可以更改此属性。在OnPaintBackground方法中,它调用其父级的InvokePaintBackground来绘制背景。
public class CcTransparentControl : Control
{
private bool _transparentBackgound = true;
public bool TransparentBackground
{
get { return _transparentBackgound; }
set { _transparentBackgound = value; }
}
protected override void OnPaintBackground(PaintEventArgs e)
{
if (_transparentBackgound)
{
IPaintControl parent = Parent as IPaintControl;
if (parent != null)
{
parent.InvokePaintBackground(e);
}
}
else
{
base.OnPaintBackground(e);
}
}
}
现在可以使用以下代码创建透明标签控件:
public class CcTransparentLabel : CcTransparentControl
{
private ContentAlignment textAlign = ContentAlignment.TopLeft;
public ContentAlignment TextAlign
{
get { return textAlign; }
set { textAlign = value; }
}
public CcTransparentLabel()
{
}
protected override void OnPaint(PaintEventArgs e)
{
Graphics gfx = e.Graphics;
if (this.TextAlign == ContentAlignment.TopLeft)
{
gfx.DrawString(this.Text, this.Font, new SolidBrush(this.ForeColor), ClientRectangle);
}
else if (this.TextAlign == ContentAlignment.TopCenter)
{
SizeF size = gfx.MeasureString(this.Text, this.Font);
int left = this.Width / 2 - (int)size.Width / 2;
var rect = new Rectangle(ClientRectangle.Left + left, ClientRectangle.Top, (int)size.Width, ClientRectangle.Height);
gfx.DrawString(this.Text, this.Font, new SolidBrush(this.ForeColor), rect);
}
else if (this.TextAlign == ContentAlignment.TopRight)
{
SizeF size = gfx.MeasureString(this.Text, this.Font);
int left = this.Width - (int)size.Width + this.Left;
var rect = new Rectangle(ClientRectangle.Left + left, ClientRectangle.Top, (int)size.Width, ClientRectangle.Height);
gfx.DrawString(this.Text, this.Font, new SolidBrush(this.ForeColor), rect);
}
}
}
在表单中,将表单更改为继承自CcForm,并将CcTransparentLabel拖放到其中。
public partial class FormWithSolidColorBackground : CcForm
以下是屏幕截图。如所见,标签现在具有透明背景。
然而,当尝试添加具有渐变颜色的图像背景时,标签看起来不再正确。要了解问题,首先需要看看如何在表单上显示背景图像。
public partial class FormWithImageBackground : CcForm
{
private Rectangle _backgroundRect;
private Bitmap _background;
private string currentPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().GetName().CodeBase.ToString());
public FormWithImageBackground()
{
InitializeComponent();
_background = new Bitmap(currentPath + @"\ImageBackground.jpg");
_backgroundRect = new Rectangle(0, 0, _background.Width, _background.Height);
}
protected override void OnPaintBackground(PaintEventArgs e)
{
Graphics g = e.Graphics;
g.DrawImage(_background, this.ClientRectangle, _backgroundRect, GraphicsUnit.Pixel);
}
}
发生的情况是,当透明标签控件调用OnPaintBackground时,它会在标签控件内重新绘制图像。因此,它在标签的背景上显示了图像的左上角。为了解决这个问题,将标签控件的位置传递给表单,并使用它来重新绘制图像。例如,如果标签位于(10, 20),则图像背景将在(-10, -20)处显示。这可能不是最好的解决方案,但它简单且有效。以下是修订后的接口和控件。
public interface IPaintControl
{
void InvokePaintBackground(PaintEventArgs e, Point location);
}
public class CcForm : Form, IPaintControl
{
public virtual void InvokePaintBackground(PaintEventArgs e, Point location)
{
OnPaintBackground(e);
}
}
public class CcTransparentControl : Control
{
....
protected override void OnPaintBackground(PaintEventArgs e)
{
if (_transparentBackgound)
{
IPaintControl parent = Parent as IPaintControl;
if (parent != null)
{
parent.InvokePaintBackground(e, this.Location);
}
}
else
{
base.OnPaintBackground(e);
}
}
}
在表单中,然后覆盖InvokePaintBackground方法以在所需位置绘制图像。
public override void InvokePaintBackground(System.Windows.Forms.PaintEventArgs e, System.Drawing.Point location)
{
Graphics g = e.Graphics;
Rectangle destRect = new Rectangle(-1 * location.X, -1 * location.Y, ClientRectangle.Width, ClientRectangle.Height);
g.DrawImage(_background, destRect, _backgroundRect, GraphicsUnit.Pixel);
}
现在有了一个图像背景上的透明标签。
还创建了透明的单选按钮和复选框控件。这些是表单中常用的控件,Panel控件也是如此。以下示例显示了透明单选按钮和复选框在透明面板上的效果。
祝编程愉快!