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

参考

相关文章
|
6月前
|
Python
wxPython StaticText控件背景色透明
wxPython StaticText控件背景色透明
129 0
|
Windows
Winform控件优化之背景透明那些事1:Button控件等背景透明
WinForm不支持真正的透明,其控件透明的实现都是背景颜色设置和对应位置的父控件背景相同。 Winform中控件的背景透明只有三种:Button控件的透明、其他控件的透明...
2922 0
Winform控件优化之背景透明那些事1:Button控件等背景透明
|
算法 Windows
Winform控件优化之实现无锯齿的圆角窗体(或任意图形的无锯齿丝滑的窗体或控件)【借助LayeredWindow】
在一般能搜到的所有实现圆角窗体的示例中,都有着惨不忍睹的锯齿...而借助于Layered Windows,是可以实现丝滑无锯齿效果的Form窗体的,其具体原理就是分层窗体....
1680 0
Winform控件优化之实现无锯齿的圆角窗体(或任意图形的无锯齿丝滑的窗体或控件)【借助LayeredWindow】
|
6月前
Winform使用PictureBox控件显示图片并且自适应
Winform使用PictureBox控件显示图片并且自适应
406 0
|
算法 API C#
Winform控件优化之圆角按钮【各种实现中的推荐做法】(下)
最终优化实现ButtonPro按钮(继承自Button),既提供Button原生功能,又提供扩展功能,除了圆角以外,还实现了圆形、圆角矩形的脚尖效果、边框大小和颜色、背景渐变颜色...
1966 0
Winform控件优化之圆角按钮【各种实现中的推荐做法】(下)
WPF控件和窗体一起放大一起缩小
WPF控件和窗体一起放大一起缩小
238 0
|
C# 图形学 Windows
Winform控件优化之圆角按钮【各种实现中的推荐做法】(上)
Windows 11下所有控件已经默认采用圆角,其效果更好、相对有着更好的优化...尝试介绍很常见的圆角效果,通过重写控件的OnPaint方法实现绘制,并在后面进一步探索对应的优化和可能的问题
1423 0
Winform控件优化之圆角按钮【各种实现中的推荐做法】(上)
|
C#
WPF 创建无边框的圆角窗口
原文:WPF 创建无边框的圆角窗口 如题所述,在WPF中要创建一个没有边框且为圆角的窗体,有如下几步工作要进行: 第一步:去掉窗体默认样式的边框 首先将窗体的背景设为透明,将允许透明的属性设置为True,...
2704 0
|
C++
duilib corner属性的贴图技巧——让图片自动贴到控件的的某一边或者一角并自适应控件的大小
转载请说明原出处,谢谢~~          Duilib给控件贴图功能可以附带多个属性,各个属性的配合可以达到许多效果。以下是duilib支持的所有贴图属性: 贴图描述:          Duilib的表现力丰富很大程度上得益于贴图描述的简单强大。
1813 0
QT应用编程: 半透明遮罩窗口实现
QT应用编程: 半透明遮罩窗口实现
534 0
QT应用编程: 半透明遮罩窗口实现