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

参考

相关文章
|
3月前
|
Python
wxPython StaticText控件背景色透明
wxPython StaticText控件背景色透明
26 0
|
Windows
Winform控件优化之背景透明那些事1:Button控件等背景透明
WinForm不支持真正的透明,其控件透明的实现都是背景颜色设置和对应位置的父控件背景相同。 Winform中控件的背景透明只有三种:Button控件的透明、其他控件的透明...
2453 0
Winform控件优化之背景透明那些事1:Button控件等背景透明
|
算法 Windows
Winform控件优化之实现无锯齿的圆角窗体(或任意图形的无锯齿丝滑的窗体或控件)【借助LayeredWindow】
在一般能搜到的所有实现圆角窗体的示例中,都有着惨不忍睹的锯齿...而借助于Layered Windows,是可以实现丝滑无锯齿效果的Form窗体的,其具体原理就是分层窗体....
960 0
Winform控件优化之实现无锯齿的圆角窗体(或任意图形的无锯齿丝滑的窗体或控件)【借助LayeredWindow】
|
1月前
Winform使用PictureBox控件显示图片并且自适应
Winform使用PictureBox控件显示图片并且自适应
34 0
|
9月前
|
C#
WPF控件和窗体一起放大一起缩小
WPF控件和窗体一起放大一起缩小
182 0
|
算法 API C#
Winform控件优化之圆角按钮【各种实现中的推荐做法】(下)
最终优化实现ButtonPro按钮(继承自Button),既提供Button原生功能,又提供扩展功能,除了圆角以外,还实现了圆形、圆角矩形的脚尖效果、边框大小和颜色、背景渐变颜色...
1203 0
Winform控件优化之圆角按钮【各种实现中的推荐做法】(下)
|
10月前
|
C# 数据安全/隐私保护
ApeForms | C# WinForm窗体控件平滑减速运动
在桌面软件开发中,有时会需要控制窗体或控件移动以实现某些界面效果,比如幻灯片换页、侧面的展开栏等。 通常情况下我们会使用Timer以每隔一段时间修改一下坐标位置的方式来实现目标对象的位移效果,但通过这个方式实现的动效存在几个问题: 匀速运动效果生硬; 运动过程中不便灵活改变运动状态(如侧栏展开一半时令其收起); 动效多时需要创建多个Timer对象,不易管理且占用资源; ApeForms中为控件和窗体提供了平滑运动的扩展方法,很好的解决了这些问题。不仅是坐标的平滑运动,还有控件\窗体尺寸的平滑变化、透明度的平滑变化。允许在变化的中途随时更改目标坐标\尺寸\透明度,且使用共享的Timer
11248 1
ApeForms | C# WinForm窗体控件平滑减速运动
|
C# 图形学 Windows
Winform控件优化之圆角按钮【各种实现中的推荐做法】(上)
Windows 11下所有控件已经默认采用圆角,其效果更好、相对有着更好的优化...尝试介绍很常见的圆角效果,通过重写控件的OnPaint方法实现绘制,并在后面进一步探索对应的优化和可能的问题
969 0
Winform控件优化之圆角按钮【各种实现中的推荐做法】(上)
|
C#
WPF 创建无边框的圆角窗口
原文:WPF 创建无边框的圆角窗口 如题所述,在WPF中要创建一个没有边框且为圆角的窗体,有如下几步工作要进行: 第一步:去掉窗体默认样式的边框 首先将窗体的背景设为透明,将允许透明的属性设置为True,...
2561 0
|
C#
WPF透明窗体制作
原文:WPF透明窗体制作 窗体的样式: 其中Border用来实现透明效果,Grid用来呈现窗体内的控件,为了避免窗体内的控件变成透明的,所以Border,Grid必须处在同一级别上。
857 0