zl程序教程

您现在的位置是:首页 >  后端

当前栏目

c# winform不规则窗口实现(透明窗口)

c#Winform 实现 窗口 透明 不规则
2023-09-27 14:20:54 时间

一、前言

最近在搞c#的winform窗体应用,需要实现一个不规则窗口的效果。
比如形状如下的一个窗口
在这里插入图片描述

二、最终运行效果

在这里插入图片描述

三、分析

想要做一个不规则的窗口,那么标题栏要去掉;标题栏去掉了,窗口就不能移动了,所以我们还要实现窗口的移动逻辑,最后,窗口使用一张不规则形状的背景图,通过一个算法,判断各个像素的alpha值是否小于我们设定的alpha阈值,如果是,则把颜色过滤掉,这样就实现了透明效果了,也就实现了不规则形状的显示。

四、创建工程

好了,创建c# winform窗体应用工程,创建一个PictureBox控件,变量名为pictureBg,引用我们的图片
在这里插入图片描述

五、具体代码

代码如下,注释比较清晰,我就不啰嗦了。

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

namespace TestDemo
{
    public partial class Form1 : Form
    {
        private Point m_mousePos;
        private bool m_isMouseDown;

        public Form1()
        {
            InitializeComponent();

            //隐藏标题栏
            this.FormBorderStyle = FormBorderStyle.None;
            //窗口移动控制
            pictureBg.MouseDown += OnMouseDown;
            pictureBg.MouseUp += OnMouseUp;
            pictureBg.MouseMove += OnMouseMove;

            //背景图大小设置
            pictureBg.SizeMode = PictureBoxSizeMode.AutoSize;
            pictureBg.Parent = this;
            pictureBg.Location = new Point(0, 0);
            //背景图透明设置
            Bitmap img = (Bitmap)pictureBg.Image;
            var grapth = GetNoneTransparentRegion(img, 100);
            this.Region = new Region(grapth);
            this.BackgroundImage = pictureBg.Image;
            this.BackgroundImageLayout = ImageLayout.Zoom;
        }

        /// <summary>
        /// 鼠标按下,开启移动
        /// </summary>
        /// <param name="e"></param>
        protected void OnMouseDown(object sender, MouseEventArgs e)
        {
            m_mousePos = Cursor.Position;
            m_isMouseDown = true;
        }

        /// <summary>
        /// 鼠标抬起,关闭移动
        /// </summary>
        /// <param name="e"></param>
        protected void OnMouseUp(object sender, MouseEventArgs e)
        {
            m_isMouseDown = false;
            this.Focus();
        }

        /// <summary>
        /// 移动窗口
        /// </summary>
        /// <param name="e"></param>
        private void OnMouseMove(object sender, MouseEventArgs e)
        {
            if (m_isMouseDown)
            {
                Point tempPos = Cursor.Position;
                this.Location = new Point(Location.X + (tempPos.X - m_mousePos.X), Location.Y + (tempPos.Y - m_mousePos.Y));
                m_mousePos = Cursor.Position;
            }
        }

        /// 返回指定图片中的非透明区域;
        /// </summary>
        /// <param name="img">位图</param>
        /// <param name="alpha">alpha 小于等于该值的为透明</param>
        /// <returns></returns>
        public GraphicsPath GetNoneTransparentRegion(Bitmap img, byte alpha)
        {
            int height = img.Height;
            int width = img.Width;

            int xStart, xEnd;
            GraphicsPath grpPath = new GraphicsPath();
            for (int y = 0; y < height; y++)
            {
                //逐行扫描;
                for (int x = 0; x < width; x++)
                {
                    //略过连续透明的部分;
                    while (x < width && img.GetPixel(x, y).A <= alpha)
                    {
                        x++;
                    }
                    //不透明部分;
                    xStart = x;
                    while (x < width && img.GetPixel(x, y).A > alpha)
                    {
                        x++;
                    }
                    xEnd = x;
                    if (img.GetPixel(x - 1, y).A > alpha)
                    {
                        grpPath.AddRectangle(new Rectangle(xStart, y, xEnd - xStart, 1));
                    }
                }
            }
            return grpPath;
        }
    }
}