精通
英语
和
开源
,
擅长
开发
与
培训
,
胸怀四海
第一信赖
.NET Compact Framework doesn't provide out-of-box controls with transparent background. This article shows how to create user controls to overcome this issue..NET Compact Framework不提供具有透明背景的现成控件。本文介绍了如何创建用户控件来克服此问题。
注:作者的代码移植也不麻烦,代码在codeproject上有,如果遇到问题请联系我。
In a recent .NET compact framework application I was working on, I needed to add an image to the form's background. I did it by using the code from this video tutorial from Microsoft. However, the video also told us that the label control (and other controls) in .NET compact framework doesn't support transparent background. You will have to create your own user control. I found a good article Creating gradient background with transparent labels in .NET Compact Framework by Per Ola Sæther. It helped me to create my solution.在我正在开发的最新.NET Compact Framework应用程序中,我需要向窗体背景添加图像。我是通过使用Microsoft提供的该视频教程中的代码来实现的。但是,该视频还告诉我们,.NET Compact Framework中的标签控件(和其他控件)不支持透明背景。您将必须创建自己的用户控件。我在 Per OlaSæther的.NET Compact Framework中找到了一篇很好的文章,用透明标签创建渐变背景。它帮助我创建了解决方案。
The basic ideas to create a transparent control is to override the OnPaintBackgound method of the control so it calls the parent form's OnPaintBackgound to draw the background and then draw content of the control on top of it.
In that article, the author showed how to create a transparent label control. But the code can be simplified. I also did some refactoring work so it extends to not just label control.
First, I created the same interface introduced in that article.创建透明控件的基本思想是重写控件的OnPaintBackgound 方法,以便它调用父窗体OnPaintBackgound来绘制背景,然后在其顶部绘制控件的内容。
在那篇文章中,作者展示了如何创建透明标签控件。但是代码可以简化。我还做了一些重构工作,所以它不仅扩展到标签控件。
首先,我创建了与该文章中介绍的相同的界面。
public interface IPaintControl
{
// have the background painted
void InvokePaintBackground(PaintEventArgs e);
}
Then I created a base form so I don't have to write the same code for each form.然后,我创建了一个基本窗体,因此不必为每个窗体编写相同的代码。
public class CcForm : Form, IPaintControl
{
public virtual void InvokePaintBackground(PaintEventArgs e)
{
OnPaintBackground(e);
}
}
A base control is created so we can have not only the transparent label, but also other kinds of controls, such as radio button and checkbox. It has a property called TransparentBackground. If you don't want your control to be transparent for some reason, you can change this property. In the OnPaintBackground method, it calls its parent’s InvokePaintBackground to draw the background.创建了一个基本控件,因此我们不仅可以使用透明标签,还可以使用其他类型的控件,例如单选按钮和复选框。它具有称为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);
}
}
Now we can create the transparent label control using the following code:现在,我们可以使用以下代码创建透明标签控件:
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);
}
}
}
In our form, we change the form to inherit from CcForm and drag/drop a CcTransparentLabel onto it.在我们的窗体中,我们更改了要继承的窗体CcForm 并将其拖放到该窗体CcTransparentLabel 上。
public partial class FormWithSolidColorBackground : CcForm
Here is the screen shot. As you can see, the label has transparent background now.这是屏幕截图。如您所见,标签现在具有透明背景。
However, when I tried to add image background with gradient color, my label doesn't look right anymore.但是,当我尝试使用渐变色添加图像背景时,我的标签看起来不再正确。
To understand the issue, we need to first take a look at how we display background image on a form.要理解该问题,我们首先需要看一下如何在表单上显示背景图像
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);
}
}
What happened is when the OnPaintBackground was called by the transparent label control, it re-draws the image inside of the label control. So it shows the top-left corner of the image on the label’s background. To fix this issue, I pass in the location of the label control to the form and use it to re-draw the image. For example, if the label is located at (10, 20), the image background would be displayed at (-10, –20). This may not be the best solution, but it is simple and it worked. Here is the revised interface and controls.发生的事情是当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);
}
}
In the form, I then override the InvokePaintBackground method to draw the image at the desired location.在窗体中,然后重写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);
}
Now we have a transparent label over image background.现在,我们在图像背景上有了一个透明标签。
I also created a transparent radio button and checkbox controls. These are the controls commonly used in a form and so is the Panel control. The following example showed the transparent radio button and checkbox on a transparent panel.我还创建了一个透明的单选按钮和复选框控件。这些是表单中常用的控件,控件也是如此Panel 。以下示例显示了透明面板上的透明单选按钮和复选框。