关于透明、半透明winform的实现

本文介绍了如何在WinForm应用中实现透明和半透明效果。通过设置窗体背景为截图并实时更新,达到透明视觉效果。在窗口拖动和尺寸变化时,采取策略以避免频繁截图,减少资源占用。若不需要蒙版,移除Panel即可。

前两个月由于项目需要,要求做一个半透明窗体,翻阅了很多网站都不尽人意,在吸取了众家之长后,终于得到了比较满意的答案,效果图如下


直接上代码

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace TransparentWindow
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load( object sender, EventArgs e )
        {
            SetBackgroundImageTransparent();
        }
        private Color tr_color = Color.Transparent;
        private bool b_start = false;
        bool[] b_visible = null;
        private void SetBackgroundImageTransparent()
        {
            Point pt = this.PointToScreen( new Point( 0, 0 ) );
            Bitmap b = new Bitmap( this.Width, this.Height );
            using( Graphics g = Graphics.FromImage( b ) )
            {
                g.CopyFromScreen( pt, new Point(), new Size( this.Width, this.Height ) );                
            }
            
            this.BackgroundImage = b;

            
        }
        private void BeginSet()
        {
            tr_color = this.TransparencyKey;
            b_start = true;
        }
        private void Setting()
        {
            if( b_start )
            {
                b_visible = new bool[Controls.Count];
                for( int i = 0; i < Controls.Count; i++ )
                {
                    b_visible[i] = Controls[i].Visible;
                    Controls[i].Visible = false;
                }
                BackgroundImage = null;
                BackColor = Color.White;
                b_start = false;
                this.TransparencyKey = Color.White;
            }
        }
        private void EndSet()
        {
            SetBackgroundImageTransparent();
            this.TransparencyKey = tr_color;
            for( int i = 0; i < Controls.Count; i++ )
            {
                Controls[i].Visible = b_visible[i];
            }
            b_start = false;
        }

        private void textBox1_TextChanged( object sender, EventArgs e )
        {
            textBox1.SelectionStart = textBox1.Text.Length;
            textBox1.ScrollToCaret();
        }


        private void Form1_Resize( object sender, EventArgs e )
        {
            Setting();

            textBox1.Text += "Form1_Resize" + Environment.NewLine;
        }

        private void Form1_ResizeBegin( object sender, EventArgs e )
        {
            BeginSet();
            textBox1.Text += "Form1_ResizeBegin" + Environment.NewLine;
        }

        private void Form1_ResizeEnd( object sender, EventArgs e )
        {
            textBox1.Text += "Form1_ResizeEnd" + Environment.NewLine;
            EndSet();
            
            
        }

        private void Form1_SizeChanged( object sender, EventArgs e )
        {
            textBox1.Text += "Form1_SizeChanged" + Environment.NewLine;
        }

        private void Form1_Move( object sender, EventArgs e )
        {
            Setting();
            textBox1.Text += "Form1_Move" + Environment.NewLine;
        }


        private void button1_Click( object sender, EventArgs e )
        {
            textBox1.Clear();
        }

        private void button2_Click( object sender, EventArgs e )
        {
            this.Size = new Size( this.Size.Width + 1, this.Size.Height + 1 );
        }

        private void Form1_MouseMove( object sender, MouseEventArgs e )
        {
            
        }

        
 
    }
}


窗体设计代码比较简单,一个panel以dock为fill铺在窗体上,然后是控件在panel上,panel的背景是一个png图片,背景色为透明

主要代码就是SetBackgroundImageTransparent,里面的代码更是简单,就是一个截图,把截图当成窗体的背景图片,这样就使得窗体看起来“透明”了,由于是截图,所以要添加额外的代码来保证截图的实时性,首先在改变前保护现场(beginset),在拖动时、改变大小时为了防止截图过于频繁,资源占用过多,保持了真透明,在拖动结束、改变大小结束时重新截图,还原现场(endset),更新背景图片

如果不要蒙板,把panel去掉即可,

希望对大家有所帮助





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值