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

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

Winform窗体的透明

{callout color="#f0ad4e"}
此方法也需要.Net Framework 4.0及以上的版本才可以。
关键在于TransparencyKey指定和BackColor一样的颜色。窗体默认不支持背景透明设置,指定Color.Transparent无效。TransparencyKey不能取值Color.Black(黑色)。
{/callout}

两行代码就能实现Form窗体的(背景)透明效果,它不是Opacity属性的整个窗体的透明,而只是背景透明,加上去除边框和标题栏,就能实现很好的背景透明效果。

{callout color="#f0ad4e"}
// 透明窗体内的透明控件的背景图边缘 会有 BackColor 颜色的白边
this.BackColor = Color.LimeGreen;
this.TransparencyKey = Color.LimeGreen;
{/callout}

它会将Form窗体控件设置为透明背景的效果,非常棒。但是会有个小问题,就是透明Form上的透明控件上的图片或背景图片会有一个相应颜色的白边,这算是一个小瑕疵【可以设置窗体的BackColor/TransparencyKey颜色与原本控件上背景图片的颜色尽量一致,尽量避免多出的白边问题】,如下:
2126608824.png

【这个白边即使指定Color.Empty也无法解除】

目前测试,设置背景颜色和TransparencyKey不能取值Color.Black(黑色),它会导致窗体原本的拖动、标题栏中最大最小关闭按钮失效【如果是无边框,则此问题应当不算问题】。

BackColor = Color.Lime; // Color.Red\Color.Blue等
TransparencyKey = BackColor;

加上无边框窗体的效果:

FormBorderStyle = FormBorderStyle.None;

3098746758.png
理论上设置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;

演示效果如下:
3233915903.gif

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,指定透明样式,也可以实现透明。

{callout color="#f0ad4e"}
该效果只是实现了透明,控件本身、所占位置均存在,且鼠标不能透过操作底层显示出的控件。
{/callout}

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

4144676069.png

GDI+直接绘制图片或文字实现透明效果(可以针对多图片)

此部分参考自 How to Use Transparent Images and Labels in Windows Forms
2348753619.png
定义通用类
绘制图片和文字的通用类,直接继承自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?

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

取消
昵称表情代码图片

    暂无评论内容