65.9K
CodeProject 正在变化。 阅读更多。
Home

在 .NET Compact Framework 中创建透明控件

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.32/5 (10投票s)

2009年10月9日

CPOL

3分钟阅读

viewsIcon

102638

downloadIcon

3469

本文介绍了如何在 .NET Compact Framework 中创建透明控件

引言

.NET Compact Framework 不提供具有透明背景的现成控件。本文介绍了如何创建用户控件来克服这个问题。

背景

在我最近正在开发的 .NET Compact Framework 应用程序中,我需要在窗体的背景中添加图像。我使用了这个视频教程中的代码。但是,该视频还告诉我们,.NET Compact Framework 中的标签控件(和其他控件)不支持透明背景。您必须创建自己的用户控件。我找到了 Per Ola Sæther 的一篇很好的文章在 .NET Compact Framework 中创建具有透明标签的渐变背景。它帮助我创建了我的解决方案。

Using the Code

创建透明控件的基本思想是覆盖控件的 OnPaintBackgound 方法,使其调用父窗体的 OnPaintBackgound 来绘制背景,然后在上面绘制控件的内容。

在那篇文章中,作者展示了如何创建一个透明标签控件。但是代码可以简化。我还做了一些重构工作,因此它可以扩展到不仅仅是标签控件。

首先,我创建了那篇文章中介绍的相同接口。

public interface IPaintControl
{
    // have the background painted
    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
{
    // have the background painted
    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 控件也是如此。以下示例显示了透明面板上的透明单选按钮和复选框。

编程愉快!

历史

  • 2009 年 10 月 8 日:首次发布
  • 2009 年 10 月 9 日:文章已更新
© . All rights reserved.