Winform控件优化之背景透明那些事2:窗体背景透明、镂空穿透、SetStyle、GDI透明效果等

简介: 两行代码就能实现Form窗体的(背景)透明效果,它不是Opacity属性的整个窗体透明,`TransparencyKey`实现窗体的透明、窗体中间部分镂空效果...

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);
    }
}

参考

相关文章
|
Windows
Winform控件优化之背景透明那些事1:Button控件等背景透明
WinForm不支持真正的透明,其控件透明的实现都是背景颜色设置和对应位置的父控件背景相同。 Winform中控件的背景透明只有三种:Button控件的透明、其他控件的透明...
3654 0
Winform控件优化之背景透明那些事1:Button控件等背景透明
|
前端开发 API C#
C#使用外部字体、嵌入字体到程序资源中(Winform)及字体的版权问题
应用程序能够使用一个好的字体,是用户界面很重要的一部分,但是很多字体如果系统没有安装,则需要额外引入,这就涉及到极其重要的字体版权问题,及额外字体的使用和安装。最好的方式应该是将字体嵌入到程序中...
5554 1
C#使用外部字体、嵌入字体到程序资源中(Winform)及字体的版权问题
|
小程序 C#
C#WinForm实现Loading等待界面
上篇博客中解决了程序加载时屏幕闪烁的问题。 但是,加载的过程变得很缓慢。 这个给用户的体验也不是很好,我这里想加一个Loading的进度条。 项目启动的时候,加载进度条,界面UI加载完毕,进度条消失。
722 0
|
API C# Windows
Winform控件优化之无边框窗体及其拖动、调整大小和实现最大最小化关闭功能的自定义标题栏效果
Winform中实现无边框窗体只需要设置FormBorderStyle = FormBorderStyle.None,但是无边框下我们需要保留移动窗体、拖拽调整大小、自定义美观好看的标题栏等...
5098 0
Winform控件优化之无边框窗体及其拖动、调整大小和实现最大最小化关闭功能的自定义标题栏效果
|
C# 索引 Windows
Winform控件优化之TabControl控件的使用和常用功能
TabControl是一个分页切换(tab)控件,不同的页框内可以呈现不同的内容,将主要介绍调整tab的左右侧显示、设置多行tab、禁用或删除tabpage、隐藏TabControl头部的选项卡等
7563 0
Winform控件优化之TabControl控件的使用和常用功能
|
API 图形学
Winform控件优化之自定义控件的本质【从圆角控件看自定义的本质,Region区域无法反锯齿的问题】
自定义控件的本质只有两点:重绘控件Region区域(圆角、多边形、图片等),这是整个控件的真实范围;重绘图形,在原有Region范围内,重绘不同的图形(圆角、多边形、图片等)作为背景......
787 0
Winform控件优化之自定义控件的本质【从圆角控件看自定义的本质,Region区域无法反锯齿的问题】
|
C# 容器
Winform控件优化之TabControl控件的美化和功能扩展
在基本的TabControl控件使用和功能之上,可以尝试对其进行美化和功能扩展,比如动态删除或添加tab、绘制图标按钮及鼠标hover时的背景变化、Tab从右向左布局的优化处理等。最重要...
3710 0
Winform控件优化之TabControl控件的美化和功能扩展
|
算法 Windows
Winform控件优化之实现无锯齿的圆角窗体(或任意图形的无锯齿丝滑的窗体或控件)【借助LayeredWindow】
在一般能搜到的所有实现圆角窗体的示例中,都有着惨不忍睹的锯齿...而借助于Layered Windows,是可以实现丝滑无锯齿效果的Form窗体的,其具体原理就是分层窗体....
2210 0
Winform控件优化之实现无锯齿的圆角窗体(或任意图形的无锯齿丝滑的窗体或控件)【借助LayeredWindow】
|
API C# Windows
【C#】在winform中如何实现嵌入第三方软件窗体
【C#】在winform中如何实现嵌入第三方软件窗体
713 0
|
算法 API C#
Winform控件优化之圆角按钮【各种实现中的推荐做法】(下)
最终优化实现ButtonPro按钮(继承自Button),既提供Button原生功能,又提供扩展功能,除了圆角以外,还实现了圆形、圆角矩形的脚尖效果、边框大小和颜色、背景渐变颜色...
3470 0
Winform控件优化之圆角按钮【各种实现中的推荐做法】(下)