Winform窗体的透明
此方法也需要.Net Framework 4.0及以上的版本才可以。关键在于
TransparencyKey
指定和BackColor
一样的颜色。窗体默认不支持背景透明设置,指定Color.Transparent
无效。TransparencyKey
不能取值Color.Black
(黑色)。
两行代码就能实现Form窗体的(背景)透明效果,它不是Opacity
属性的整个窗体的透明,而只是背景透明,加上去除边框和标题栏,就能实现很好的背景透明效果。
// 透明窗体内的透明控件的背景图边缘 会有 BackColor 颜色的白边
this.BackColor = Color.LimeGreen;
this.TransparencyKey = Color.LimeGreen;
它会将Form窗体控件设置为透明背景的效果,非常棒。但是会有个小问题,就是透明Form上的透明控件上的图片或背景图片会有一个相应颜色的白边,这算是一个小瑕疵【可以设置窗体的BackColor/TransparencyKey
颜色与原本控件上背景图片的颜色尽量一致,尽量避免多出的白边问题】,如下:
【这个白边即使指定Color.Empty
也无法解除】
目前测试,设置背景颜色和TransparencyKey
不能取值Color.Black
(黑色),它会导致窗体原本的拖动、标题栏中最大最小关闭按钮失效【如果是无边框,则此问题应当不算问题】。
BackColor = Color.Lime; // Color.Red\Color.Blue等
TransparencyKey = BackColor;
加上无边框窗体的效果:
FormBorderStyle = FormBorderStyle.None;
理论上设置
SupportsTransparentBackColor
支持背景透明就可以,但实际无效(猜测,应该是因为主窗体没有父控件的原因,需要有父控件才能生效。不知添加CreateParams
的透明设置是否有效)//// 无效 SetStyle(ControlStyles.UserPaint, true); SetStyle(ControlStyles.OptimizedDoubleBuffer, true); SetStyle(ControlStyles.SupportsTransparentBackColor, true); this.BackColor = Color.Transparent; this.TransparencyKey = BackColor;
永远显示在窗口最前方,可鼠标穿透的窗体镂空效果
通过设置TransparencyKey
实现窗体的透明、窗体中间部分镂空,鼠标等可以透过并从透过的部分操作。
在一些录屏软件中会需要这种效果,整个窗体镂空部分框选的是录屏的区域,调整区域大小进行适当录屏范围,比如GifCam
录屏软件。
TopLevel
设置Form为顶层窗体,TopMost
设置Form始终在最前面。
TopLevel=true;
TopMost=true;
BackColor = Color.Empty;
TransparencyKey = BackColor;
演示效果如下:
TextBox控件的透明
TextBox和Form一样,默认不支持设置透明背景色:textBox1.BackColor = Color.Transparent;
会发生异常,控件不支持透明的背景色。
通过SetStyle
设置支持背景透明。
不过TextBox透明也没啥意义,因为透明后看不见文字编辑区域了。
public class TransparentTextBox : TextBox
{
public TransparentTextBox()
{
SetStyle(ControlStyles.SupportsTransparentBackColor |
ControlStyles.OptimizedDoubleBuffer |
ControlStyles.AllPaintingInWmPaint |
ControlStyles.ResizeRedraw |
ControlStyles.UserPaint, true);
BackColor = Color.Transparent;
}
}
背景的不完全透明
BackColor = Transparent
等实现的都是完全透明,要实现不完全透明,在“完全透明”的基础上,设置BackgroundImage为一张带有百分比透明度的图片。通过图片的透明度,来间接设置控件的透明度
CreateParams
实现控件透明的设置
在继承控件时,通过重写CreateParams,指定透明样式,也可以实现透明。
该效果只是实现了透明,控件本身、所占位置均存在,且鼠标不能透过操作底层显示出的控件。
如下,透明的Panel控件:
/// <summary>
/// A transparent control.
/// </summary>
public class TransparentPanel : Panel
{
protected override CreateParams CreateParams
{
get
{
CreateParams createParams = base.CreateParams;
createParams.ExStyle |= 0x00000020; // WS_EX_TRANSPARENT
return createParams;
}
}
}
GDI+直接绘制图片或文字实现透明效果(可以针对多图片)
此部分参考自 How to Use Transparent Images and Labels in Windows Forms
- 定义通用类
绘制图片和文字的通用类,直接继承自Panel,包含抽象方法OnDraw和用于绘制的Graphics对象
using System;
using System.Drawing;
using System.Windows.Forms;
using System.Drawing.Drawing2D;
/// <span class="code-SummaryComment"><summary></span>
/// Use this for drawing custom graphics and text with transparency.
/// Inherit from DrawingArea and override the OnDraw method.
/// <span class="code-SummaryComment"></summary></span>
abstract public class DrawingArea : Panel
{
/// <span class="code-SummaryComment"><summary></span>
/// Drawing surface where graphics should be drawn.
/// Use this member in the OnDraw method.
/// <span class="code-SummaryComment"></summary></span>
protected Graphics graphics;
/// <span class="code-SummaryComment"><summary></span>
/// Override this method in subclasses for drawing purposes.
/// <span class="code-SummaryComment"></summary></span>
abstract protected void OnDraw();
}
重写CreateParams
属性,确保控件实例化时有正确的样式
protected override CreateParams CreateParams
{
get
{
CreateParams cp = base.CreateParams;
cp.ExStyle |= 0x00000020; //WS_EX_TRANSPARENT
return cp;
}
}
确保背景不会绘制,需要重写OnPaintBackground
方法,并且不进行任何操作;重写OnPaint
方法,用于空间绘制自己时调用此处理
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();
}
同时定义一个DrawText方法,用于很方便的绘制文本
#region DrawText helper functions
protected void DrawText(string text, Point position)
{
DrawingArea.DrawText(this.graphics, text, "Microsoft Sans Serif", 8.25f
, FontStyle.Regular, Brushes.Black, position);
}
protected void DrawText(string text, Brush color, Point position)
{
DrawingArea.DrawText(this.graphics, text, "Microsoft Sans Serif", 8.25f
, FontStyle.Regular, color, position);
}
protected void DrawText(string text, FontStyle style, Point position)
{
DrawingArea.DrawText(this.graphics, text, "Microsoft Sans Serif", 8.25f
, style, Brushes.Black, position);
}
protected void DrawText(string text, FontStyle style, Brush color, Point position)
{
DrawingArea.DrawText(this.graphics, text, "Microsoft Sans Serif", 8.25f
, style, color, position);
}
protected void DrawText(string text, float fontSize, FontStyle style, Brush color
, Point position)
{
DrawingArea.DrawText(this.graphics, text, "Microsoft Sans Serif", fontSize
, style, color, position);
}
protected void DrawText(string text, string fontFamily, float fontSize
, FontStyle style, Brush color, Point position)
{
DrawingArea.DrawText(this.graphics, text, fontFamily, fontSize, style, color, position);
}
static public void DrawText(Graphics graphics, string text, string fontFamily
, float fontSize, FontStyle style, Brush color, Point position)
{
Font font = new Font(fontFamily, fontSize, style);
SizeF textSizeF = graphics.MeasureString(text, font);
int width = (int)Math.Ceiling(textSizeF.Width);
int height = (int)Math.Ceiling(textSizeF.Height);
Size textSize = new Size(width, height);
Rectangle rectangle = new Rectangle(position, textSize);
graphics.DrawString(text, font, color, rectangle);
}
#endregion
- 使用控件绘制带透明的图片和文本
添加一个新类并继承自DrawingArea,在重写的OnDraw
方法中实现对图片和文本的绘制
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);
}
}
参考
- How to: Give Your Control a Transparent Background
- C# Windows Form Application Transparent button
- Transparent background on winforms?
- 利用
Graphics.CopyFromScreen
实现截图背景图片的方法,How to do a background for a label will be without color? 中有介绍,理论上处理逻辑是没问题的,但是不知为何测试效果并不理想,无法实现透明下面的内容。同样C# Winform 变相实现背景透明中介绍截取父控件背景,但是代码执行会报错超出内存。。。,无法实际执行。 - 另 Making a control transparent给出了一个透明的控件,可了解下
- 关于图片和控件重叠时无法正确透明底层的问题,C# Winform控件对透明图片重叠时的解决方法、C# Winform控件贴透明png图片遇到的问题有介绍,但似乎不好用。。
- 在设置透明度后,加载窗体可能会出现界面加载慢且闪烁问题。解决方案可参考 panel设置背景透明后,窗体大小改变时,界面闪烁
- 推荐一篇文章 Transparent Controls in .NETCF